config.el 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. (setq user-full-name "Colin Powell"
  2. user-mail-address "colin@unbl.ink")
  3. (setq ivy-read-action-function #'ivy-hydra-read-action)
  4. (setq doom-theme 'doom-challenger-deep
  5. doom-font (font-spec :family "JetBrains Mono NL" :size 12 :weight 'semi-light)
  6. doom-big-font (font-spec :family "JetBrains Mono NL" :size 16)
  7. doom-variable-pitch-font (font-spec :family "Overpass" :size 16))
  8. ;; Applies to current frame
  9. (set-frame-parameter nil 'internal-border-width 10) ; applies to the current frame
  10. ;; If we create new frames (via emacsclient) this will do the trick
  11. (add-to-list 'default-frame-alist '(internal-border-width . 10))
  12. (nyan-mode) ;; progress in the form of a rainbow cat.
  13. (add-hook 'after-init-hook #'global-emojify-mode) ;; emojis?!
  14. (add-hook 'prog-mode-hook #'goto-address-mode) ;; linify links!
  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 "o"
  28. :desc "(H)ckrnews" "H" #'hackernews
  29. :desc "(R)SS" "R" #'=rss
  30. :desc "(M)ail" "M" #'=notmuch
  31. :desc "(L)obste.rs" "L" #'ivy-lobsters)
  32. (:prefix "b"
  33. :desc "Black format buffer" "f" #'blacken-buffer
  34. :desc "isort buffer" "I" #'py-isort-buffer
  35. :desc "Links in buffer" "l" #'ace-link-org)
  36. (:prefix "s"
  37. :desc "Search the web" "w" #'web-search
  38. :desc "Goto URL in eww" "u" #'eww-browse-url
  39. :desc "Search in eww" "3" #'eww-search-words
  40. :desc "Search all the things" "g" #'deadgrep))
  41. (setq wttrin-default-cities '("Castine, ME" "San Francisco" "Thessaloniki"))
  42. (setq wttrin-default-accept-language '("Accept-Language" . "en-US"))
  43. (map!
  44. (:leader
  45. (:prefix "o"
  46. :desc "(W)eather" "W" #'wttrin)))
  47. (setq libmpdel-hostname "mpd.unbl.ink")
  48. (defun mpdel-playlist-play ()
  49. "Start playing the song at point."
  50. (interactive)
  51. (if (derived-mode-p 'mpdel-playlist-current-playlist-mode)
  52. (libmpdel-play-song (navigel-entity-at-point))
  53. (mpdel-core-insert-current-playlist)))
  54. (map! :leader
  55. (:prefix "-"
  56. :desc "MPD Open playlist" "-" #'mpdel-playlist-open
  57. :desc "MPD Remove at point" "d" #'mpdel-playlist-delete
  58. :desc "MPD Start at point" "s" #'mpdel-playlist-play
  59. :desc "MPD Next track" "n" #'libmpdel-playback-next
  60. :desc "MPD Previous track" "p" #'libmpdel-playback-previous))
  61. (setq elfeed-protocol-ttrss-maxsize 100) ;; bigger than 200 is invalid
  62. (setq elfeed-feeds '("ttrss+https://powellc:hT7nPKAHa^fYwXZ*@reader.unbl.ink"))
  63. (setq elfeed-log-level 'debug)
  64. (elfeed-protocol-enable)
  65. ;; Schedule feed update for every 15 minutes
  66. (run-at-time "30 min" nil 'elfeed-update)
  67. (setq elfeed-search-filter "@2-days-ago +unread")
  68. (defun elfeed-search-format-date (date)
  69. (format-time-string "%Y-%m-%d %H:%M" (seconds-to-time date)))
  70. ; Serif font in Elfeed
  71. (add-hook! 'elfeed-mode-hook 'variable-pitch-mode)
  72. (add-hook! 'elfeed-show-mode-hook (text-scale-set 1.2))
  73. (defun unfill-paragraph ()
  74. "Takes a multi-line paragraph and makes it into a single line of text."
  75. (interactive)
  76. (let ((fill-column (point-max)))
  77. (fill-paragraph nil)))
  78. (define-key global-map "\M-z" 'unfill-paragraph)
  79. ;; PlantUML is awesome for quick diagrams
  80. (add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
  81. ;; Timezone location strings at http://worldtime.io
  82. (setq display-time-world-list '(("America/Los_Angeles" "San Francisco")
  83. ("America/Tegucigalpa" "Tegucigalpa")
  84. ("America/New_York" "New York")
  85. ("Europe/London" "London")
  86. ("Europe/Warsaw" "Warsaw")
  87. ("Europe/Kiev" "Lviv")))
  88. (flycheck-define-checker vale
  89. "A checker for prose"
  90. :command ("vale" "--output" "line"
  91. source)
  92. :standard-input nil
  93. :error-patterns
  94. ((error line-start (file-name) ":" line ":" column ":" (id (one-or-more (not (any ":")))) ":" (message) line-end))
  95. :modes (markdown-mode org-mode text-mode)
  96. )
  97. (add-to-list 'flycheck-checkers 'vale 'append)
  98. (add-hook 'org-mode-hook #'doom-disable-line-numbers-h)
  99. (after! org
  100. (setq org-directory (expand-file-name "~/var/org/")
  101. org-agenda-files (file-expand-wildcards "~/var/org/2020-*")
  102. org-pretty-entities t
  103. org-agenda-dim-blocked-tasks nil
  104. org-log-done 'time
  105. org-hide-emphasis-markers t
  106. org-fontify-whole-heading-line t
  107. org-fontify-done-headline t
  108. org-fontify-quote-and-verse-blocks t
  109. org-ellipsis "…"
  110. org-image-actual-width '(600)
  111. org-protocol-default-template-key "l"
  112. org-capture-templates
  113. '(("i" "Send to inbox" entry (file "~/var/org/inbox.org")
  114. "* TODO %?\n")
  115. ("l" "Link" entry (file "~/var/org/inbox.org")
  116. "* TODO %a\n %?\n %i"))
  117. org-todo-keywords
  118. '((sequence "TODO(t)" "NEXT(n)" "MAYBE(m)" "|" "DONE(d)" "WONTDO(w)"))
  119. org-modules '(ol-eshell
  120. ol-notmuch
  121. ob-eval
  122. ob-exp
  123. ob-http
  124. org-id)))
  125. ;; Don’t display git gutter in org mode
  126. ;; With tree folding, it's pretty much useless
  127. (after! git-gutter
  128. (setq git-gutter:disabled-modes '(org-mode image-mode)))
  129. ;; Refiling
  130. (setq org-refile-targets '(("~/var/org/inbox.org" :maxlevel . 9)))
  131. (setq org-outline-path-complete-in-steps nil) ; Refile in a single go
  132. (setq org-refile-use-outline-path t) ; Show full paths for refiling
  133. (setq +inbox-file "~/var/org/inbox.org")
  134. (defun +open-inbox-file ()
  135. (interactive)
  136. "Opens the inbox file"
  137. (find-file +inbox-file))
  138. (map!
  139. :leader
  140. :desc "Open inbox" "I" #'+open-inbox-file
  141. :desc "Save all org buffers" "A" #'org-save-all-org-buffers)
  142. (setq org-agenda-span 3
  143. org-agenda-start-day "1d")
  144. (defun +show-agenda ()
  145. (interactive)
  146. (delete-other-windows)
  147. (with-popup-rules! nil
  148. (org-agenda-list)
  149. (calendar))
  150. (other-window 1)
  151. (split-window-vertically)
  152. (other-window 1)
  153. (find-file +todo-file))
  154. (setq org-roam-directory "~/var/org/")
  155. (setq org-roam-dailies-directory "")
  156. (setq org-roam-dailies-capture-templates
  157. '(("d" "default" entry
  158. #'org-roam-capture--get-point
  159. "* %?"
  160. :file-name "%<%Y-%m-%d>"
  161. :head "#+title: %<%Y-%m-%d>\n\n")))
  162. (setq org-fc-directories "~/var/org/")
  163. (require 'org-fc-hydra)
  164. (require 'justify-kp)
  165. ;(setq nov-text-width t)
  166. (setq nov-text-width 100)
  167. (defun my-nov-window-configuration-change-hook ()
  168. (my-nov-post-html-render-hook)
  169. (remove-hook 'window-configuration-change-hook
  170. 'my-nov-window-configuration-change-hook
  171. t))
  172. (defun my-nov-post-html-render-hook ()
  173. (if (get-buffer-window)
  174. (let ((max-width (pj-line-width))
  175. buffer-read-only)
  176. (save-excursion
  177. (goto-char (point-min))
  178. (while (not (eobp))
  179. (when (not (looking-at "^[[:space:]]*$"))
  180. (goto-char (line-end-position))
  181. (when (> (shr-pixel-column) max-width)
  182. (goto-char (line-beginning-position))
  183. (pj-justify)))
  184. (forward-line 1))))
  185. (add-hook 'window-configuration-change-hook
  186. 'my-nov-window-configuration-change-hook
  187. nil t)))
  188. (add-hook 'nov-post-html-render-hook 'my-nov-post-html-render-hook)
  189. (defun my-nov-font-setup ()
  190. (face-remap-add-relative 'variable-pitch :family "Noto Serif Regular"
  191. :height 1.0
  192. :size 16))
  193. (add-hook 'nov-mode-hook 'my-nov-font-setup)
  194. (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
  195. ;(add-hook 'nov-mode-hook 'variable-pitch-mode)
  196. (setq mm-text-html-renderer 'w3m)
  197. (setq w3m-fill-column 88)
  198. (setq message-kill-buffer-on-exit t)
  199. (setq message-auto-save-directory "~/Mail/colin@unbl.ink/Drafts/")
  200. (setq message-directory "~/Mail/colin@unbl.ink/")
  201. ;; sendmail-program "/usr/local/bin/msmtpq" <--- this doesn't work as advertised right now
  202. (setq send-mail-function 'sendmail-send-it
  203. sendmail-program "/usr/local/bin/msmtp"
  204. mail-specify-envelope-from t
  205. message-sendmail-f-is-evil t
  206. message-sendmail-envelope-from 'header
  207. message-sendmail-extra-arguments '("--read-envelope-from")
  208. mail-envelope-from 'header)
  209. (setq notmuch-saved-searches '((:name "inbox" :query "tag:inbox" :key "i")
  210. (:name "unread" :query "tag:inbox and tag:unread" :key "u")
  211. (:name "jira" :query "tag:jira and date:yesterday..today" :key "j")
  212. (:name "github" :query "tag:github and date:yesterday..today" :key "g")))
  213. (after! notmuch
  214. (set-popup-rule! "^\\*notmuch*" :ignore t)
  215. )
  216. (map! :leader
  217. (:prefix "e"
  218. :desc "(s)end queued mail" "s" #'smtpmail-send-queued-mail
  219. :desc "Open (i)nbox" "i" #'=notmuch
  220. :desc "Open (n)otmuch" "n" #'notmuch
  221. :desc "(C)ompose mail" "c" #'notmuch-mua-new-mail))
  222. (after! eshell
  223. (set-eshell-alias!
  224. "djtest" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py test $*"
  225. "djpytest" "DJANGO_SETTINGS_MODULE=ff.settings.ci pytest --reuse-db --black --flake8 --isort --durations=3 $*"
  226. "djsh" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py shell_plus"
  227. "dj" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py $*"
  228. "f" "(other-window 1) && find-file $1"
  229. "l" "ls -lh"
  230. "d" "dired $1"
  231. "gl" "(call-interactively 'magit-log-current)"
  232. "gs" "magit-status"
  233. "gc" "magit-commit"))
  234. (after! lsp
  235. (setq lsp-file-watch-threshold nil))
  236. (setq mastodon-instance-url "https://mastodon.technology")
  237. (map! :leader
  238. (:prefix "="
  239. :desc "Open mastodon" "=" #'mastodon
  240. :desc "Update Mastodon timeline" "u" #'mastodon-tl--update
  241. :desc "More Mastodon timeline" "m" #'mastodon-tl--more
  242. :desc "Toot to Mastodon" "t" #'mastodon-toot))
  243. (use-package! slack
  244. :commands (slack-start)
  245. :init
  246. (setq slack-buffer-emojify t)
  247. (setq slack-prefer-current-team t)
  248. :config
  249. (slack-register-team
  250. :name "15five"
  251. :token (auth-source-pick-first-password
  252. :host "15five.slack.com"
  253. :user "colin.powell@15five.com")
  254. :subscribed-channels '(squad-admin water-cooler))
  255. (slack-register-team
  256. :name "RAB"
  257. :token (auth-source-pick-first-password
  258. :host "randomaccessbrewery.slack.com"
  259. :user "colin@onec.me")
  260. :subscribed-channels '(the_taps random))
  261. (evil-define-key 'normal slack-info-mode-map
  262. ",u" 'slack-room-update-messages)
  263. (evil-define-key 'normal slack-mode-map
  264. ",c" 'slack-buffer-kill
  265. ",ra" 'slack-message-add-reaction
  266. ",rr" 'slack-message-remove-reaction
  267. ",rs" 'slack-message-show-reaction-users
  268. ",pl" 'slack-room-pins-list
  269. ",pa" 'slack-message-pins-add
  270. ",pr" 'slack-message-pins-remove
  271. ",mm" 'slack-message-write-another-buffer
  272. ",me" 'slack-message-edit
  273. ",md" 'slack-message-delete
  274. ",u" 'slack-room-update-messages
  275. ",2" 'slack-message-embed-mention
  276. ",3" 'slack-message-embed-channel
  277. "\C-n" 'slack-buffer-goto-next-message
  278. "\C-p" 'slack-buffer-goto-prev-message)
  279. (evil-define-key 'normal slack-edit-message-mode-map
  280. ",k" 'slack-message-cancel-edit
  281. ",s" 'slack-message-send-from-buffer
  282. ",2" 'slack-message-embed-mention
  283. ",3" 'slack-message-embed-channel))
  284. (use-package! alert
  285. :commands (alert)
  286. :init
  287. (setq alert-default-style 'libnotify))
  288. (map! :leader
  289. (:prefix "o"
  290. (:prefix ("s" . "+slack")
  291. :desc "Slack channels" "S" #'slack-start
  292. :desc "Slack channels" "s" #'slack-channel-select
  293. :desc "Slack IMs" "i" #'slack-im-select
  294. :desc "Slack groups" "g" #'slack-group-select
  295. :desc "Slack threads" "t" #'slack-all-threads)))
  296. (load! "beancount")
  297. (require 'beancount)
  298. (add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode))
  299. (define-derived-mode
  300. pandoc-view-mode
  301. markdown-mode
  302. "pandoc-view-mode"
  303. "View pandoc processing of docx file using markdown mode."
  304. (erase-buffer)
  305. (let* ((pandoc (executable-find "pandoc")))
  306. (insert (shell-command-to-string
  307. (concat pandoc " --wrap=none " (shell-quote-argument (buffer-file-name)) " -t markdown"))))
  308. (not-modified)
  309. (read-only-mode t))
  310. (add-to-list 'auto-mode-alist '("\\.docx\\'" . pandoc-view-mode))
  311. ;;(add-hook 'magit-mode-hook #'doom-disable-line-numbers-h)
  312. (setq +magit-hub-features t ;; I want the PR/issue stuff too!
  313. +magit-hub-enable-by-default t) ;; And I want it on by default!
  314. (after! magit
  315. (magit-wip-after-save-mode t)
  316. (magit-wip-after-apply-mode t)
  317. (setq magit-save-repository-buffers 'dontask
  318. magit-circleci-token "097bf0dd808ad9103d489844e37cecffdf967837"
  319. magit-repository-directories '(("~/src/" . 3)
  320. ("~/dotfiles/" . 0))
  321. magit-popup-display-buffer-action nil ;; Not sure why this is here, wonder what it does
  322. magit-display-file-buffer-function #'switch-to-buffer-other-window
  323. magithub-clone-default-directory "~/src" ;; I want my stuff to clone to ~/projects
  324. magithub-preferred-remote-method 'ssh_url)) ;; HTTPS cloning is awful, i authenticate with ssh keys.
  325. (setq lsp-enable-links nil)
  326. (when (require 'openwith nil 'noerror)
  327. (setq openwith-associations
  328. (list
  329. (list (openwith-make-extension-regexp
  330. '("mpg" "mpeg" "mp3" "mp4"
  331. "avi" "wmv" "wav" "mov" "flv"
  332. "ogm" "ogg" "mkv"))
  333. "vlc"
  334. '(file))
  335. (list (openwith-make-extension-regexp
  336. '("pdf" "ps" "ps.gz" "dvi"))
  337. "zathura"
  338. '(file))
  339. ))
  340. (openwith-mode 1))