My Spacemacs User Config
*1 Preamble
2 Coding
2.1 PHP
2.1.1 Set up keyboard shortcuts for PHPUnit
(with-eval-after-load 'php-mode (define-key php-mode-map (kbd "C-c C-t t") 'phpunit-current-test) (define-key php-mode-map (kbd "C-c C-t c") 'phpunit-current-class) (define-key php-mode-map (kbd "C-c C-t p") 'phpunit-current-project))
2.1.2 Use web-mode for Laravel templates.
(add-to-list 'auto-mode-alist '("\\.blade.php\\'" . web-mode))
3 Productivity
3.1 org
3.1.1 Agenda
3.1.1.1 Use org-super-agenda a nicer looking agenda.
(org-super-agenda-mode) (setq org-agenda-custom-commands '(("g" "Super groups" agenda "" ((org-super-agenda-groups '((:auto-property "agenda-group"))))) ("u" "Super view" agenda "" ((org-super-agenda-groups '(;; Each group has an implicit boolean OR operator between its selectors. (:name "Today" ; Optionally specify section name :time-grid t ; Items that appear on the time grid :tag "today" :todo "TODAY") ; Items that have this TODO keyword (:name "Important" ;; Single arguments given alone :tag "bills" :priority "A") ;; Set order of multiple groups at once (:name "Quick wins (< 20 mins)" :effort< "0:20") (:name "Cleaning" :tag "cleaning" :order 5) (:name "Chores" :tag "chore" :order 5) (:name "Stuck" :tag "stuck" :order 2) (:name "Town" :tag ("town" "@town") :order 9) (:order-multi (2 (:name "Shopping in town" ;; Boolean AND group matches items that match all subgroups :and (:tag "shopping" :tag "@town")) ;;(:name "Personal" ;; :habit t ;; :tag "personal") (:name "Food-related" ;; Multiple args given in list with implicit OR :tag ("food" "dinner")))) ;; Groups supply their own section names when none are given (:todo "WAITING" :order 8) ; Set order of this section (:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING") ;; Show this group at the end of the agenda (since it has the ;; highest number). If you specified this group last, items ;; with these todo keywords that e.g. have priority A would be ;; displayed in that group instead, because items are grouped ;; out in the order the groups are listed. :order 9) (:priority<= "B" ;; Show this section after "Today" and "Important", because ;; their order is unspecified, defaulting to 0. Sections ;; are displayed lowest-number-first. :order 3) ;; After the last group, the agenda will display items that didn't ;; match any of these groups, with the default order position of 99 ))))))
3.1.2 Capturing
3.1.2.1 capture templates
(require 'org-protocol) (add-to-list 'load-path "/home/neil/.emacs.d/private/org-protocol-capture-html") (require 'org-protocol-capture-html) (setq org-capture-templates (quote (("c" "TODO scheduled today" entry (file+headline "~/org/_GTD.org" "Inbox") "** TODO %?\n SCHEDULED: %t\n") ("w" "Web site" entry (file+olp "/home/shared/commonplace/clippings.org" "Clippings") "** %c :website:\n%U %?%:initial")))) ;; to start in insert mode when creating via capture template (add-hook 'org-capture-mode-hook 'evil-insert-state)
3.1.3 Refiling
(setq org-refile-targets '((nil :maxlevel . 9) (org-agenda-files :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
3.1.4 Babel
;; babel (with-eval-after-load 'org (org-babel-do-load-languages 'org-babel-load-languages '((sql . t) (python . t) (plantuml . t) (sqlite . t) (shell . t))))
3.1.5 Misc
3.1.5.1 Deleting links
See: https://emacs.stackexchange.com/questions/10707/in-org-mode-how-to-remove-a-link
(defun ngm/org-delete-link () "Replace an org link of the format [[LINK][DESCRIPTION]] with DESCRIPTION. If the link is of the format [[LINK]], delete the whole org link. In both the cases, save the LINK to the kill-ring. Execute this command while the point is on or after the hyper-linked org link." (interactive) (when (derived-mode-p 'org-mode) (let ((search-invisible t) start end) (save-excursion (when (re-search-backward "\\[\\[" nil :noerror) (when (re-search-forward "\\[\\[\\(.*?\\)\\(\\]\\[.*?\\)*\\]\\]" nil :noerror) (setq start (match-beginning 0)) (setq end (match-end 0)) (kill-new (match-string-no-properties 1)) ; Save the link to kill-ring (replace-regexp "\\[\\[.*?\\(\\]\\[\\(.*?\\)\\)*\\]\\]" "\\2" nil start end)))))))
3.1.5.2 org-timeline
(require 'org-timeline) (add-hook 'org-agenda-finalize-hook 'org-timeline-insert-timeline :append)
4 Writing and knowledge management
I do my writing mostly in org-journal and org-roam.
(setq org-journal-file-format "%Y-%m-%d.org")
4.1 Writing mode
A couple of customisations to make writing prose a nice experience.
(defun ngm-visual-line-motion () "So j and k move up and down more like you'd expect in visual line mode" (interactive) (define-key evil-motion-state-map "j" 'evil-next-visual-line) (define-key evil-motion-state-map "k" 'evil-previous-visual-line)) (defun ngm-journal-mode () "Set up journalling mode the way that I like it" (interactive) (olivetti-mode) (variable-pitch-mode 1) (face-remap-add-relative 'variable-pitch '(:family "Roboto Slab" :height 140)) (ngm-visual-line-motion) (setq company-backends '(company-capf)) ; for org-roam completion )
4.2 org-roam
org-roam builds on top of org-mode, but I feel like it deserves it's own section.
4.2.1 Prefer immediate DB update method.
This updates the DB on save, rather than on an idle timer. I was finding idle timer frustrating, as the unexpected DB update interrupted my flow. Updating on save works better for me, as I tend to pause momentarily after a save anyway, as I usually save at the end of a sentence.
(setq org-roam-db-update-method 'immediate)
4.2.2 Wikilink syntax for adding links
For inserting links to other wiki pages more quickly, essentially with wikilink syntax. See: Using fuzzy links AKA wikilinks in org-roam.
(require 'key-chord) (key-chord-mode 1) (key-chord-define org-mode-map "[[" #'ngm/insert-roam-link) (defun ngm/insert-roam-link () "Inserts an Org-roam link." (interactive) (insert "[[roam:]]") (backward-char 2))
4.2.3 Tags
(setq org-roam-tag-sources '(prop last-directory))
4.2.4 org-roam capture templates
Add CREATED and LASTMODIFIED properties to the new note.
(setq org-roam-capture-templates '(("d" "default" plain (function org-roam--capture-get-point) "%?" :file-name "${slug}" :head "#+title: ${title}\n#+CREATED: %U\n#+LAST_MODIFIED: %U\n\n" :unnarrowed t))) (setq org-roam-dailies-directory "journal") (setq org-roam-dailies-capture-templates '(("d" "daily" plain (function org-roam-capture--get-point) "" :immediate-finish t :file-name "journal/%<%Y-%m-%d>" :head "#+TITLE: %<%Y-%m-%d>")))
4.2.5 Updating timestamps on save
I would prefer to do this on org-roam files only. See Update a field (#+LASTMODIFIED: ) at save - How To - Org-roam. Doesn't seem to work though.
(setq time-stamp-active t time-stamp-start "#\\+LAST_MODIFIED:[ \t]*" time-stamp-end "$" time-stamp-format "\[%04y-%02m-%02d %3a %02H:%02M\]") (add-hook 'before-save-hook 'time-stamp nil)
4.2.6 Graph settings
Exclude some of the big files from the graph.
(setq org-roam-graph-exclude-matcher '("sitemap" "index" "recentchanges"))
4.2.7 org-roam-server
(setq org-roam-server-light-dir "~/Code/org-roam-server-light") (setq org-roam-server-light-network-vis-options "{ \"edges\": { \"arrows\": { \"to\": { \"enabled\": true,\"scaleFactor\": 1.5 } } } }" ;; change background color of web application org-roam-server-light-style "body.darkmode { background-color: #121212!important; }" ;; set default set of excluded or included tags ;; customize only the value of id, in this case "test" and "journal" org-roam-server-light-default-exclude-filters "[{ \"tags\": \"journal\", \"id\" : \"Recent changes\", \"id\":\"recentchanges\" }]" ) ;; finally load the main elisp file (load (expand-file-name "org-roam-server-light.el" org-roam-server-light-dir)) (setq org-roam-server-default-exclude-filters "[{ \"tags\": \"journal\", \"id\" : \"Recent changes\", \"id\":\"recentchanges\" }]")
5 Look'n'feel
5.1 Themes
(doom-themes-treemacs-config) (doom-themes-org-config)
5.2 Solaire
See https://github.com/hlissner/emacs-solaire-mode
(require 'solaire-mode) ;; Enable solaire-mode anywhere it can be enabled (solaire-global-mode +1) ;; To enable solaire-mode unconditionally for certain modes: (add-hook 'ediff-prepare-buffer-hook #'solaire-mode) ;; ...if you use auto-revert-mode, this prevents solaire-mode from turning ;; itself off every time Emacs reverts the file (add-hook 'after-revert-hook #'turn-on-solaire-mode) ;; highlight the minibuffer when it is activated: (add-hook 'minibuffer-setup-hook #'solaire-mode-in-minibuffer) ;; if the bright and dark background colors are the wrong way around, use this ;; to switch the backgrounds of the `default` and `solaire-default-face` faces. ;; This should be used *after* you load the active theme! ;; ;; NOTE: This is necessary for themes in the doom-themes package! (solaire-mode-swap-bg)
5.3 Tabs (centaur)
Not currently using this, as I think it broke something.
;; centaur-tabs configuration ;; https://github.com/ema2159/centaur-tabs ;(require 'centaur-tabs) ;(centaur-tabs-mode t) ;(global-set-key (kbd "C-<prior>") 'centaur-tabs-backward) ;(global-set-key (kbd "C-<next>") 'centaur-tabs-forward) ;(centaur-tabs-mode) ;(centaur-tabs-headline-match) ;(setq centaur-tabs-set-modified-marker t ; centaur-tabs-modified-marker " ● " ; centaur-tabs-cycle-scope 'tabs ; centaur-tabs-height 35 ; centaur-tabs-set-icons t ; centaur-tabs-close-button " × ") ;(dolist (centaur-face '(centaur-tabs-selected ; centaur-tabs-selected-modified ; centaur-tabs-unselected ; centaur-tabs-unselected-modified)) ; (set-face-attribute centaur-face nil :family "Noto Sans Mono" :height 100))
5.4 Helm
(defun open-local-file-projectile (directory) "Helm action function, open projectile file within DIRECTORY specify by the keyword projectile-default-file define in `dir-locals-file'" (let ((default-file (f-join directory (nth 1 (car (-tree-map (lambda (node) (when (eq (car node) 'projectile-default-file) (format "%s" (cdr node)))) (dir-locals-get-class-variables (dir-locals-read-from-dir directory)))))))) (if (f-exists? default-file) (find-file default-file) (message "The file %s doesn't exist in the select project" default-file) ) ) ) (with-eval-after-load "helm-projectile" (helm-add-action-to-source "Open default file" 'open-local-file-projectile helm-source-projectile-projects) ) ;; (add-to-list 'helm-source-projectile-projects-actions '("Open default file" . open-local-file-projectile) t) ;; https://github.com/syl20bnr/spacemacs/issues/13100 ;(setq completion-styles '(helm-flex))
5.4.1 Remove duplicates in helm command history
See: https://github.com/syl20bnr/spacemacs/issues/13564
(setq history-delete-duplicates t)
6 Communications
6.1 mu4e (mail)
;; mu4e (setq mu4e-maildir "~/Maildir" mu4e-attachment-dir "~/downloads" mu4e-sent-folder "/Sent" mu4e-drafts-folder "/Drafts" mu4e-trash-folder "/Trash" mu4e-refile-folder "/Archive") (setq user-mail-address "neil@doubleloop.net" user-full-name "Neil Mather") ;; Get mail (setq mu4e-get-mail-command "mbsync protonmail" mu4e-change-filenames-when-moving t ; needed for mbsync mu4e-update-interval 120) ; update every 2 minutes (defun htmlize-and-send () "When in an org-mu4e-compose-org-mode message, htmlize and send it." (interactive) (when (member 'org~mu4e-mime-switch-headers-or-body post-command-hook) (org-mime-htmlize) (message-send-and-exit))) (add-hook 'org-ctrl-c-ctrl-c-hook 'htmlize-and-send t) ;; composing mail ;(setq mu4e-compose-format-flowed nil) ;(add-hook 'mu4e-compose-mode-hook (lambda () (turn-off-auto-fill) (use-hard-newlines -1))) ;; enable format=flowed ;; - mu4e sets up visual-line-mode and also fill (M-q) to do the right thing ;; - each paragraph is a single long line; at sending, emacs will add the ;; special line continuation characters. ;; - also see visual-line-fringe-indicators setting below (setq mu4e-compose-format-flowed t) ;; because it looks like email clients are basically ignoring format=flowed, ;; let's complicate their lives too. send format=flowed with looong lines. :) ;; https://www.ietf.org/rfc/rfc2822.txt (setq fill-flowed-encode-column 998) ;; in mu4e with format=flowed, this gives me feedback where the soft-wraps are (setq visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow)) ;; Send mail (setq message-send-mail-function 'smtpmail-send-it smtpmail-auth-credentials "~/.authinfo" ;; Here I assume you encrypted the credentials smtpmail-smtp-server "127.0.0.1" smtpmail-smtp-service 1025) ;; look'n'feel (setq mu4e-html2text-command 'mu4e-shr2text) (setq shr-color-visible-luminance-min 60) (setq shr-color-visible-distance-min 5) (setq shr-use-colors nil) (advice-add #'shr-colorize-region :around (defun shr-no-colourise-region (&rest ignore)))
6.2 IRC (erc)
(setq erc-hide-list '("JOIN" "PART" "QUIT"))
7 Misc
7.1 Tidal
;; tidal ;;(add-to-list 'load-path "/home/neil/.emacs.d/private/tidal") ;;(require 'tidal)