config.el 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. (add-to-list 'default-frame-alist '(inhibit-double-buffering . t))
  2. (setq user-full-name "Colin Powell"
  3. user-mail-address "colin@unbl.ink")
  4. (setq doom-font (font-spec :family "FuraCode Nerd Font Mono" :size 12))
  5. (setq doom-big-font (font-spec :family "FuraCode Nerd Font Mono" :size 17))
  6. (setq doom-theme 'doom-monokai-spectrum)
  7. ;; Applies to current frame
  8. (set-frame-parameter nil 'internal-border-width 20) ; applies to the current frame
  9. ;; If we create new frames (via emacsclient) this will do the trick
  10. (add-to-list 'default-frame-alist '(internal-border-width . 20))
  11. ;; Dash highlighting
  12. (after! dash (dash-enable-font-lock))
  13. ;; Dash highlighting
  14. (after! dash (dash-enable-font-lock))
  15. (map! ;; Easier window movement
  16. :n "C-h" 'evil-window-left
  17. :n "C-j" 'evil-window-down
  18. :n "C-k" 'evil-window-up
  19. :n "C-l" 'evil-window-right
  20. (:map evil-treemacs-state-map
  21. "C-h" 'evil-window-left
  22. "C-l" 'evil-window-right)
  23. :leader
  24. (:prefix "f"
  25. :desc "Find file in dotfiles" "t" #'+hlissner/find-in-dotfiles
  26. :desc "Browse dotfiles" "T" #'+hlissner/browse-dotfiles)
  27. (:prefix "t"
  28. :desc "Switch themes" "t" #'load-theme)
  29. (:prefix "o"
  30. :desc "Elfeed feed reader" "f" #'elfeed
  31. :desc "Hckrnews" "h" #'hackernews
  32. :desc "Lobste.rs" "l" #'ivy-lobsters)
  33. (:prefix "b"
  34. :desc "Black format buffer" "f" #'blacken-buffer
  35. :desc "isort buffer" "I" #'py-isort-buffer
  36. :desc "Links in buffer" "l" #'ace-link-org)
  37. (:prefix "s"
  38. :desc "Search project TODOs" "t" #'+ivy/tasks
  39. :desc "Search the web" "w" #'web-search
  40. :desc "Goto URL in eww" "u" #'eww-browse-url
  41. :desc "Search in eww" "3" #'eww-search-words
  42. :desc "Search all the things" "g" #'deadgrep))
  43. (setq wttrin-default-cities '("Castine, ME" "San Francisco" "Thessaloniki"))
  44. (setq wttrin-default-accept-language '("Accept-Language" . "en-US"))
  45. (map!
  46. (:leader
  47. (:prefix "o"
  48. :desc "Weather" "w" #'wttrin)))
  49. ;; app/search
  50. (after! web-search
  51. (push '("Searx" "http://search.unbl.ink/?q=%s")
  52. web-search-providers)
  53. (setq web-search-default-provider "Searx"))
  54. ;; app/eglot
  55. ;; Back to eglot ...
  56. (add-hook 'foo-mode-hook 'eglot-ensure)
  57. (setq libmpdel-hostname "mpd.unbl.ink")
  58. (defun mpdel-playlist-play ()
  59. "Start playing the song at point."
  60. (interactive)
  61. (if (derived-mode-p 'mpdel-playlist-current-playlist-mode)
  62. (libmpdel-play-song (navigel-entity-at-point))
  63. (mpdel-core-insert-current-playlist)))
  64. (map! :leader
  65. (:prefix "-"
  66. :desc "MPD Open playlist" "-" #'mpdel-playlist-open
  67. :desc "MPD Remove at point" "d" #'mpdel-playlist-delete
  68. :desc "MPD Start at point" "s" #'mpdel-playlist-play
  69. :desc "MPD Next track" "n" #'libmpdel-playback-next
  70. :desc "MPD Previous track" "p" #'libmpdel-playback-previous))
  71. (add-hook! 'elfeed-show-mode-hook (text-scale-set 1.5))
  72. (setq rmh-elfeed-org-files (list "~/org/elfeed.org"))
  73. (setq elfeed-search-filter "@2-days-ago +unread")
  74. (defun elfeed-search-format-date (date)
  75. (format-time-string "%Y-%m-%d %H:%M" (seconds-to-time date)))
  76. ; crontab-like elfeed updating
  77. (run-with-timer 0 (* 30 60) 'elfeed-update)
  78. (setq httpd-host "0.0.0.0")
  79. (setq httpd-port 10000)
  80. (map! :leader
  81. (:prefix "r" ; For (m)essaging
  82. :desc "Open Elfeed" "o" #'elfeed
  83. :desc "Update Elfeed" "u" #'elfeed-update))
  84. (add-hook 'prog-mode-hook #'goto-address-mode) ;; Linkify links!
  85. ;;; It is the opposite of fill-paragraph
  86. (defun unfill-paragraph ()
  87. "Takes a multi-line paragraph and makes it into a single line of text."
  88. (interactive)
  89. (let ((fill-column (point-max)))
  90. (fill-paragraph nil)))
  91. ;; Handy key definition
  92. (define-key global-map "\M-z" 'unfill-paragraph)
  93. ;; A rainbow cat, why not?
  94. (nyan-mode)
  95. ;; Show the cursor when we make jumps, I'm too old for this shit.
  96. (beacon-mode)
  97. ;; Emojis, fuck me.
  98. (add-hook 'after-init-hook #'global-emojify-mode)
  99. ;; PlantUML is awesome for quick diagrams
  100. (add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
  101. ;; Timezone location strings at http://worldtime.io
  102. (setq display-time-world-list '(("America/Los_Angeles" "San Francisco")
  103. ("America/Tegucigalpa" "Tegucigalpa")
  104. ("America/New_York" "New York")
  105. ("Europe/London" "London")
  106. ("Europe/Warsaw" "Warsaw")
  107. ("Europe/Kiev" "Lviv")))
  108. (setq +workspaces-switch-project-function #'ignore
  109. +format-on-save-enabled-modes '(python-mode)
  110. +pretty-code-enabled-modes '(emacs-lisp-mode org-mode))
  111. ;; tools/deft
  112. (setq deft-extensions '("org"))
  113. (setq deft-directory "~/org")
  114. (after! org
  115. (setq org-directory (expand-file-name "~/org/")
  116. org-agenda-files (list org-directory)
  117. org-agenda-window-setup 'only-window
  118. org-pretty-entities t
  119. org-log-done 'time
  120. org-fontify-whole-heading-line t
  121. org-fontify-done-headline t
  122. org-fontify-quote-and-verse-blocks t
  123. org-ellipsis "…"
  124. org-capture-templates
  125. '(("i" "Send to inbox" entry (file+headline "~/org/inbox.org" "Inbox")
  126. "* TODO %?\n"))
  127. org-todo-keywords
  128. '((sequence "TODO(t)" "NEXT(n)" "MAYBE(m)" "|" "DONE(d)" "WONTDO(w)"))
  129. org-tag-alist '(("@personal" . ?h)
  130. ("@farm" . ?f)
  131. ("@town" . ?s)
  132. ("@errand" . ?e)
  133. ("@15five" . ?w)
  134. ("@family" . ?m))
  135. org-modules '(ol-eshell
  136. ol-notmuch
  137. ob-eval
  138. ob-exp
  139. ob-http
  140. org-drill
  141. org-id)))
  142. ;; Refiling
  143. (setq org-refile-targets '((nil :maxlevel . 9)
  144. (org-agenda-files :maxlevel . 9)))
  145. (setq org-outline-path-complete-in-steps nil) ; Refile in a single go
  146. (setq org-refile-use-outline-path t) ; Show full paths for refiling
  147. ;; org-set-tags-command
  148. (setq +inbox-file "~/org/inbox.org")
  149. (defun +open-inbox-file ()
  150. (interactive)
  151. "Opens the inbox file"
  152. (find-file +inbox-file))
  153. (map!
  154. :leader
  155. :desc "Open inbox" "I" #'+open-inbox-file
  156. :desc "Open today" "T" #'org-roam-today
  157. :desc "Open tomorrow" "N" #'org-roam-tomorrow)
  158. (map! :leader
  159. (:prefix "f" :desc "Save all org buffers" "a" #'org-save-all-org-buffers))
  160. (setq org-agenda-span 5
  161. org-agenda-start-day "1d")
  162. (defun +show-agenda ()
  163. (interactive)
  164. (delete-other-windows)
  165. (with-popup-rules! nil
  166. (org-agenda-list)
  167. (calendar))
  168. (other-window 1)
  169. (split-window-vertically)
  170. (other-window 1)
  171. (find-file +todo-file))
  172. (use-package! org-roam
  173. :commands (org-roam-insert org-roam-find-file org-roam)
  174. :init
  175. (setq org-roam-directory "~/org/")
  176. (map! :leader
  177. :prefix "n"
  178. :desc "Org-Roam-Insert" "i" #'org-roam-insert
  179. :desc "Org-Roam-Find" "/" #'org-roam-find-file
  180. :desc "Org-Roam-Buffer" "r" #'org-roam)
  181. :config
  182. (org-roam-mode +1))
  183. (with-eval-after-load 'org-roam
  184. (with-eval-after-load 'company
  185. (with-eval-after-load 'org
  186. (require 'company-org-roam)
  187. (company-org-roam-init))))
  188. (require 'justify-kp)
  189. ;(setq nov-text-width t)
  190. (setq nov-text-width 80)
  191. (defun my-nov-window-configuration-change-hook ()
  192. (my-nov-post-html-render-hook)
  193. (remove-hook 'window-configuration-change-hook
  194. 'my-nov-window-configuration-change-hook
  195. t))
  196. (defun my-nov-post-html-render-hook ()
  197. (if (get-buffer-window)
  198. (let ((max-width (pj-line-width))
  199. buffer-read-only)
  200. (save-excursion
  201. (goto-char (point-min))
  202. (while (not (eobp))
  203. (when (not (looking-at "^[[:space:]]*$"))
  204. (goto-char (line-end-position))
  205. (when (> (shr-pixel-column) max-width)
  206. (goto-char (line-beginning-position))
  207. (pj-justify)))
  208. (forward-line 1))))
  209. (add-hook 'window-configuration-change-hook
  210. 'my-nov-window-configuration-change-hook
  211. nil t)))
  212. (add-hook 'nov-post-html-render-hook 'my-nov-post-html-render-hook)
  213. (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
  214. (defun my-nov-font-setup ()
  215. (face-remap-add-relative 'variable-pitch :family "Liberation Serif"
  216. :size 20
  217. :height 1.0))
  218. (add-hook 'nov-mode-hook 'my-nov-font-setup)
  219. (load! "+mail") ;; Mail stuff
  220. ;; Use word wrap in text emails, because most people suck
  221. (remove-hook 'text-mode-hook #'auto-fill-mode)
  222. (add-hook 'message-mode-hook #'word-wrap-mode)
  223. (after! eshell
  224. (set-eshell-alias!
  225. "f" "(other-window 1) && find-file $1"
  226. "l" "ls -lh"
  227. "d" "dired $1"
  228. "dc" "docker-compose $*"
  229. "fftest" "cd ~/src/ff/fifteen5 && docker-compose exec app django-admin test -k $*"
  230. "ffsh" "cd ~/src/ff/fifteen5/ && docker-compose exec app django-admin shell_plus"
  231. "ffdj" "cd ~/src/ff/fifteen5/ && docker-compose exec app django-admin $*"
  232. "gl" "(call-interactively 'magit-log-current)"
  233. "gs" "magit-status"
  234. "gc" "magit-commit"))
  235. (use-package! ranger
  236. :commands (ranger deer ranger-override-dired-fn)
  237. :config
  238. (set-popup-rule! "^\\*ranger" :ignore t))
  239. (map!
  240. (:leader
  241. (:prefix "a"
  242. :desc "Ranger" "r" #'ranger
  243. :desc "Deer" "d" #'deer)))
  244. (add-hook! dired-mode #'ranger-override-dired-fn) ;; Override dired-mode so it uses deer
  245. (setq mastodon-instance-url "https://mastodon.technology")
  246. (map! :leader
  247. (:prefix "="
  248. :desc "Open mastodon" "=" #'mastodon
  249. :desc "Update Mastodon timeline" "u" #'mastodon-tl--update
  250. :desc "Toot to Mastodon" "t" #'mastodon-toot))
  251. (use-package! slack
  252. :commands (slack-start)
  253. :init
  254. (setq slack-buffer-emojify t)
  255. (setq slack-prefer-current-team t)
  256. :config
  257. (slack-register-team
  258. :name "15five"
  259. :token (auth-source-pick-first-password
  260. :host "15five.slack.com"
  261. :user "colin.powell@15five.com")
  262. :subscribed-channels '(squad-admin water-cooler))
  263. (slack-register-team
  264. :name "RAB"
  265. :token (auth-source-pick-first-password
  266. :host "randomaccessbrewery.slack.com"
  267. :user "colin@onec.me")
  268. :subscribed-channels '(the_taps random))
  269. (evil-define-key 'normal slack-info-mode-map
  270. ",u" 'slack-room-update-messages)
  271. (evil-define-key 'normal slack-mode-map
  272. ",c" 'slack-buffer-kill
  273. ",ra" 'slack-message-add-reaction
  274. ",rr" 'slack-message-remove-reaction
  275. ",rs" 'slack-message-show-reaction-users
  276. ",pl" 'slack-room-pins-list
  277. ",pa" 'slack-message-pins-add
  278. ",pr" 'slack-message-pins-remove
  279. ",mm" 'slack-message-write-another-buffer
  280. ",me" 'slack-message-edit
  281. ",md" 'slack-message-delete
  282. ",u" 'slack-room-update-messages
  283. ",2" 'slack-message-embed-mention
  284. ",3" 'slack-message-embed-channel
  285. "\C-n" 'slack-buffer-goto-next-message
  286. "\C-p" 'slack-buffer-goto-prev-message)
  287. (evil-define-key 'normal slack-edit-message-mode-map
  288. ",k" 'slack-message-cancel-edit
  289. ",s" 'slack-message-send-from-buffer
  290. ",2" 'slack-message-embed-mention
  291. ",3" 'slack-message-embed-channel))
  292. (use-package! alert
  293. :commands (alert)
  294. :init
  295. (setq alert-default-style 'libnotify))
  296. (map! :leader
  297. (:prefix "y" ; For (y)acking
  298. :desc "Slack channels" "s" #'slack-start
  299. :desc "Slack channels" "c" #'slack-channel-select
  300. :desc "Slack IMs" "i" #'slack-im-select
  301. :desc "Slack groups" "g" #'slack-group-select
  302. :desc "Slack threads" "t" #'slack-all-threads))
  303. (load! "beancount")
  304. (require 'beancount)
  305. (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode))
  306. (define-derived-mode
  307. pandoc-view-mode
  308. markdown-mode
  309. "pandoc-view-mode"
  310. "View pandoc processing of docx file using markdown mode."
  311. (erase-buffer)
  312. (let* ((pandoc (executable-find "pandoc")))
  313. (insert (shell-command-to-string
  314. (concat pandoc " --wrap=none " (shell-quote-argument (buffer-file-name)) " -t markdown"))))
  315. (not-modified)
  316. (read-only-mode t))
  317. (add-to-list 'auto-mode-alist '("\\.docx\\'" . pandoc-view-mode))