howto

Setting up emacs re-re-dux

What is more fun that configuring emacs?

tags
emacs

Can we ever stop setting up emacs? I don't think it's possible, no. Lets do it again, with a nice clean setup using Nano Emacs.

Compiling emacs

First lets get ourselves a clean emacs from d12frosted/homebrew-emacs-plus.

1
2
3
4
  $ brew tap d12frosted/emacs-plus
  $ brew install emacs-plus@29 --with-imagemagick --with-native-comp \
    --with-modern-sexy-v2-icon --with-xwidgets
  $ ln -s /opt/homebrew/opt/emacs-plus@29/Emacs.app /Applications

This will take a nice little while.

And some graphing things that we will eventually use with org-babel:

1
  $ brew install plantuml graphviz

Also, some fonts:

1
2
3
4
5
  $ brew tap homebrew/cask-fonts
  $ brew install font-roboto
  $ brew install font-roboto-slab
  $ brew install font-roboto-mono
  $ brew install font-hack

Installing straight.el

Lets turn off package.el in ~/.emacs.d/early-init.el:

1
  (setq package-enable-at-startup nil)

Then we can set some sane defaults in ~/.emacs.d/init.el

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
  (defconst *spell-check-support-enabled* nil) ;; Enable with t if you prefer
  (defconst -is-a-mac (eq system-type 'darwin))
  (setq custom-file (locate-user-emacs-file "custom.el"))

  ;; Backups
  (setq
   backup-by-copying t      ; don't clobber symlinks
   backup-directory-alist
   '(("." . "~/.saves/"))    ; don't litter my fs tree
   delete-old-versions t
   kept-new-versions 6
   kept-old-versions 2
   version-control t
   global-visual-line-mode t
   visible-bell 1)

  ;; Cleaning up some visual mess
  (tool-bar-mode 0)
  (scroll-bar-mode 0)

  ;; Safe themes
  (setq custom-safe-themes t)

os stuff

From https://github.com/purcell/emacs.d:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
  (when -is-a-mac
    (setq mac-command-modifier 'meta)
    (setq mac-option-modifier 'none)
    ;; Make mouse wheel / trackpad scrolling less jerky
    (setq mouse-wheel-scroll-amount '(1
                                      ((shift) . 5)
                                      ((control))))
    (dolist (multiple '("" "double-" "triple-"))
      (dolist (direction '("right" "left"))
        (global-set-key (read-kbd-macro (concat "<" multiple "wheel-" direction ">")) 'ignore)))
    (global-set-key (kbd "M-`") 'ns-next-frame)
    (global-set-key (kbd "M-h") 'ns-do-hide-emacs)
    (global-set-key (kbd "M-˙") 'ns-do-hide-others)
    (with-eval-after-load 'nxml-mode
      (define-key nxml-mode-map (kbd "M-h") nil))
    (global-set-key (kbd "M-ˍ") 'ns-do-hide-others) ;; what describe-key reports for cmd-option-h
    )

straight.el

From Jeff Kreeftmeijer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
;; straight.el
(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 6))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

(straight-use-package 'use-package)

(use-package straight
  :custom
  (straight-use-package-by-default t))

org-mode

I'm a big fan of org-mode, especially org-tempo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  ;; Org mode awesome
  (use-package org
    :ensure t
    :bind (
       ("C-c l" . org-store-link)
       ("C-c a" . org-agenda)
       ("C-c c" . org-capture))
    :config
    (require 'org-tempo)
    (org-babel-do-load-languages
     'org-babel-load-languages
     '(
       (dot . t)
       (gnuplot . t)
       (plantuml . t)
       (emacs-lisp . t)
       (ruby . t)
       (shell . t)))
    (setq org-startup-indented t) ; Enable `org-indent-mode' by default
    (setq org-log-done t) ; Set time for when things were completed
    (setq org-hide-emphasis-markers t) ; Not show typographical commands
    (setq org-plantuml-exec-mode 'plantuml)
    )

  (use-package org-superstar
    :ensure t
    :config
    (add-hook 'org-mode-hook (lambda () (org-superstar-mode 1))))

Presentations

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  (use-package org-present
    :ensure t
    )

  (use-package hide-mode-line :ensure t)

  (defun efs/presentation-setup ()
    ;; Hide the mode line
    (hide-mode-line-mode 1)
    (visual-line-mode);
    (visual-fill-column-mode)
    ;; Display images inline
    (org-display-inline-images) ;; Can also use org-startup-with-inline-images

    ;; Scale the text.  The next line is for basic scaling:
    (setq text-scale-mode-amount 3)
    (text-scale-mode 1))

    ;; This option is more advanced, allows you to scale other faces too
    ;; (setq-local face-remapping-alist '((default (:height 2.0) variable-pitch)
    ;;                                    (org-verbatim (:height 1.75) org-verbatim)
    ;;                                    (org-block (:height 1.25) org-block))))

  (defun efs/presentation-end ()
    ;; Show the mode line again
    (hide-mode-line-mode 0)

    ;; Turn off text scale mode (or use the next line if you didn't use text-scale-mode)
    ;; (text-scale-mode 0))

    ;; If you use face-remapping-alist, this clears the scaling:
    (setq-local face-remapping-alist '((default variable-pitch default))))

  (use-package org-tree-slide
    :ensure t
    :hook ((org-tree-slide-play . efs/presentation-setup)
           (org-tree-slide-stop . efs/presentation-end))
    :custom
    (org-tree-slide-slide-in-effect t)
    (org-tree-slide-activate-message "Presentation started!")
    (org-tree-slide-deactivate-message "Presentation finished!")
    (org-tree-slide-header t)
    (org-tree-slide-breadcrumbs " > ")
    (org-image-actual-width nil))

  (use-package visual-fill-column
    :ensure t)

Searching and execing

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  ;; Counsel
  (use-package counsel :ensure t)

  ;; Exec from shell
  (use-package exec-path-from-shell
    :ensure t
    :config
    (exec-path-from-shell-copy-env "PATH"))

  ;; Which key

  (use-package which-key
    :ensure t
    :config
    (which-key-mode))

nano-emacs

1
2
3
4
5
6
7
8
9
  (setq nano-font-family-monospaced "Hack")
  
  ;; Nano Emacs
  (require 'bookmark)

  (straight-use-package
   '(nano-emacs :type git :host github :repo "rougier/nano-emacs"))

  (require 'nano)

Matching the system theme

Adapted from Lambda Theme. We add a hook to ns-system-appearance-change-functions and then make sure that we toggle the nano theme based upon the current setting in ns-system-appearance.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  ;; See https://github.com/d12frosted/homebrew-emacs-plus#system-appearance-change
  (defun nano-sync-theme (appearance)
  "Sync the nano theme with the system theme"
  (if
   (string= nano-theme-var ns-system-appearance)
   (message "Theme is good")
   (nano-toggle-theme)))

  (when -is-a-mac
    (add-hook 'ns-system-appearance-change-functions #'nano-sync-theme))
nano-sync-theme

Icons

1
2
3
4
5
6
7
8
9
  (use-package vscode-icon
  :ensure t
  :commands (vscode-icon-for-file))


  (use-package all-the-icons
    :if (display-graphic-p))

  ;; M-x all-the-icons-install-fonts

Programming

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  ;; Magit and Projectile

  (use-package magit
    :ensure t
    :bind ("C-x g" . magit-status))

  (use-package projectile
    :ensure t
    :init
    (projectile-mode +1)
    :config
    (setq projectile-completion-system 'default)
    :bind (:map projectile-mode-map
                ("C-c p" . projectile-command-map)))

  (use-package ag :ensure t)

  (use-package docker
    :ensure t
    :bind ("C-c C-d" . docker))

  (use-package dockerfile-mode
    :ensure t)

  (use-package typescript-mode :ensure t)
  (use-package terraform-mode :ensure t)
  (use-package toml-mode :ensure t)
  (use-package yaml-mode :ensure t)
  (use-package gist :ensure t)

Elfeed

This will let you manage your lists of feeds in a org file, and if you've installed emacs-plus with --with-xwidgets you can use % to toggle between the text view of the RSS feed and a webkit rendered version of the page itself, in all its glory.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  ;; elfeed

  (defun elfeed-eww-browse ()
    "Wrapper to open eww and mark elfeed as read"
    (interactive)
    (let ((link (elfeed-entry-link elfeed-show-entry)))
      (when link
        (eww-browse-url link))))

  (use-package elfeed
    :ensure t
    :bind (
       ("C-x w" . elfeed))
    :config
    (define-key elfeed-show-mode-map (kbd "B") 'elfeed-eww-browse)
    )

  (use-package elfeed-org
    :ensure t
    :config
    (elfeed-org))

  ;; Only if you've installed with --with-xwidgets
  (use-package elfeed-webkit
    :ensure
    :bind (:map elfeed-show-mode-map
                ("%" . elfeed-webkit-toggle)))

(use-package elfeed-goodies :ensure t :config (setq elfeed-goodies/entry-pane-position 'bottom) (elfeed-goodies/setup))

Better dired

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  (let ((gls (executable-find "gls")))
    (when gls (setq insert-directory-program gls)))

  (use-package dired-subtree
    :ensure t
    :after dired
    :config
    (setq dired-subtree-use-backgrounds nil)
    (bind-key "<tab>" #'dired-subtree-toggle dired-mode-map)
    (bind-key "<backtab>" #'dired-subtree-cycle dired-mode-map))

  (use-package dired-sidebar
    :bind (("C-x C-n" . dired-sidebar-toggle-sidebar))
    :ensure t
    :commands (dired-sidebar-toggle-sidebar)
    :init
    (add-hook 'dired-sidebar-mode-hook
              (lambda ()
                (unless (file-remote-p default-directory)
                  (auto-revert-mode))))
    :config
    (push 'toggle-window-split dired-sidebar-toggle-hidden-commands)
    (push 'rotate-windows dired-sidebar-toggle-hidden-commands)
  
    (setq dired-sidebar-subtree-line-prefix "__")
    (setq dired-sidebar-theme 'icons)
    (setq dired-sidebar-use-term-integration t)
    (setq dired-sidebar-use-custom-font t))

Shell Modes

Coterm installs terminal emulation for the shell, which is super handy!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  ;; Install a better terminal

  (use-package vterm :ensure t)

  ;; Install terminal emulation in the regular shell
  (use-package coterm :ensure t
    :config
    (coterm-mode))

  (defun shell-here ()
    "Opens up a new shell in the directory associated with the
  current buffer's file. The shell is renamed to match that
  directory to make multiple shell windows easier."
    (interactive)
    (let* ((parent (if (buffer-file-name)
                       (file-name-directory (buffer-file-name))
                     default-directory))
           (height (/ (frame-total-lines) 3))
           (name   (car (last (split-string parent "/" t))))
           (bufname (concat "*shell: " name "*")))
      (delete-other-windows)
      (split-window-vertically (- height))
      (other-window 1)
      (switch-to-buffer bufname)
      (shell bufname)
      ))

  (global-set-key (kbd "C-!") 'shell-here)

  (defun live-preview ()
    "Opens up a web browser in the current directory"
    (interactive)
      (let* ((parent (if (buffer-file-name)
                       (file-name-directory (buffer-file-name))
                     default-directory))
           (height (/ (frame-total-lines) 3))
           (name   (car (last (split-string parent "/" t))))
           (bufname (concat "*preview: " name "*")))
      (delete-other-windows)
      (split-window-vertically (- height))
      (other-window 1)
      (switch-to-buffer bufname)
      (unless (get-buffer-process bufname)
        (async-shell-command "npx live-server" bufname))))

Mastodon

Haha, why not?

1
2
3
4
5
6
7
8
  (use-package emojify
    :hook (after-init . global-emojify-mode))

  (use-package mastodon
    :ensure t
    :config
    (setq mastodon-instance-url "https://floss.social"
          mastodon-active-user "wschenk"))

AI

1
2
3
4
5
6
  (use-package ellama
    :ensure t
    :init
    ;; setup key bindings
    (setopt ellama-keymap-prefix "C-c e")
    )

Obsidian

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  (use-package obsidian
    :ensure t
    :demand t
    :config
    (obsidian-specify-path "/Users/wschenk/Library/Mobile Documents/iCloud~md~obsidian/Documents/my awesome vault")
    (global-obsidian-mode t)
    :custom
    ;; This directory will be used for `obsidian-capture' if set.
    (obsidian-inbox-directory "Inbox")
    ;; Create missing files in inbox? - when clicking on a wiki link
    ;; t: in inbox, nil: next to the file with the link
    ;; default: t
    ;(obsidian-wiki-link-create-file-in-inbox nil)
    ;; The directory for daily notes (file name is YYYY-MM-DD.md)
    (obsidian-daily-notes-directory "Daily")
    ;; Directory of note templates, unset (nil) by default
    ;(obsidian-templates-directory "Templates")
    ;; Daily Note template name - requires a template directory. Default: Daily Note Template.md
    ;(setq obsidian-daily-note-template "Daily Note Template.md")
    :bind (:map obsidian-mode-map
    ;; Replace C-c C-o with Obsidian.el's implementation. It's ok to use another key binding.
    ("C-c C-o" . obsidian-follow-link-at-point)
    ;; Jump to backlinks
    ("C-c C-b" . obsidian-backlink-jump)
    ;; If you prefer you can use `obsidian-insert-link'
    ("C-c C-l" . obsidian-insert-wikilink)))

And bring in other files

1
(load "~/.emacs.d/blog.el")

Previously

labnotes

Using Mrsk

Deployment testing

tags
mrsk

Next

labnotes

Playing with SSHKit

Deployment testing

tags
sshkit
ruby