[emacs] Move to .doom.d config file

This commit is contained in:
2020-09-25 22:11:58 -04:00
parent 8da4c6e41b
commit 708bf56f90
12 changed files with 434 additions and 20 deletions

18
emacs/.doom.d/+magit.el Normal file
View File

@ -0,0 +1,18 @@
;;; ~/.doom.d/+magit.el -*- lexical-binding: t; -*-
(setq +magit-hub-features t ;; I want the PR/issue stuff too!
+magit-hub-enable-by-default t) ;; And I want it on by default!
(after! magit
(magit-wip-after-save-mode t)
(magit-wip-after-apply-mode t)
(setq magit-save-repository-buffers 'dontask
magit-circleci-token "097bf0dd808ad9103d489844e37cecffdf967837"
magit-repository-directories '(("~/src/" . 3)
("~/dotfiles/" . 0))
magit-popup-display-buffer-action nil ;; Not sure why this is here, wonder what it does
magit-display-file-buffer-function #'switch-to-buffer-other-window
magithub-clone-default-directory "~/src" ;; I want my stuff to clone to ~/projects
magithub-preferred-remote-method 'ssh_url)) ;; HTTPS cloning is awful, i authenticate with ssh keys.

459
emacs/.doom.d/+mail.el Normal file
View File

@ -0,0 +1,459 @@
;;; -*- lexical-binding: t; -*-
;;; Config is mostly from https://kkatsuyuki.github.io/notmuch-conf/ aadsa
;;; This is all modified from
;;; https://github.com/fuxialexander/doom-emacs-private-xfu/
;;;; Notmuch
(use-package! notmuch
:commands (notmuch
notmuch-tree
notmuch-tree-mode
notmuch-search
notmuch-search-mode
notmuch-hello
notmuch-hello-mode
notmuch-show
notmuch-show-mode
notmuch-message-mode)
:init
(map!
(:leader
(:prefix "e"
:desc "Send queued mail" "s" #'smtpmail-send-queued-mail
:desc "Open (i)nbox" "i" #'=notmuch
:desc "Open (n)otmuch" "n" #'notmuch
:desc "(C)ompose mail" "c" #'notmuch-mua-new-mail))))
(set-evil-initial-state! '(notmuch-hello-mode
notmuch-show-mode
notmuch-search-mode
notmuch-tree-mode
notmuch-message-mode) 'normal)
;; (add-hook 'notmuch-tree-mode-hook '+mail/buffer-face-mode-notmuch)
;; (add-hook 'notmuch-search-mode-hook '+mail/buffer-face-mode-notmuch)
;; (add-hook 'notmuch-message-mode-hook '+mail/buffer-face-mode-notmuch)
(add-hook 'notmuch-message-mode-hook (lambda () (set (make-local-variable 'company-backends) '(notmuch-company (company-ispell :with company-yasnippet)))))
(add-hook 'notmuch-tree-mode-hook (lambda () (setq-local line-spacing nil)))
;;(remove-hook 'message-mode-hook #'turn-on-auto-fill)
;;(remove-hook 'notmuch-message-mode-hook #'turn-on-auto-fill)
;; (push 'notmuch-tree-mode evil-snipe-disabled-modes)
;; (push 'notmuch-hello-mode evil-snipe-disabled-modes)
;; (push 'notmuch-search-mode evil-snipe-disabled-modes)
;; (push 'notmuch-show-mode evil-snipe-disabled-modes)
(advice-add #'notmuch-start-notmuch-sentinel :override #'+mail/notmuch-start-notmuch-sentinel)
(advice-add #'notmuch-show :override #'+mail/notmuch-show-reuse-buffer)
(advice-add #'notmuch-hello-insert-searches :override #'+mail/notmuch-hello-insert-searches)
(advice-add #'notmuch-hello-insert-saved-searches :override #'+mail/notmuch-hello-insert-saved-searches)
(advice-add #'notmuch-hello-insert-buttons :override #'+mail/notmuch-hello-insert-buttons)
;; (set! :popup "\\*notmuch-hello\\*" '((size . 20) (side . left)) '((quit . t) (modeline . nil)))
(push (lambda (buf) (string-match-p "^\\*notmuch" (buffer-name buf)))
doom-real-buffer-functions)
(map! (:after notmuch
(:map notmuch-show-mode-map
:nmv "o" #'ace-link-notmuch-show
:nmv "i" #'+mail/open-message-with-mail-app-notmuch-show
:nmv "I" #'notmuch-show-view-all-mime-parts
:nmv "q" #'notmuch-bury-or-kill-this-buffer
(:when (featurep! :completion ivy)
:nmv "s" #'counsel-notmuch)
(:when (featurep! :completion helm)
:nmv "s" #'helm-notmuch)
:nmv "t" #'notmuch-tree-from-show-current-query
:nmv "N" #'notmuch-mua-new-mail
:nmv "n" #'notmuch-show-next-thread-show
:nmv "r" #'notmuch-show-reply
:nmv "<tab>" #'notmuch-show-toggle-visibility-headers
:nmv "R" #'notmuch-show-reply-sender
:nmv "p" #'notmuch-show-previous-thread-show)
(:map notmuch-hello-mode-map
:nmv "o" #'ace-link-notmuch-hello
:nmv "t" #'notmuch-tree
:nmv "k" #'widget-backward
:nmv "n" #'notmuch-mua-new-mail
:nmv "N" #'notmuch-mua-new-mail
:nmv "j" #'widget-forward
(:when (featurep! :completion ivy)
:nmv "s" #'counsel-notmuch)
(:when (featurep! :completion helm)
:nmv "s" #'helm-notmuch)
:nmv "q" #'+mail/quit
:nmv "r" #'notmuch-hello-update)
(:map notmuch-search-mode-map
:nmv "j" #'notmuch-search-next-thread
:nmv "k" #'notmuch-search-previous-thread
:nmv "t" #'notmuch-tree-from-search-thread
;; :nmv "RET" #'notmuch-tree-from-search-thread
:nmv "RET" #'notmuch-search-show-thread
:nmv "N" #'notmuch-mua-new-mail
:nmv "T" #'notmuch-tree-from-search-current-query
:nmv ";" #'notmuch-search-tag
:nmv "," #'notmuch-jump-search
:nmv "d" #'+mail/notmuch-search-delete
:nmv "a" #'notmuch-search-archive-thread
;; :nmv "q" #'notmuch
:nmv "q" #'+mail/quit
:nmv "R" #'notmuch-search-reply-to-thread-sender
:nmv "r" #'notmuch-search-reply-to-thread
:nmv "go" #'+notmuch-exec-offlineimap
(:when (featurep! :completion ivy)
:nmv "s" #'counsel-notmuch)
(:when (featurep! :completion helm)
:nmv "s" #'helm-notmuch)
:nmv "x" #'+mail/notmuch-search-spam)
(:map notmuch-tree-mode-map
:nmv "j" #'notmuch-tree-next-message
:nmv "k" #'notmuch-tree-prev-message
:nmv "S" #'notmuch-search-from-tree-current-query
(:when (featurep! :completion ivy)
:nmv "s" #'counsel-notmuch)
(:when (featurep! :completion helm)
:nmv "s" #'helm-notmuch)
:nmv "t" #'notmuch-tree
:nmv ";" #'notmuch-tree-tag
:nmv "RET" #'notmuch-tree-show-message
:nmv "q" #'notmuch-tree-quit
:nmv "s-n" #'notmuch-mua-new-mail
:nmv "r" #'notmuch-search-reply-to-thread-sender
:nmv "a" #'notmuch-tree-archive-message-then-next
:nmv "A" #'notmuch-tree-archive-thread
:nmv "i" #'+mail/open-message-with-mail-app-notmuch-tree
:nmv "d" #'+mail/notmuch-tree-delete
:nmv "x" #'+mail/notmuch-tree-spam)
(:map notmuch-message-mode-map
:localleader
:desc "Send and Exit" doom-localleader-key #'notmuch-mua-send-and-exit
:desc "Kill Message Buffer" "k" #'notmuch-mua-kill-buffer
:desc "Save as Draft" "s" #'message-dont-send
:desc "Attach file" "f" #'mml-attach-file)))
; Use w3m to parse HTML email
(setq mm-text-html-renderer 'w3m)
(setq w3m-fill-column 72)
;;;; counsel-notmuch
(when (featurep! :completion ivy)
(use-package! counsel-notmuch
:commands counsel-notmuch
:after notmuch))
;;;; helm-notmuch
(when (featurep! :completion helm)
(use-package! helm-notmuch
:commands helm-notmuch
:after notmuch))
;;;; org-mime
(use-package! org-mime
:after (org notmuch))
:config (setq org-mime-library 'mml)
;;;###autoload
(defun =mail ()
"Activate (or switch to) `notmuch' in its workspace."
(interactive)
(if-let* ((buf (cl-find-if (lambda (it) (string-match-p "^\\*notmuch" (buffer-name (window-buffer it))))
(doom-visible-windows))))
(select-window (get-buffer-window buf))
(notmuch-search "tag:inbox")))
;; (call-interactively 'notmuch-hello-sidebar))
;;;###autoload
(defun +mail/quit ()
(interactive)
;; (+popup/close (get-buffer-window "*notmuch-hello*"))
(doom-kill-matching-buffers "^\\*notmuch"))
;;;###autoload
(defun +mail/notmuch-search-delete ()
(interactive)
(notmuch-search-add-tag
(list "+deleted" "-inbox" "-unread"))
(notmuch-search-next-thread))
;;;###autoload
(defun +mail/notmuch-tree-delete ()
(interactive)
(notmuch-tree-add-tag
(list "+trash" "-inbox" "-unread"))
(notmuch-tree-next-message))
;;;###autoload
(defun +mail/notmuch-search-spam ()
(interactive)
(notmuch-search-add-tag
(list "+spam" "-inbox" "-unread"))
(notmuch-search-next-thread))
;;;###autoload
(defun +mail/notmuch-tree-spam ()
(interactive)
(notmuch-tree-add-tag
(list "+spam" "-inbox" "-unread"))
(notmuch-tree-next-message))
;;;###autoload
(defun +mail/open-message-with-mail-app-notmuch-tree ()
(interactive)
(let* ((msg-path (car (plist-get (notmuch-tree-get-message-properties) :filename)))
(temp (make-temp-file "notmuch-message-" nil ".eml")))
(shell-command-to-string (format "cp '%s' '%s'" msg-path temp))
(start-process-shell-command "email" nil (format "thunderbird '%s'" temp))))
;; Override
;;;###autoload
(defun +mail/notmuch-start-notmuch-sentinel (proc event)
"Process sentinel function used by `notmuch-start-notmuch'."
(let* ((err-file (process-get proc 'err-file))
(err-buffer (or (process-get proc 'err-buffer)
(find-file-noselect err-file)))
(err (when (not (zerop (buffer-size err-buffer)))
(with-current-buffer err-buffer (buffer-string))))
(sub-sentinel (process-get proc 'sub-sentinel))
(real-command (process-get proc 'real-command)))
(condition-case err
(progn
;; Invoke the sub-sentinel, if any
(when sub-sentinel
(funcall sub-sentinel proc event))
;; Check the exit status. This will signal an error if the
;; exit status is non-zero. Don't do this if the process
;; buffer is dead since that means Emacs killed the process
;; and there's no point in telling the user that (but we
;; still check for and report stderr output below).
(when (buffer-live-p (process-buffer proc))
(notmuch-check-async-exit-status proc event real-command err))
;; If that didn't signal an error, then any error output was
;; really warning output. Show warnings, if any.
(let ((warnings
(when err
(with-current-buffer err-buffer
(goto-char (point-min))
(end-of-line)
;; Show first line; stuff remaining lines in the
;; errors buffer.
(let ((l1 (buffer-substring (point-min) (point))))
(skip-chars-forward "\n")
(cons l1 (unless (eobp)
(buffer-substring (point) (point-max)))))))))
(when warnings
(notmuch-logged-error (car warnings) (cdr warnings)))))
(error
;; Emacs behaves strangely if an error escapes from a sentinel,
;; so turn errors into messages.
(message "%s" (error-message-string err))))
(when err-buffer
(set-process-query-on-exit-flag (get-buffer-process err-buffer) nil)
(kill-buffer err-buffer))
(when err-file (ignore-errors (delete-file err-file)))))
;;;###autoload
(defun +mail/notmuch-show-reuse-buffer (thread-id &optional elide-toggle parent-buffer query-context buffer-name)
"Run \"notmuch show\" with the given thread ID and display results.
ELIDE-TOGGLE, if non-nil, inverts the default elide behavior.
The optional PARENT-BUFFER is the notmuch-search buffer from
which this notmuch-show command was executed, (so that the
next thread from that buffer can be show when done with this
one).
The optional QUERY-CONTEXT is a notmuch search term. Only
messages from the thread matching this search term are shown if
non-nil.
The optional BUFFER-NAME provides the name of the buffer in
which the message thread is shown. If it is nil (which occurs
when the command is called interactively) the argument to the
function is used.
Returns the buffer containing the messages, or NIL if no messages
matched."
(interactive "sNotmuch show: \nP")
(let ((buffer-name (generate-new-buffer-name
(or (concat "*notmuch-" buffer-name "*")
(concat "*notmuch-" thread-id "*"))))
;; We override mm-inline-override-types to stop application/*
;; parts from being displayed unless the user has customized
;; it themselves.
(mm-inline-override-types
(if (equal mm-inline-override-types
(eval (car (get 'mm-inline-override-types 'standard-value))))
(cons "application/*" mm-inline-override-types)
mm-inline-override-types)))
(switch-to-buffer (get-buffer-create buffer-name))
;; No need to track undo information for this buffer.
(setq buffer-undo-list t)
(notmuch-show-mode)
;; Set various buffer local variables to their appropriate initial
;; state. Do this after enabling `notmuch-show-mode' so that they
;; aren't wiped out.
(setq notmuch-show-thread-id thread-id
notmuch-show-parent-buffer parent-buffer
notmuch-show-query-context (if (or (string= query-context "")
(string= query-context "*"))
nil query-context)
notmuch-show-process-crypto notmuch-crypto-process-mime
;; If `elide-toggle', invert the default value.
notmuch-show-elide-non-matching-messages
(if elide-toggle
(not notmuch-show-only-matching-messages)
notmuch-show-only-matching-messages))
(add-hook 'post-command-hook #'notmuch-show-command-hook nil t)
(jit-lock-register #'notmuch-show-buttonise-links)
(notmuch-tag-clear-cache)
(let ((inhibit-read-only t))
(if (notmuch-show--build-buffer)
;; Messages were inserted into the buffer.
(current-buffer)
;; No messages were inserted - presumably none matched the
;; query.
(kill-buffer (current-buffer))
(ding)
(message "No messages matched the query!")
nil))))
;;;###autoload
;(defun +mail/notmuch-hello-insert-searches (title query-list &rest options)
; "Insert a section with TITLE showing a list of buttons made from QUERY-LIST.
;QUERY-LIST should ideally be a plist but for backwards
;compatibility other forms are also accepted (see
;`notmuch-saved-searches' for details). The plist should
;contain keys :name and :query; if :count-query is also present
;then it specifies an alternate query to be used to generate the
;count for the associated search.
;Supports the following entries in OPTIONS as a plist:
;:initially-hidden - if non-nil, section will be hidden on startup
;:show-empty-searches - show buttons with no matching messages
;:hide-if-empty - hide if no buttons would be shown
; (only makes sense without :show-empty-searches)
;:filter - This can be a function that takes the search query as its argument and
; returns a filter to be used in conjuction with the query for that search or nil
; to hide the element. This can also be a string that is used as a combined with
; each query using \"and\".
;:filter-count - Separate filter to generate the count displayed each search. Accepts
; the same values as :filter. If :filter and :filter-count are specified, this
; will be used instead of :filter, not in conjunction with it."
; (widget-insert (propertize title 'face 'org-agenda-structure))
; (if (and notmuch-hello-first-run (plist-get options :initially-hidden))
; (add-to-list 'notmuch-hello-hidden-sections title))
; (let ((is-hidden (member title notmuch-hello-hidden-sections))
; (widget-push-button-prefix "")
; (widget-push-button-suffix "")
; (start (point)))
; (if is-hidden
; (widget-create 'push-button
; :notify `(lambda (widget &rest ignore)
; (setq notmuch-hello-hidden-sections
; (delete ,title notmuch-hello-hidden-sections))
; (notmuch-hello-update))
; (propertize " +" 'face 'org-agenda-structure))
; (widget-create 'push-button
; :notify `(lambda (widget &rest ignore)
; (add-to-list 'notmuch-hello-hidden-sections
; ,title)
; (notmuch-hello-update))
; " -"))
; (widget-insert "\n")
; (when (not is-hidden)
; (let ((searches (apply 'notmuch-hello-query-counts query-list options)))
; (when (or (not (plist-get options :hide-if-empty))
; searches)
; (widget-insert "\n")
; (notmuch-hello-insert-buttons searches)
; (indent-rigidly start (point) notmuch-hello-indent))))))
;
;;;;###autoload
;(defun +mail/notmuch-hello-insert-saved-searches ()
; "Insert the saved-searches section."
; (let ((searches (notmuch-hello-query-counts
; (if notmuch-saved-search-sort-function
; (funcall notmuch-saved-search-sort-function
; notmuch-saved-searches)
; notmuch-saved-searches)
; :show-empty-searches notmuch-show-empty-saved-searches)))
; (when searches
; (widget-insert (propertize "Notmuch" 'face 'org-agenda-date-today))
; (widget-insert "\n\n")
; (widget-insert (propertize "Saved searches" 'face 'org-agenda-structure))
; (widget-insert "\n\n")
; (let ((start (point)))
; (notmuch-hello-insert-buttons searches)
; (indent-rigidly start (point) notmuch-hello-indent)))))
;
;;;;###autoload
;(defun +mail/notmuch-hello-insert-buttons (searches)
; "Insert buttons for SEARCHES.
;SEARCHES must be a list of plists each of which should contain at
;least the properties :name NAME :query QUERY and :count COUNT,
;where QUERY is the query to start when the button for the
;corresponding entry is activated, and COUNT should be the number
;of messages matching the query. Such a plist can be computed
;with `notmuch-hello-query-counts'."
; (let* ((widest (notmuch-hello-longest-label searches))
; (tags-and-width (notmuch-hello-tags-per-line widest))
; (tags-per-line (car tags-and-width))
; (column-width (cdr tags-and-width))
; (column-indent 0)
; (count 0)
; (reordered-list (notmuch-hello-reflect searches tags-per-line))
; ;; Hack the display of the buttons used.
; (widget-push-button-prefix "")
; (widget-push-button-suffix ""))
; ;; dme: It feels as though there should be a better way to
; ;; implement this loop than using an incrementing counter.
; (mapc (lambda (elem)
; ;; (not elem) indicates an empty slot in the matrix.
; (when elem
; (if (> column-indent 0)
; (widget-insert (make-string column-indent ? )))
; (let* ((name (plist-get elem :name))
; (query (plist-get elem :query))
; (oldest-first (case (plist-get elem :sort-order)
; (newest-first nil)
; (oldest-first t)
; (otherwise notmuch-search-oldest-first)))
; (search-type (eq (plist-get elem :search-type) 'tree))
; (msg-count (plist-get elem :count)))
; (widget-insert (format "\n%5s "
; (notmuch-hello-nice-number msg-count)))
; (widget-create 'push-button
; :notify #'notmuch-hello-widget-search
; :notmuch-search-terms query
; :notmuch-search-oldest-first oldest-first
; :notmuch-search-type search-type
; name)
; (setq column-indent
; (1+ (max 0 (- column-width (length name)))))))
; (setq count (1+ count))
; (when (eq (% count tags-per-line) 0)
; (setq column-indent 0)
; (widget-insert "\n")))
; reordered-list)
;
; ;; If the last line was not full (and hence did not include a
; ;; carriage return), insert one now.
; (unless (eq (% count tags-per-line) 0)
; (widget-insert "\n"))))
; Kill email message buffers when you close them
(setq message-kill-buffer-on-exit t)
(setq message-default-mail-headers "Cc: \nBcc: \n")
(setq message-auto-save-directory "~/Mail/colin@unbl.ink/Drafts/")
(setq message-directory "~/Mail/colin@unbl.ink/")
;;; Setup sending email with msmtp
(setq send-mail-function 'sendmail-send-it
sendmail-program "/usr/local/bin/msmtp"
smtpmail-queue-mail t
mail-specify-envelope-from t
message-sendmail-f-is-evil t
message-sendmail-envelope-from 'header
message-sendmail-extra-arguments '("--read-envelope-from")
mail-envelope-from 'header)

1
emacs/.doom.d/+python.el Normal file
View File

@ -0,0 +1 @@
;;; ~/devel/dotfiles/config/doom/+python.el -*- lexical-binding: t; -*-

30
emacs/.doom.d/+reason.el Normal file
View File

@ -0,0 +1,30 @@
;;; -*- lexical-binding: t; -*-
(def-package! reason-mode
:mode "\\.rei?$"
:commands (reason-mode)
:config
(let* (
(refmt-bin (executable-find "refmt"))
(merlin-bin (executable-find "ocamlmerlin"))
(merlin-base-dir (when merlin-bin
(replace-regexp-in-string "bin/ocamlmerlin$" "" merlin-bin))))
;; Add npm merlin.el to the emacs load path and tell emacs where to find ocamlmerlin
(when merlin-bin
(add-to-list 'load-path (concat merlin-base-dir "share/emacs/site-lisp/"))
(setq merlin-command merlin-bin))
(when refmt-bin
(setq refmt-command refmt-bin))
(require 'merlin)
(add-hook! reason-mode
(add-hook 'before-save-hook #'refmt-before-save nil t)
(merlin-mode))
(setq-hook! reason-mode
indent-region-function #'apply-refmt)
(set-electric! 'some-mode :chars '(?|))
(set-lookup-handlers! 'reason-mode
:definition #'merlin-locate
:references #'merlin-occurrences
:documentation #'merlin-document)
(set-company-backend! 'reason-mode 'merlin-company-backend)))

View File

@ -0,0 +1,34 @@
;;; private/hlissner/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +hlissner/find-in-dotfiles ()
"Open a file somewhere in ~/.dotfiles via a fuzzy filename search."
(interactive)
(doom-project-find-file (expand-file-name "~/.dotfiles")))
;;;###autoload
(defun +hlissner/browse-dotfiles ()
"Browse the files in ~/.dotfiles."
(interactive)
(doom-project-browse (expand-file-name "~/.dotfiles")))
;;;###autoload
(defun +hlissner/find-notes-for-major-mode (&optional arg)
"TODO"
(interactive "P")
(let ((default-directory (expand-file-name "code/" +org-dir)))
(if arg
(call-interactively #'find-file)
(find-file
(expand-file-name (concat (string-remove-suffix "-mode" (symbol-name major-mode)) ".org"))))))
;;;###autoload
(defun +hlissner/find-notes-for-project (&optional arg)
"TODO"
(interactive "P")
(let ((project-root (doom-project-name 'nocache))
(default-directory (expand-file-name "projects/" +org-dir)))
(if arg
(call-interactively #'find-file)
(find-file
(expand-file-name (concat project-root ".org"))))))

1013
emacs/.doom.d/beancount.el Normal file

File diff suppressed because it is too large Load Diff

384
emacs/.doom.d/config.el Normal file
View File

@ -0,0 +1,384 @@
(setq user-full-name "Colin Powell"
user-mail-address "colin@unbl.ink")
(setq ivy-read-action-function #'ivy-hydra-read-action)
(setq doom-theme 'doom-old-hope
doom-font (font-spec :family "JetBrains Mono NL" :size 14 :weight 'semi-light)
doom-big-font (font-spec :family "JetBrains Mono NL" :size 18)
doom-variable-pitch-font (font-spec :family "Overpass" :size 16))
;; Applies to current frame
;(set-frame-parameter nil 'internal-border-width 10) ; applies to the current frame
;; If we create new frames (via emacsclient) this will do the trick
;(add-to-list 'default-frame-alist '(internal-border-width . 10))
(nyan-mode) ;; progress in the form of a rainbow cat.
(add-hook 'after-init-hook #'global-emojify-mode) ;; emojis?!
(add-hook 'prog-mode-hook #'goto-address-mode) ;; linify links!
(map! ;; Easier window movement
:n "C-h" 'evil-window-left
:n "C-j" 'evil-window-down
:n "C-k" 'evil-window-up
:n "C-l" 'evil-window-right
(:map evil-treemacs-state-map
"C-h" 'evil-window-left
"C-l" 'evil-window-right)
:leader
(:prefix "f"
:desc "Find file in dotfiles" "t" #'+hlissner/find-in-dotfiles
:desc "Browse dotfiles" "T" #'+hlissner/browse-dotfiles)
(:prefix "o"
:desc "(H)ckrnews" "H" #'hackernews
:desc "(R)SS" "R" #'=rss
:desc "(M)ail" "M" #'=notmuch
:desc "(L)obste.rs" "L" #'ivy-lobsters)
(:prefix "b"
:desc "Black format buffer" "f" #'blacken-buffer
:desc "isort buffer" "I" #'py-isort-buffer
:desc "Links in buffer" "l" #'ace-link-org)
(:prefix "s"
:desc "Search the web" "w" #'web-search
:desc "Goto URL in eww" "u" #'eww-browse-url
:desc "Search in eww" "3" #'eww-search-words
:desc "Search all the things" "g" #'deadgrep))
(setq wttrin-default-cities '("Castine, ME" "San Francisco" "Thessaloniki"))
(setq wttrin-default-accept-language '("Accept-Language" . "en-US"))
(map!
(:leader
(:prefix "o"
:desc "(W)eather" "W" #'wttrin)))
(setq libmpdel-hostname "mpd.unbl.ink")
(defun mpdel-playlist-play ()
"Start playing the song at point."
(interactive)
(if (derived-mode-p 'mpdel-playlist-current-playlist-mode)
(libmpdel-play-song (navigel-entity-at-point))
(mpdel-core-insert-current-playlist)))
(map! :leader
(:prefix "-"
:desc "MPD Open playlist" "-" #'mpdel-playlist-open
:desc "MPD Remove at point" "d" #'mpdel-playlist-delete
:desc "MPD Start at point" "s" #'mpdel-playlist-play
:desc "MPD Next track" "n" #'libmpdel-playback-next
:desc "MPD Previous track" "p" #'libmpdel-playback-previous))
(setq elfeed-protocol-ttrss-maxsize 200) ;; bigger than 200 is invalid
(setq elfeed-feeds '("ttrss+https://powellc:hT7nPKAHa^fYwXZ*@reader.unbl.ink"))
(setq elfeed-log-level 'debug)
(elfeed-protocol-enable)
;; Schedule feed update for every day at 3PM
(run-at-time "15 min" nil 'elfeed-update)
(setq elfeed-search-filter "@2-days-ago +unread")
(defun elfeed-search-format-date (date)
(format-time-string "%Y-%m-%d %H:%M" (seconds-to-time date)))
; Serif font in Elfeed
(add-hook! 'elfeed-mode-hook 'variable-pitch-mode)
(add-hook! 'elfeed-show-mode-hook (text-scale-set 1.2))
(defun unfill-paragraph ()
"Takes a multi-line paragraph and makes it into a single line of text."
(interactive)
(let ((fill-column (point-max)))
(fill-paragraph nil)))
(define-key global-map "\M-z" 'unfill-paragraph)
;; PlantUML is awesome for quick diagrams
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
;; Timezone location strings at http://worldtime.io
(setq display-time-world-list '(("America/Los_Angeles" "San Francisco")
("America/Tegucigalpa" "Tegucigalpa")
("America/New_York" "New York")
("Europe/London" "London")
("Europe/Warsaw" "Warsaw")
("Europe/Kiev" "Lviv")))
(flycheck-define-checker vale
"A checker for prose"
:command ("vale" "--output" "line"
source)
:standard-input nil
:error-patterns
((error line-start (file-name) ":" line ":" column ":" (id (one-or-more (not (any ":")))) ":" (message) line-end))
:modes (markdown-mode org-mode text-mode)
)
(add-to-list 'flycheck-checkers 'vale 'append)
(add-hook 'org-mode-hook #'doom-disable-line-numbers-h)
(after! org
(setq org-directory (expand-file-name "~/var/org/")
org-agenda-files (list org-directory)
org-pretty-entities t
org-agenda-dim-blocked-tasks nil
org-log-done 'time
org-hide-emphasis-markers t
org-fontify-whole-heading-line t
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-ellipsis ""
org-image-actual-width '(600)
org-capture-templates
'(("i" "Send to inbox" entry (file "~/var/org/inbox.org")
"* TODO %?\n"))
org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "MAYBE(m)" "|" "DONE(d)" "WONTDO(w)"))
org-modules '(ol-eshell
ol-notmuch
ob-eval
ob-exp
ob-http
org-id)))
;; Dont display git gutter in org mode
;; With tree folding, it's pretty much useless
(after! git-gutter
(setq git-gutter:disabled-modes '(org-mode image-mode)))
;; Refiling
(setq org-refile-targets '(("~/var/org/inbox.org" :maxlevel . 9)))
(setq org-outline-path-complete-in-steps nil) ; Refile in a single go
(setq org-refile-use-outline-path t) ; Show full paths for refiling
(setq +inbox-file "~/var/org/inbox.org")
(defun +open-inbox-file ()
(interactive)
"Opens the inbox file"
(find-file +inbox-file))
(map!
:leader
:desc "Open inbox" "I" #'+open-inbox-file
:desc "Save all org buffers" "A" #'org-save-all-org-buffers)
(setq org-agenda-span 3
org-agenda-start-day "1d")
(defun +show-agenda ()
(interactive)
(delete-other-windows)
(with-popup-rules! nil
(org-agenda-list)
(calendar))
(other-window 1)
(split-window-vertically)
(other-window 1)
(find-file +todo-file))
(setq org-roam-directory "~/var/org/")
(setq org-fc-directories "~/var/org/")
(require 'org-fc-hydra)
(require 'justify-kp)
;(setq nov-text-width t)
(setq nov-text-width 100)
(defun my-nov-window-configuration-change-hook ()
(my-nov-post-html-render-hook)
(remove-hook 'window-configuration-change-hook
'my-nov-window-configuration-change-hook
t))
(defun my-nov-post-html-render-hook ()
(if (get-buffer-window)
(let ((max-width (pj-line-width))
buffer-read-only)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(when (not (looking-at "^[[:space:]]*$"))
(goto-char (line-end-position))
(when (> (shr-pixel-column) max-width)
(goto-char (line-beginning-position))
(pj-justify)))
(forward-line 1))))
(add-hook 'window-configuration-change-hook
'my-nov-window-configuration-change-hook
nil t)))
(add-hook 'nov-post-html-render-hook 'my-nov-post-html-render-hook)
(defun my-nov-font-setup ()
(face-remap-add-relative 'variable-pitch :family "Noto Serif Regular"
:height 1.0
:size 16))
(add-hook 'nov-mode-hook 'my-nov-font-setup)
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
;(add-hook 'nov-mode-hook 'variable-pitch-mode)
;(load! "+mail") ;; Mail stuff
; Use w3m to parse HTML email
(setq mm-text-html-renderer 'w3m)
(setq w3m-fill-column 88)
; Kill email message buffers when you close them
(setq message-kill-buffer-on-exit t)
(setq message-auto-save-directory "~/Mail/colin@unbl.ink/Drafts/")
(setq message-directory "~/Mail/colin@unbl.ink/")
;;; Setup sending email with msmtp
;; sendmail-program "/usr/local/bin/msmtpq" <--- this doesn't work as advertised right now
(setq send-mail-function 'sendmail-send-it
sendmail-program "/usr/local/bin/msmtp"
mail-specify-envelope-from t
message-sendmail-f-is-evil t
message-sendmail-envelope-from 'header
message-sendmail-extra-arguments '("--read-envelope-from")
mail-envelope-from 'header)
(map! :leader
(:prefix "e"
:desc "(s)end queued mail" "s" #'smtpmail-send-queued-mail
:desc "Open (i)nbox" "i" #'=notmuch
:desc "Open (n)otmuch" "n" #'notmuch
:desc "(C)ompose mail" "c" #'notmuch-mua-new-mail))
(after! eshell
(set-eshell-alias!
"djtest" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py test $*"
"djpytest" "DJANGO_SETTINGS_MODULE=ff.settings.ci pytest --reuse-db --black --flake8 --isort --durations=3 $*"
"djsh" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py shell_plus"
"dj" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py $*"
"f" "(other-window 1) && find-file $1"
"l" "ls -lh"
"d" "dired $1"
"gl" "(call-interactively 'magit-log-current)"
"gs" "magit-status"
"gc" "magit-commit"))
;(add-hook 'python-mode-hook 'eglot-ensure)
(setq mastodon-instance-url "https://mastodon.technology")
(map! :leader
(:prefix "="
:desc "Open mastodon" "=" #'mastodon
:desc "Update Mastodon timeline" "u" #'mastodon-tl--update
:desc "Toot to Mastodon" "t" #'mastodon-toot))
(use-package! slack
:commands (slack-start)
:init
(setq slack-buffer-emojify t)
(setq slack-prefer-current-team t)
:config
(slack-register-team
:name "15five"
:token (auth-source-pick-first-password
:host "15five.slack.com"
:user "colin.powell@15five.com")
:subscribed-channels '(squad-admin water-cooler))
(slack-register-team
:name "RAB"
:token (auth-source-pick-first-password
:host "randomaccessbrewery.slack.com"
:user "colin@onec.me")
:subscribed-channels '(the_taps random))
(evil-define-key 'normal slack-info-mode-map
",u" 'slack-room-update-messages)
(evil-define-key 'normal slack-mode-map
",c" 'slack-buffer-kill
",ra" 'slack-message-add-reaction
",rr" 'slack-message-remove-reaction
",rs" 'slack-message-show-reaction-users
",pl" 'slack-room-pins-list
",pa" 'slack-message-pins-add
",pr" 'slack-message-pins-remove
",mm" 'slack-message-write-another-buffer
",me" 'slack-message-edit
",md" 'slack-message-delete
",u" 'slack-room-update-messages
",2" 'slack-message-embed-mention
",3" 'slack-message-embed-channel
"\C-n" 'slack-buffer-goto-next-message
"\C-p" 'slack-buffer-goto-prev-message)
(evil-define-key 'normal slack-edit-message-mode-map
",k" 'slack-message-cancel-edit
",s" 'slack-message-send-from-buffer
",2" 'slack-message-embed-mention
",3" 'slack-message-embed-channel))
(use-package! alert
:commands (alert)
:init
(setq alert-default-style 'libnotify))
(map! :leader
(:prefix "o"
(:prefix ("s" . "+slack")
:desc "Slack channels" "S" #'slack-start
:desc "Slack channels" "s" #'slack-channel-select
:desc "Slack IMs" "i" #'slack-im-select
:desc "Slack groups" "g" #'slack-group-select
:desc "Slack threads" "t" #'slack-all-threads)))
(load! "beancount")
(require 'beancount)
(add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode))
(define-derived-mode
pandoc-view-mode
markdown-mode
"pandoc-view-mode"
"View pandoc processing of docx file using markdown mode."
(erase-buffer)
(let* ((pandoc (executable-find "pandoc")))
(insert (shell-command-to-string
(concat pandoc " --wrap=none " (shell-quote-argument (buffer-file-name)) " -t markdown"))))
(not-modified)
(read-only-mode t))
(add-to-list 'auto-mode-alist '("\\.docx\\'" . pandoc-view-mode))
;;(add-hook 'magit-mode-hook #'doom-disable-line-numbers-h)
(setq +magit-hub-features t ;; I want the PR/issue stuff too!
+magit-hub-enable-by-default t) ;; And I want it on by default!
(after! magit
(magit-wip-after-save-mode t)
(magit-wip-after-apply-mode t)
(setq magit-save-repository-buffers 'dontask
magit-circleci-token "097bf0dd808ad9103d489844e37cecffdf967837"
magit-repository-directories '(("~/src/" . 3)
("~/dotfiles/" . 0))
magit-popup-display-buffer-action nil ;; Not sure why this is here, wonder what it does
magit-display-file-buffer-function #'switch-to-buffer-other-window
magithub-clone-default-directory "~/src" ;; I want my stuff to clone to ~/projects
magithub-preferred-remote-method 'ssh_url)) ;; HTTPS cloning is awful, i authenticate with ssh keys.
(setq lsp-enable-links nil)
(when (require 'openwith nil 'noerror)
(setq openwith-associations
(list
(list (openwith-make-extension-regexp
'("mpg" "mpeg" "mp3" "mp4"
"avi" "wmv" "wav" "mov" "flv"
"ogm" "ogg" "mkv"))
"vlc"
'(file))
(list (openwith-make-extension-regexp
'("pdf" "ps" "ps.gz" "dvi"))
"zathura"
'(file))
))
(openwith-mode 1))

497
emacs/.doom.d/config.org Normal file
View File

@ -0,0 +1,497 @@
#+TITLE: DOOM Emacs Configuration
This configuration of Emacs is highly opinionated.
* Basics
My identity. Used in a handful of places in Emacs to pre-populate authorship and such.
#+BEGIN_SRC emacs-lisp
(setq user-full-name "Colin Powell"
user-mail-address "colin@unbl.ink")
#+END_SRC
From a friend at [[https://discord.com/channels/406534637242810369/695450585758957609/715126265715097600][Discord]]
#+BEGIN_SRC emacs-lisp
(setq ivy-read-action-function #'ivy-hydra-read-action)
#+END_SRC
* User interface
** Fonts and themes
I change my default theme almost as often as the weather. I tend to revert back
to Doom One most of the time, but I like the Kaolin themes, as well as Nimbus
for it's retro charm. Nimbus just doesn't look great when I'm tired though.
#+BEGIN_SRC emacs-lisp
(setq doom-theme 'doom-old-hope
doom-font (font-spec :family "JetBrains Mono NL" :size 14 :weight 'semi-light)
doom-big-font (font-spec :family "JetBrains Mono NL" :size 18)
doom-variable-pitch-font (font-spec :family "Overpass" :size 16))
#+END_SRC
** Borders
Barring the unfortunate end of X11 development and my eventual transition to
wayland and sway, you can pry i3wm from my cold, dead hands. One problem,
however is that when you're trying your best to rice up i3, Emacs needs a padded
border.
#+BEGIN_SRC emacs-lisp
;; Applies to current frame
;(set-frame-parameter nil 'internal-border-width 10) ; applies to the current frame
;; If we create new frames (via emacsclient) this will do the trick
;(add-to-list 'default-frame-alist '(internal-border-width . 10))
#+END_SRC
** Fringe
#+BEGIN_SRC emacs-lisp
(nyan-mode) ;; progress in the form of a rainbow cat.
(add-hook 'after-init-hook #'global-emojify-mode) ;; emojis?!
(add-hook 'prog-mode-hook #'goto-address-mode) ;; linify links!
#+END_SRC
* Keybindings
#+BEGIN_SRC emacs-lisp
(map! ;; Easier window movement
:n "C-h" 'evil-window-left
:n "C-j" 'evil-window-down
:n "C-k" 'evil-window-up
:n "C-l" 'evil-window-right
(:map evil-treemacs-state-map
"C-h" 'evil-window-left
"C-l" 'evil-window-right)
:leader
(:prefix "f"
:desc "Find file in dotfiles" "t" #'+hlissner/find-in-dotfiles
:desc "Browse dotfiles" "T" #'+hlissner/browse-dotfiles)
(:prefix "o"
:desc "(H)ckrnews" "H" #'hackernews
:desc "(R)SS" "R" #'=rss
:desc "(M)ail" "M" #'=notmuch
:desc "(L)obste.rs" "L" #'ivy-lobsters)
(:prefix "b"
:desc "Black format buffer" "f" #'blacken-buffer
:desc "isort buffer" "I" #'py-isort-buffer
:desc "Links in buffer" "l" #'ace-link-org)
(:prefix "s"
:desc "Search the web" "w" #'web-search
:desc "Goto URL in eww" "u" #'eww-browse-url
:desc "Search in eww" "3" #'eww-search-words
:desc "Search all the things" "g" #'deadgrep))
#+END_SRC
* Weather
Wttrin is a pretty funny way to check weather. I like that you can copy and
paste fun a ASCII representations of the day's weather. It's not terribly
accurate though.
#+BEGIN_SRC emacs-lisp
(setq wttrin-default-cities '("Castine, ME" "San Francisco" "Thessaloniki"))
(setq wttrin-default-accept-language '("Accept-Language" . "en-US"))
(map!
(:leader
(:prefix "o"
:desc "(W)eather" "W" #'wttrin)))
#+END_SRC
* Music
Right now, just make sure I can connect to my local Mopidy server via MPDel.
#+BEGIN_SRC emacs-lisp
(setq libmpdel-hostname "mpd.unbl.ink")
(defun mpdel-playlist-play ()
"Start playing the song at point."
(interactive)
(if (derived-mode-p 'mpdel-playlist-current-playlist-mode)
(libmpdel-play-song (navigel-entity-at-point))
(mpdel-core-insert-current-playlist)))
(map! :leader
(:prefix "-"
:desc "MPD Open playlist" "-" #'mpdel-playlist-open
:desc "MPD Remove at point" "d" #'mpdel-playlist-delete
:desc "MPD Start at point" "s" #'mpdel-playlist-play
:desc "MPD Next track" "n" #'libmpdel-playback-next
:desc "MPD Previous track" "p" #'libmpdel-playback-previous))
#+END_SRC
* RSS
Here were going to use TinyTinyRSS as a backend store for our RSS feeds.
#+BEGIN_SRC emacs-lisp
(setq elfeed-protocol-ttrss-maxsize 200) ;; bigger than 200 is invalid
(setq elfeed-feeds '("ttrss+https://powellc:hT7nPKAHa^fYwXZ*@reader.unbl.ink"))
(setq elfeed-log-level 'debug)
(elfeed-protocol-enable)
;; Schedule feed update for every day at 3PM
(run-at-time "15 min" nil 'elfeed-update)
#+END_SRC
Then welll setup some nice defaults and font settings for viewing feeds in Elfeed.
#+BEGIN_SRC emacs-lisp
(setq elfeed-search-filter "@2-days-ago +unread")
(defun elfeed-search-format-date (date)
(format-time-string "%Y-%m-%d %H:%M" (seconds-to-time date)))
; Serif font in Elfeed
(add-hook! 'elfeed-mode-hook 'variable-pitch-mode)
(add-hook! 'elfeed-show-mode-hook (text-scale-set 1.2))
#+END_SRC
* Formatting
Here we define the opposite function to fill-paragraph and then map it to Meta-z, which helps when undoing fill paragraph moves.
#+BEGIN_SRC emacs-lisp
(defun unfill-paragraph ()
"Takes a multi-line paragraph and makes it into a single line of text."
(interactive)
(let ((fill-column (point-max)))
(fill-paragraph nil)))
(define-key global-map "\M-z" 'unfill-paragraph)
#+END_SRC
PlantUML is pretty fantastic. This enables a mode for editing plantuml files in Emacs.
#+BEGIN_SRC emacs-lisp
;; PlantUML is awesome for quick diagrams
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
#+END_SRC
Handy clock to look up what timezone my co-workers are in!
#+BEGIN_SRC emacs-lisp
;; Timezone location strings at http://worldtime.io
(setq display-time-world-list '(("America/Los_Angeles" "San Francisco")
("America/Tegucigalpa" "Tegucigalpa")
("America/New_York" "New York")
("Europe/London" "London")
("Europe/Warsaw" "Warsaw")
("Europe/Kiev" "Lviv")))
#+END_SRC
Vale linter, a more up to date proselint!
How I went about [[file:/usr/home/powellc/var/org/20200916134500-vale_prose_linter.org::*Installing Vale][installing Vale]]
#+BEGIN_SRC emacs-lisp
(flycheck-define-checker vale
"A checker for prose"
:command ("vale" "--output" "line"
source)
:standard-input nil
:error-patterns
((error line-start (file-name) ":" line ":" column ":" (id (one-or-more (not (any ":")))) ":" (message) line-end))
:modes (markdown-mode org-mode text-mode)
)
(add-to-list 'flycheck-checkers 'vale 'append)
#+END_SRC
* Org-mode
** Basic configuration
A handful of mods here clean up org mode. Line numbers dont mean much when youre folding and unfolding all the time. I also really enjoy the typography of a serif font when Im writing a lot of words.
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook #'doom-disable-line-numbers-h)
(after! org
(setq org-directory (expand-file-name "~/var/org/")
org-agenda-files (list org-directory)
org-pretty-entities t
org-agenda-dim-blocked-tasks nil
org-log-done 'time
org-hide-emphasis-markers t
org-fontify-whole-heading-line t
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-ellipsis ""
org-image-actual-width '(600)
org-capture-templates
'(("i" "Send to inbox" entry (file "~/var/org/inbox.org")
"* TODO %?\n"))
org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "MAYBE(m)" "|" "DONE(d)" "WONTDO(w)"))
org-modules '(ol-eshell
ol-notmuch
ob-eval
ob-exp
ob-http
org-id)))
;; Dont display git gutter in org mode
;; With tree folding, it's pretty much useless
(after! git-gutter
(setq git-gutter:disabled-modes '(org-mode image-mode)))
;; Refiling
(setq org-refile-targets '(("~/var/org/inbox.org" :maxlevel . 9)))
(setq org-outline-path-complete-in-steps nil) ; Refile in a single go
(setq org-refile-use-outline-path t) ; Show full paths for refiling
#+END_SRC
** Key bindings
I add only two custom mappings to the default org mode maps, a shortcut to my Inbox file and a quick way to save all open org mode files.
#+BEGIN_SRC emacs-lisp
(setq +inbox-file "~/var/org/inbox.org")
(defun +open-inbox-file ()
(interactive)
"Opens the inbox file"
(find-file +inbox-file))
(map!
:leader
:desc "Open inbox" "I" #'+open-inbox-file
:desc "Save all org buffers" "A" #'org-save-all-org-buffers)
#+END_SRC
** Agenda configuration
#+BEGIN_SRC emacs-lisp
(setq org-agenda-span 3
org-agenda-start-day "1d")
(defun +show-agenda ()
(interactive)
(delete-other-windows)
(with-popup-rules! nil
(org-agenda-list)
(calendar))
(other-window 1)
(split-window-vertically)
(other-window 1)
(find-file +todo-file))
#+END_SRC
** Org-roam
I am absolutely in love with [[https://org-roam.readthedocs.io/en/develop/][Org-roam]]. Everything about it makes taking notes easier. I just need to level up with Zettels and web publishing of my notes.
#+BEGIN_SRC emacs-lisp
(setq org-roam-directory "~/var/org/")
#+END_SRC
** Org-fc
Trying a new space-repetition framework.
#+BEGIN_SRC emacs-lisp
(setq org-fc-directories "~/var/org/")
(require 'org-fc-hydra)
#+END_SRC
* Novel
Reading novels in Emacs, how novel!
#+BEGIN_SRC emacs-lisp
(require 'justify-kp)
;(setq nov-text-width t)
(setq nov-text-width 100)
(defun my-nov-window-configuration-change-hook ()
(my-nov-post-html-render-hook)
(remove-hook 'window-configuration-change-hook
'my-nov-window-configuration-change-hook
t))
(defun my-nov-post-html-render-hook ()
(if (get-buffer-window)
(let ((max-width (pj-line-width))
buffer-read-only)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(when (not (looking-at "^[[:space:]]*$"))
(goto-char (line-end-position))
(when (> (shr-pixel-column) max-width)
(goto-char (line-beginning-position))
(pj-justify)))
(forward-line 1))))
(add-hook 'window-configuration-change-hook
'my-nov-window-configuration-change-hook
nil t)))
(add-hook 'nov-post-html-render-hook 'my-nov-post-html-render-hook)
(defun my-nov-font-setup ()
(face-remap-add-relative 'variable-pitch :family "Noto Serif Regular"
:height 1.0
:size 16))
(add-hook 'nov-mode-hook 'my-nov-font-setup)
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
;(add-hook 'nov-mode-hook 'variable-pitch-mode)
#+END_SRC
* Mail
** Basics
I use notmuch to read and write email from within Emacs.
#+BEGIN_SRC emacs-lisp
;(load! "+mail") ;; Mail stuff
; Use w3m to parse HTML email
(setq mm-text-html-renderer 'w3m)
(setq w3m-fill-column 88)
; Kill email message buffers when you close them
(setq message-kill-buffer-on-exit t)
(setq message-auto-save-directory "~/Mail/colin@unbl.ink/Drafts/")
(setq message-directory "~/Mail/colin@unbl.ink/")
;;; Setup sending email with msmtp
;; sendmail-program "/usr/local/bin/msmtpq" <--- this doesn't work as advertised right now
(setq send-mail-function 'sendmail-send-it
sendmail-program "/usr/local/bin/msmtp"
mail-specify-envelope-from t
message-sendmail-f-is-evil t
message-sendmail-envelope-from 'header
message-sendmail-extra-arguments '("--read-envelope-from")
mail-envelope-from 'header)
#+END_SRC
** Keybindings
#+BEGIN_SRC emacs-lisp
(map! :leader
(:prefix "e"
:desc "(s)end queued mail" "s" #'smtpmail-send-queued-mail
:desc "Open (i)nbox" "i" #'=notmuch
:desc "Open (n)otmuch" "n" #'notmuch
:desc "(C)ompose mail" "c" #'notmuch-mua-new-mail))
#+END_SRC
* Eshell
Handful of fun aliases to make working in Eshell almost like a /real/ shell :smile:
#+BEGIN_SRC emacs-lisp
(after! eshell
(set-eshell-alias!
"djtest" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py test $*"
"djpytest" "DJANGO_SETTINGS_MODULE=ff.settings.ci pytest --reuse-db --black --flake8 --isort --durations=3 $*"
"djsh" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py shell_plus"
"dj" "DJANGO_SETTINGS_MODULE=ff.settings.ci python manage.py $*"
"f" "(other-window 1) && find-file $1"
"l" "ls -lh"
"d" "dired $1"
"gl" "(call-interactively 'magit-log-current)"
"gs" "magit-status"
"gc" "magit-commit"))
#+END_SRC
* Coding
I once used LSP, but Emacs lsp-mode is flaky as hell. It works sometimes, but other times causes pyls to thrash the CPU. I don't need that, not when Eglot exists. This just makes sure Eglot runs in `python-mode`
#+BEGIN_SRC emacs-lisp
;(add-hook 'python-mode-hook 'eglot-ensure)
#+END_SRC
* Mastodon
There's gotta be a way to get the token out of password-store for this.
#+BEGIN_SRC emacs-lisp
(setq mastodon-instance-url "https://mastodon.technology")
(map! :leader
(:prefix "="
:desc "Open mastodon" "=" #'mastodon
:desc "Update Mastodon timeline" "u" #'mastodon-tl--update
:desc "Toot to Mastodon" "t" #'mastodon-toot))
#+END_SRC
* Slack
** Configure teams
#+BEGIN_SRC emacs-lisp
(use-package! slack
:commands (slack-start)
:init
(setq slack-buffer-emojify t)
(setq slack-prefer-current-team t)
:config
(slack-register-team
:name "15five"
:token (auth-source-pick-first-password
:host "15five.slack.com"
:user "colin.powell@15five.com")
:subscribed-channels '(squad-admin water-cooler))
(slack-register-team
:name "RAB"
:token (auth-source-pick-first-password
:host "randomaccessbrewery.slack.com"
:user "colin@onec.me")
:subscribed-channels '(the_taps random))
(evil-define-key 'normal slack-info-mode-map
",u" 'slack-room-update-messages)
(evil-define-key 'normal slack-mode-map
",c" 'slack-buffer-kill
",ra" 'slack-message-add-reaction
",rr" 'slack-message-remove-reaction
",rs" 'slack-message-show-reaction-users
",pl" 'slack-room-pins-list
",pa" 'slack-message-pins-add
",pr" 'slack-message-pins-remove
",mm" 'slack-message-write-another-buffer
",me" 'slack-message-edit
",md" 'slack-message-delete
",u" 'slack-room-update-messages
",2" 'slack-message-embed-mention
",3" 'slack-message-embed-channel
"\C-n" 'slack-buffer-goto-next-message
"\C-p" 'slack-buffer-goto-prev-message)
(evil-define-key 'normal slack-edit-message-mode-map
",k" 'slack-message-cancel-edit
",s" 'slack-message-send-from-buffer
",2" 'slack-message-embed-mention
",3" 'slack-message-embed-channel))
(use-package! alert
:commands (alert)
:init
(setq alert-default-style 'libnotify))
#+END_SRC
** Key bindings
#+BEGIN_SRC emacs-lisp
(map! :leader
(:prefix "o"
(:prefix ("s" . "+slack")
:desc "Slack channels" "S" #'slack-start
:desc "Slack channels" "s" #'slack-channel-select
:desc "Slack IMs" "i" #'slack-im-select
:desc "Slack groups" "g" #'slack-group-select
:desc "Slack threads" "t" #'slack-all-threads)))
#+END_SRC
* Beancount
Use Emacs and plain text files for your accounting!
#+BEGIN_SRC emacs-lisp
(load! "beancount")
(require 'beancount)
(add-to-list 'auto-mode-alist '("\\.beancount\\'" . beancount-mode))
#+END_SRC
* Pandoc
Here we are trying to auto-translate Word and PDF files to be viewed in Emacs.
#+BEGIN_SRC emacs-lisp
(define-derived-mode
pandoc-view-mode
markdown-mode
"pandoc-view-mode"
"View pandoc processing of docx file using markdown mode."
(erase-buffer)
(let* ((pandoc (executable-find "pandoc")))
(insert (shell-command-to-string
(concat pandoc " --wrap=none " (shell-quote-argument (buffer-file-name)) " -t markdown"))))
(not-modified)
(read-only-mode t))
(add-to-list 'auto-mode-alist '("\\.docx\\'" . pandoc-view-mode))
#+END_SRC
* Magit
#+BEGIN_SRC emacs-lisp
;;(add-hook 'magit-mode-hook #'doom-disable-line-numbers-h)
(setq +magit-hub-features t ;; I want the PR/issue stuff too!
+magit-hub-enable-by-default t) ;; And I want it on by default!
(after! magit
(magit-wip-after-save-mode t)
(magit-wip-after-apply-mode t)
(setq magit-save-repository-buffers 'dontask
magit-circleci-token "097bf0dd808ad9103d489844e37cecffdf967837"
magit-repository-directories '(("~/src/" . 3)
("~/dotfiles/" . 0))
magit-popup-display-buffer-action nil ;; Not sure why this is here, wonder what it does
magit-display-file-buffer-function #'switch-to-buffer-other-window
magithub-clone-default-directory "~/src" ;; I want my stuff to clone to ~/projects
magithub-preferred-remote-method 'ssh_url)) ;; HTTPS cloning is awful, i authenticate with ssh keys.
(setq lsp-enable-links nil)
#+END_SRC
* Openwith
#+BEGIN_SRC emacs-lisp
(when (require 'openwith nil 'noerror)
(setq openwith-associations
(list
(list (openwith-make-extension-regexp
'("mpg" "mpeg" "mp3" "mp4"
"avi" "wmv" "wav" "mov" "flv"
"ogm" "ogg" "mkv"))
"vlc"
'(file))
(list (openwith-make-extension-regexp
'("pdf" "ps" "ps.gz" "dvi"))
"zathura"
'(file))
))
(openwith-mode 1))
#+END_SRC

50
emacs/.doom.d/custom.el Normal file
View File

@ -0,0 +1,50 @@
;;; custom.el --- -*- lexical-binding: t; -*-
;; Copyright (C) 2020 Colin Powell
;; Author: Colin Powell <colin@unbl.ink>
;; Keywords:
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(doom-big-font-mode t)
'(fci-rule-color "#504945")
'(jdee-db-active-breakpoint-face-colors (cons "#f0f0f0" "#a89984"))
'(jdee-db-requested-breakpoint-face-colors (cons "#f0f0f0" "#79740e"))
'(jdee-db-spec-breakpoint-face-colors (cons "#f0f0f0" "#928374"))
'(objed-cursor-color "#9d0006")
'(package-selected-packages
'(leuven-theme openwith caddyfile-mode wordgen w3m vterm-toggle ponylang-mode jq-mode jq-format hackernews elfeed-protocol dired-ranger csv-mode csv counsel-jq blacken))
'(pdf-view-midnight-colors (cons "#282828" "#fbf1c7"))
'(rustic-ansi-faces
["#fbf1c7" "#9d0006" "#79740e" "#b57614" "#076678" "#b16286" "#427b58" "#282828"])
'(vc-annotate-background "#fbf1c7")
'(vc-annotate-color-map
(list
(cons 20 "#79740e")
(cons 40 "#8d7410")
(cons 60 "#a17512")
(cons 80 "#b57614")
(cons 100 "#b3620e")
(cons 120 "#b14e08")
(cons 140 "#af3a03")
(cons 160 "#af472e")
(cons 180 "#b0545a")
(cons 200 "#b16286")
(cons 220 "#aa415b")
(cons 240 "#a32030")
(cons 260 "#9d0006")
(cons 280 "#9a2021")
(cons 300 "#97413c")
(cons 320 "#946258")
(cons 340 "#504945")
(cons 360 "#504945")))
'(vc-annotate-very-old-color nil))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(default ((t (:background "#151619" :family "JetBrains Mono NL" :foundry "JB " :slant normal :weight normal :height 135 :width normal)))))

195
emacs/.doom.d/init.el Normal file
View File

@ -0,0 +1,195 @@
;;; init.el -*- lexical-binding: t; -*-
;; This file controls what Doom modules are enabled and what order they load
;; in. Remember to run 'doom sync' after modifying it!
;; NOTE Press 'SPC h d h' (or 'C-h d h' for non-vim users) to access Doom's
;; documentation. There you'll find information about all of Doom's
;; modules and what flags they support.
;; NOTE Move your cursor over a module's name (or its flags) and press 'K' (or
;; 'C-c g k' for non-vim users) to view its documentation. This works on
;; flags as well (those symbols that start with a plus).
;;
;; Alternatively, press 'gd' (or 'C-c g d') on a module to browse its
;; directory (for easy access to its source code).
(doom! :input
;;chinese
;;japanese
:completion
(company ; the ultimate code completion backend
+childframe)
;;helm ; the *other* search engine for love and life
;;ido ; the other *other* search engine...
(ivy ; a search engine for love and life
+fuzzy
+icons)
:ui
;;deft ; notational velocity for Emacs
doom ; what makes DOOM look the way it does
doom-dashboard ; a nifty splash screen for Emacs
doom-quit ; DOOM quit-message prompts when you quit Emacs
;;fill-column ; a `fill-column' indicator
hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW
;;hydra
;;indent-guides ; highlighted indent columns
ligatures ;
;minimap ; show a map of the code on the side
modeline ; snazzy, Atom-inspired modeline, plus API
nav-flash ; blink cursor line after big motions
;;neotree ; a project drawer, like NERDTree for vim
ophints ; highlight the region an operation acts on
(popup
+all
+defaults) ; tame sudden yet inevitable temporary windows
;;tabs ; an tab bar for Emacs
treemacs ; a project drawer, like neotree but cooler
unicode ; extended unicode support for various languages
vc-gutter ; vcs diff in the fringe
vi-tilde-fringe ; fringe tildes to mark beyond EOB
(window-select +numbers) ; visually switch windows
workspaces ; tab emulation, persistence & separate workspaces
zen ; distraction-free coding or writing
:editor
(evil +everywhere); come to the dark side, we have cookies
file-templates ; auto-snippets for empty files
fold ; (nigh) universal code folding
(format +onsave) ; automated prettiness
;;god ; run Emacs commands without modifier keys
;;lispy ; vim for lisp, for people who don't like vim
multiple-cursors ; editing in many places at once
;;objed ; text object editing for the innocent
;;parinfer ; turn lisp into python, sort of
rotate-text ; cycle region at point between text candidates
snippets ; my elves. They type so I don't have to
word-wrap ; soft wrapping with language-aware indent
:emacs
(dired +icons) ; making dired pretty [functional]
electric ; smarter, keyword-based electric-indent
(ibuffer +icons) ; interactive buffer management
(undo +tree) ; persistent, smarter undo for your inevitable mistakes
vc ; version-control and Emacs, sitting in a tree
:term
eshell ; the elisp shell that works everywhere
;;shell ; simple shell REPL for Emacs
;;term ; basic terminal emulator for Emacs
vterm ; the best terminal emulation in Emacs
:checkers
syntax ; tasing you for every semicolon you forget
spell ; tasing you for misspelling mispelling
grammar ; tasing grammar mistake every you make
:tools
;;ansible
;;debugger ; FIXME stepping through code, to help you add bugs
direnv
;;docker
editorconfig ; let someone else argue about tabs vs spaces
;;ein ; tame Jupyter notebooks with emacs
(eval +overlay) ; run code, run (also, repls)
gist ; interacting with github gists
(lookup ; navigate your code and its documentation
+dictionary
+docsets)
lsp
magit ; a git porcelain for Emacs
make ; run make tasks from Emacs
pass ; password manager for nerds
pdf ; pdf enhancements
;;prodigy ; FIXME managing external services & code builders
;;rgb ; creating color strings
;;taskrunner ; taskrunner for all your projects
;;terraform ; infrastructure as code
;;tmux ; an API for interacting with tmux
;;upload ; map local to remote projects via ssh/ftp
:lang
;;agda ; types of types of types of types...
;;cc ; C/C++/Obj-C madness
;;clojure ; java with a lisp
;;common-lisp ; if you've seen one lisp, you've seen them all
;;coq ; proofs-as-programs
crystal ; ruby at the speed of c
;;csharp ; unity, .NET, and mono shenanigans
data ; config/data formats
;;(dart +flutter) ; paint ui and not much else
;;elixir ; erlang done right
;;elm ; care for a cup of TEA?
emacs-lisp ; drown in parentheses
;;erlang ; an elegant language for a more civilized age
;;ess ; emacs speaks statistics
;;faust ; dsp, but you get to keep your soul
;;fsharp ; ML stands for Microsoft's Language
;;fstar ; (dependent) types and (monadic) effects and Z3
;;gdscript ; the language you waited for
(go +lsp) ; the hipster dialect
;;(haskell +dante) ; a language that's lazier than I am
;;hy ; readability of scheme w/ speed of python
;;idris ;
;;json ; At least it ain't XML
;;(java +meghanada) ; the poster child for carpal tunnel syndrome
(javascript +lsp) ; all(hope(abandon(ye(who(enter(here))))))
;;julia ; a better, faster MATLAB
;;kotlin ; a better, slicker Java(Script)
;;latex ; writing papers in Emacs has never been so fun
;;lean
;;factor
ledger ; an accounting system in Emacs
;;lua ; one-based indices? one-based indices
markdown ; writing docs for people to ignore
nim ; python + lisp at the speed of c
;;nix ; I hereby declare "nix geht mehr!"
;;ocaml ; an objective camel
(org ; organize your plain life in plain text
+hugo
+dragndrop
+gnuplot
+ipython ; ipython support for babel
+journal
+pretty
+roam
+pandoc ; pandoc integration into org's exporter
+pomodoro
+present) ; using Emacs for presentations
;;perl ; write code no one else can comprehend
;;php ; perl's insecure younger brother
plantuml ; diagrams for confusing people more
;;purescript ; javascript, but functional
(python +lsp +pyright) ; beautiful is better than ugly
;;qt ; the 'cutest' gui framework ever
;;racket ; a DSL for DSLs
rest ; Emacs as a REST client
rst ; ReST in peace
(ruby +rails +lsp) ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
(rust +lsp) ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
;;scala ; java, but good
;;scheme ; a fully conniving family of lisps
sh ; she sells {ba,z,fi}sh shells on the C xor
;;sml
;;solidity ; do you need a blockchain? No.
;;swift ; who asked for emoji variables?
;;terra ; Earth and Moon in alignment for performance.
web ; the tubes
yaml ; JSON, but readable
:email
;;(mu4e +gmail)
notmuch
;;(wanderlust +gmail)
:app
;;calendar
irc ; how neckbeards socialize
rss ; emacs as an RSS reader
;;twitter ; twitter client https://twitter.com/vnought
:config
literate
(default +bindings +smartparens))

65
emacs/.doom.d/packages.el Normal file
View File

@ -0,0 +1,65 @@
;; -*- no-byte-compile: t; -*-
;;; $DOOMDIR/packages.el
;;;
;; Snippets! From hlissner!
(package! emacs-snippets
:recipe (:host github
:repo "hlissner/emacs-snippets"
:files ("*")))
;(package! evil-matchit
; :recipe (:host github
; :repo "redguardtoo/evil-matchit"))
; For making Nov.el look nice
(package! justify-kp
:recipe (:host github
:repo "Fuco1/justify-kp"))
(package! hydra)
(package! org-fc
:recipe(:host github
:repo "l3kn/org-fc"
:files (:defaults "awk" "demo.org")))
;(package! eglot)
;; python stuffs
(package! blacken)
;;(package! pylint)
;;(package! py-isort)
;;(package! importmagic)
;; org stuffs
(package! ob-http)
(package! org-web-tools)
(package! org-snooze)
(package! org-alert)
;;(package! org-vcard)
;;(package! org-drill)
;;(package! org-superstar)
;; handy tools
(package! w3m)
(package! nov)
(package! git-link)
(package! ivy-lobsters)
(package! web-search)
(package! mpdel)
(package! ivy-mpdel)
(package! elfeed-protocol)
(package! deadgrep)
(package! mastodon)
(package! magit-circleci)
;(package! smog)
(package! wordgen)
(package! openwith)
;; slack ... okay one more time
(package! slack)
;; pretty tings up
(package! srcery-theme)
(package! kaolin-themes)
(package! nyan-mode)
(package! emojify)