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 Use org-super-agenda a nicer looking agenda.
(setq org-agenda-custom-commands
      '(("g" "Super groups"
         agenda ""
           '((:auto-property "agenda-group")))))
        ("u" "Super view"
         agenda ""
           '(;; 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 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
       (("c" "TODO scheduled today"
         entry (file+headline "~/org/" "Inbox")
         "** TODO %?\n SCHEDULED: %t\n")
        ("w" "Web site"
         entry (file+olp "/home/shared/commonplace/" "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
    '((sql . t)
      (python . t)
      (plantuml . t)
      (sqlite . t)
      (shell . t))))

3.1.5 Misc Deleting links


(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."
  (when (derived-mode-p 'org-mode)
    (let ((search-invisible t) start end)
        (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))))))) 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 "")

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"
  (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"
  (variable-pitch-mode 1)
  (face-remap-add-relative 'variable-pitch '(:family "Roboto Slab" :height 140))
  (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."
  (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


5.2 Solaire


(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!

5.3 Tabs (centaur)

Not currently using this, as I think it broke something.

;; centaur-tabs configuration
                                      ;(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)
                                      ;(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
      (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"

    ;; (add-to-list 'helm-source-projectile-projects-actions '("Open default file" . open-local-file-projectile) t)

 ;(setq completion-styles '(helm-flex))

5.4.1 Remove duplicates in helm command history


(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 ""
      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."
  (when (member 'org~mu4e-mime-switch-headers-or-body post-command-hook)

(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. :)
(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 ""
      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)

8 Backlinks

This page last updated: 2021-02-12 Fri 20:34. Map. Recent changes. Source. Peer Production License. Webring: << random >>