34 KiB
emacs setup
- Introduction
- .emacs
- misc
- package bootstrapping
- quality-of-life details
- package: try
- package: which-key
- backup file location
- prefer ibuffer
- package: surround
- package: highlight
- track current directory reliably in
*shell*buffers - dynamic abbreviations
- package: flycheck
- package: ripgrep
- completion assist
- C++
- Development
- org-mode
- eye candy: theme selection
- emacsclient
#
#
Introduction
Roland Conybeare's curated emacs setup.
As of 6oct2023 using emacs version 29.0.91, installed via the nix package manager.
~/.emacs symlinks to ~/proj/env/dotfiles/emacs from git repo https://github.com/Rconybea/env.git;
using this to streamline account setup on new hosts.
.emacs
misc
Compatibility with some Common Lisp idioms
(require 'cl-loaddefs)
package bootstrapping
(require 'package)
;;(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(let ((repos '(("melpa" . "https://melpa.org/packages/")
;;("marmalade" . "http://marmalade-repo.org/packages/")
;;("elpa" . "http://elpa.gnu.org/packages/")
;;("elpa" . "http://tromey.com/elpa/")
;;("melpa" . "http://melpa.milkbox.net/packages/")
)))
(while repos
(add-to-list 'package-archives (car repos) t)
(setq repos (cdr repos))))
(package-initialize)
(when (not package-archive-contents)
(package-refresh-contents))
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
And some packages to autofetch
;; ----------------------------------------------------------------
;; list of emacs packages to auto-install
;; (superseded by (use-package)...? I may be confused about this)
;; ----------------------------------------------------------------
;;
(defvar roland/packages
'(surround treemacs highlight rg treemacs-projectile treemacs-magit
lsp-mode lsp-treemacs lsp-ivy magit company flycheck exec-path-from-shell projectile yasnippet))
;; install missing packages if they are whitelisted in roland/packages
;;
(dolist (p roland/packages)
(when (not (package-installed-p p))
(package-install p)))
quality-of-life details
qol: display
;; grab a little bit of extra screen real estate
;; disable scrollbars
(if (fboundp 'scroll-bar-mode)
(scroll-bar-mode -1))
;; disable toolbars
(if (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
;; disable menu bar
(if (fboundp 'menu-bar-mode)
(menu-bar-mode -1))
;; prevent initial emacs splash screen
(setq inhibit-splash-screen t)
qol: yes-or-no
;; don't like having to type 'yes' or 'no'; 'y' or 'n' will do
(defalias 'yes-or-no-p 'y-or-n-p)
qol: nuke ctrl-Z
;; C-z bound to suspend frame is annoying, because
;; it gets typed by accident too often.
;; C-x C-z remains available as an alternative binding
(global-unset-key (kbd "C-z"))
(global-unset-key (kbd "<return>"))
qol: shortcut to bury current buffer
(global-set-key (kbd "C-x b") 'bury-buffer)
qol: navigation
(global-set-key (kbd "C-x t") 'beginning-of-buffer)
(global-set-key (kbd "C-x e") 'end-of-buffer)
;; keeping window hopping to current frame allows for satellite frames that are
;; mostly display-only (e.g. magit status)
;;
(global-set-key (kbd "C-x o") 'other-window)
(global-set-key (kbd "C-x p") (lambda () (interactive) (other-window -1)))
;;(global-set-key "\C-xo" 'next-multiframe-window)
;;(global-set-key "\C-xp" 'previous-multiframe-window)
(global-set-key (kbd "S-<left>") 'windmove-left)
(global-set-key (kbd "S-<right>") 'windmove-right)
(global-set-key (kbd "S-<up>") 'windmove-up)
(global-set-key (kbd "S-<down>") 'windmove-down)
qol: kill
;; instead of kill-region,
;; prefer consistency with emacs-like keybindings e.g. gnu readline
(global-set-key (kbd "C-w") 'backward-kill-word)
;; instead of C-w..
(global-set-key (kbd "C-x C-k") 'kill-region)
(global-set-key (kbd "C-c C-k") 'kill-region)
This tweak allows using zap on necessary punctuation characters, without swallowing them.
;; use zap-up-to-char instead of zap-to-char
(autoload 'zap-up-to-char "misc"
"kill up to, but not including ARG'th occurence of CHAR.
\(fn arg char)"
'interactive)
(global-set-key "\M-z" 'zap-up-to-char)
qol: query replace
;; M-x qr --> M-x query-replace
;; M-x qrr --> M-x query-replace-regexp
(defalias 'qr 'query-replace)
(defalias 'qrr 'query-replace-regexp)
qol: mouse-3 on macos
;; mouse-3 annoying on macbook 11.3
(if (eq system-type 'darwin)
(global-unset-key [mouse-3]))
qol: mouse avoidance
Don't let mouse icon obscure cursor
(mouse-avoidance-mode 'animate)
Make cursor and mouse easier to see
(set-mouse-color "red")
(set-cursor-color "red")
package: try
;; the 'try' package lets us try a package without permanently installing it.
;; use
;; M-x try ${nameofpackage}
;;
(use-package try :ensure t)
package: which-key
;; the 'which-key' package displays popup with key bindings following
;; currently entered incomplete command
;;
(use-package which-key :ensure t :config (which-key-mode))
backup file location
;; backup location
;; (don't clutter filesystem with emacs backup files)
(let ((backup-dir "~/tmp/emacs/backups")
(auto-saves-dir "~/tmp/emacs/autosaves"))
;; create dirs if needed
(dolist (dir (list backup-dir auto-saves-dir))
(when (not (file-directory-p dir))
(make-directory dir t)))
(setq backup-directory-alist `(("." . ,backup-dir))
auto-save-file-name-transforms `((".*" ,auto-saves-dir t))
auto-save-list-file-prefix (concat auto-saves-dir ".saves-")
;; tramp-backup-directory-alist `((".*" . ,backup-dir))
;; tramp-auto-save-directory auto-saves-dir
)
(setq backup-by-copying t
delete-old-versions t
version-control t
kept-new-versions 5
kept-old-versions 2)
)
prefer ibuffer
;; ----------------------------------------------------------------
;; replace list-buffers (^x^b) with ibuffer
;; ibuffer is much better
(global-set-key "\C-x\C-b" 'ibuffer)
package: surround
Region selection based on matching parens
;; ----------------------------------------------------------------
;; M-' i ( mark text up to but excluding surrounding ().
;; M-' ( will do the same
;; M-' o ( mark surrounding () can use either ( or ) to identify paren type
;; M-' ) will do the same
;; M-' s { surround word-around-point with {}
;; M-' d ( delete innermost surrounding pair of ()'s
;; M-' k ( kill surrounding text up to but not including innermost surrounding () pair
;; M-' K ( kill surrounding text including innermost surrounding () pair
;;
(use-package surround :ensure t
:bind-keymap ("M-'" . surround-keymap))
package: highlight
Manual highlighting
;; ----------------------------------------------------------------
;; highlight.el
;;
;; C-x X u r unhighlight region
;;
(use-package highlight
:ensure t)
track current directory reliably in *shell* buffers
;; ----------------------------------------------------------------
;; Minor mode to track directory via /proc.
;; Will not work on macos!
;;
(defun shell-procfs-dirtrack (str)
;;; shell-procfs-dirtrack --- use /proc/PID/cwd to track current working directory
;;; for emacs shell buffers. From emacswiki "Shell Dirtrack by Procfs"
;;;
(prog1 str
(when (string-match comint-prompt-regexp str)
(let ((directory (file-symlink-p
(format "/proc/%s/cwd"
(process-id
(get-buffer-process
(current-buffer)))))))
(when (file-directory-p directory)
(cd directory))))))
;; have to enable this
;;
(define-minor-mode shell-procfs-dirtrack-mode
"Track shell directory by inspecting procfs."
nil nil nil
(cond (shell-procfs-dirtrack-mode
(when (bound-and-true-p shell-dirtrack-mode)
(shell-dirtrack-mode 0))
(when (bound-and-true-p dirtrack-mode)
(dirtrack-mode 0))
(add-hook 'comint-preoutput-filter-functions
'shell-procfs-dirtrack nil t))
(t
(remove-hook 'comint-preoutput-filter-functions
'shell-procfs-dirtrack t))))
;; ----------------------------------------------------------------
;; command shell.
;;
;; invoking emacs from
;; nix develop -i
;; interferes with its ability to figure out suitable shell
;; tell emacs to use bash here
;;
(setq-default shell-file-name "bash")
dynamic abbreviations
For consciously correcting typos
;; ----------------------------------------------------------------
;;
(global-set-key (kbd "C-<tab>") #'dabbrev-expand)
(define-key minibuffer-local-map (kbd "C-<tab>") #'dabbrev-expand)
package: flycheck
Flycheck runs in the background. It automatically (and subtly) highlights syntax errors as you type. Preferred over built-in flyspell.
;; enable flycheck
;; see:
;; https://www.flycheck.org/en/latest/user/quickstart.html#flycheck-quickstart
;;
;; keybindings:
;; C-c ! v show version + configuration info for this buffer
;; C-c ! n / C-c ! p inspect errors on this line
;; C-c ! l show errors for this buffer
(global-flycheck-mode)
(if (eq system-type 'darwin)
;; need this for flycheck on macos only..
(exec-path-from-shell-initialize))
package: ripgrep
Projectile uses this automagically if available
;; ----------------------------------------------------------------
;; ripgrep for search
;; see [[rg.el.readthedocs.io/en/latest/configuration.html]]
;;
;; rg-executable-per-connection
;; rg-custom-type-aliases
;; rg-prioritized -type-aliases
;; rg-default-alias-fallback
;; rg-command-line-flags
;; rg-group-result
;; rg-show-columns
;; rg-ignore-case
;; rg-hide-command t
;; rg-keymap-prefix "C-c s"
;; rg-use-transient-menu t
;; rg-show-header t
;; rg-buffer-name "rg"
;; rg-ignore-ripgreprc t
;; ...and more...
;;
;; See also rg-isearch to use ripgrep with isearch
;;
(use-package rg
:ensure t
:init (progn
(rg-enable-default-bindings)
;; want see rg command to debug it :)
(setq rg-hide-command nil)
;; need filename to report line number for navigation with C-x ` to work
(setq rg-command-line-flags nil)
;;(setq rg-use-transient-menu t) etc
;; trying to make it easy to visit match results in context
(setq rg-group-result nil)
)
)
completion assist
completion: ivy
;; ----------------------------------------------------------------
;; ivy (completion assist)
;;
;; keybindings:
;; M-x ivy-mode disable/enable toggle
;; C-x b ivy-switch-buffer
;; C-c v ivy-push-view
;; C-c V ivy-pop-view
;; ivy-resume resume last ivy completion
;;
;; in minibuffer:
;; C-n ivy-next-line next line
;; C-p ivy-prev-line previous line
;; M-< ivy-beginning-of-buffer first candidate
;; M-> ivy-end-of-buffer last candidate
;; C-v ivy-scroll-up-command scroll up ivy-height lines
;; M-v ivy-scroll-down-command scroll down ivy-height lines
;;
;; actions (on selected choice):
;; c-M or RET ivy-done default action + exit minibuffer
;; M-o ivy-dispatching-done present menu of choices
;; C-j ivy-alt-done for file name, cd into selected dir candidate
;; TAB ivy-partial-or-done completion on current input
;; C-M-j ivy-immediate-done exit with current candidate (exact spelling)
;; C-' ivy-avy use avy to select from current candidate page
;;
;; C-M-m ivy-call non-exiting version of ivy-done
;; C-M-o ivy-dispatching-call non-exiting version of ivy-dispatching-done
;;
;; C-o hydra-ivy/body invoke hydra menu with short key bindings
(use-package ivy
:ensure t
:init (progn
(setq ivy-use-virtual-buffers t)
(setq ivy-count-format "(%d/%d) ")
(ivy-mode 1)
(global-set-key (kbd "C-x b") 'ivy-switch-buffer)
;; or (bind-key "C-x b" 'ivy-switch-buffer)
)
)
C++
c++: indenting + tabs
;; in general want to expand tabs, + use 4 characters
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
;; used in style-specific modes, e.g. c++-mode
;; other styles: gnu | k&r | bsd | whitesmith | stroustrup | ellemtel | user
;;
;; C-c . <style> choose predefined style
;;(defvar 'c-default-style)
;;(defvar 'c-basic-offset)
(setq-default c-default-style "linux")
(setq-default c-basic-offset 4)
(defun disable-tabs ()
"Function to disable tab insertion; intended to be attached via c++-mode-hook."
(if (boundp 'indent-tabs-mode)
(setq indent-tabs-mode nil)
(error "Expected variable [indent-tabs-mode] to be defined")
))
;; in general disable tabs (expand to spaces)
(add-hook 'c++-mode-hook 'disable-tabs)
c++: whitespace
;; will be using customized whitespace mode, that just highlights trailing spaces
;;
(add-hook 'c++-mode-hook 'whitespace-mode)
;; tabs: visible tab characters
;; trailing: visible trailing whitespace
;;
(setq-default whitespace-style '(face tabs tab-mark trailing))
;; 124 is | character
(setq-default whitespace-display-mappings
'((tab-mark 9 [124 9] [92 9])))
(defun untabify-except-makefiles ()
"Replace tabs with spaces except in makefiles."
(unless (derived-mode-p 'makefile-mode)
(prog1 nil
(untabify (point-min) (point-max))
(delete-trailing-whitespace)
)))
(add-hook 'c++-mode-hook
#'(lambda ()
(add-hook 'before-save-hook #'untabify-except-makefiles)))
(add-hook 'nix-mode-hook
#'(lambda ()
(add-hook 'before-save-hook #'untabify-except-makefiles)))
cmake editing
;; cmake mode
;;
(use-package cmake-mode
:ensure t
:init (progn
(setq cmake-tab-width 4)
)
)
c++ completion
(use-package company
:config
(progn
(setq company-minimum-prefix-length 1) ;; LOOKS LIKE MUST HAVE THIS for company to activate
(setq company-idle-delay 0.1) ;; default 0.2
))
(add-hook 'c++-mode-hook 'company-mode)
compilation buffer
For example, to respond to cmake colored output
;; ----------------------------------------------------------------
;; xterm-color
;;
;; more modern package relative to ansi-color
;; see [[https://stackoverflow.com/questions/3072648/cucumbers-ansi-colors-messing-up-emacs-compilation-buffer]]
;;
(defun my/advice-compilation-filter (f proc string)
"colorize buffer output"
(funcall f proc (xterm-color-filter string)))
(defvar compilation-environment)
(use-package xterm-color
:ensure t
:init (progn (setq compilation-environment '("TERM=xterm-256color"))
(advice-add 'compilation-filter :around #'my/advice-compilation-filter))
)
Development
dev: snippets
;; snippets!
;; (see http://capitaomorte.github.io/yasnippet,
;; http://githib.com/capitaomorte/yasnippet)
;; snippets in ~/.emacs.d/elpa/yasnippet-20200604.246/snippets
;;
;; summary:
;; M-x yas-expand -- try to expand snippet before point. Usually TAB
;; M-x yas-load-directory -- load a directory of snippets
;; M-x yas-activate-extramode -- add snippets for a particular mode, in the current buffer
;; M-x yas-insert-snippet -- insert snippet at point
;; M-x yas-visit-snippet-file -- prompt for snippet expansion, but go to definition
;; M-x yas-new-snippet -- create a new snippet in ~/.emacs.d/snippets, function of major mode
;; M-x yas-load-snippet-buffer -- load the snippet you are editing C-c C-c in snippet-mode
;; M-x yas-tryout-snippet -- insert current snippet in a new empty buffer C-c C-t in snippet-mode
;; M-x yas-describe-tables -- list known snippets
;;
(use-package yasnippet
:ensure t
:config (yas-global-mode 1))
(add-hook 'c++-mode-hook 'yas-minor-mode)
(add-hook 'cmake-mode-hook 'yas-minor-mode)
(add-hook 'emacs-lisp-mode-hook 'yas-minor-mode)
(global-set-key (kbd "C-<return>") 'yas-expand)
(global-set-key (kbd "C-c & C-n") 'yas-new-snippet)
(global-set-key (kbd "C-c & C-v") 'yas-visit-snippet-file)
;;(yas-global-mode t)
;;;; yas-snippet-dirs
;;;; yas-installed-snippets-dir
;;;; (yas-reload-all)
dev: treemacs
;; ----------------------------------------------------------------
;; treemacs
(use-package treemacs
:config
(progn
(setq treemacs-follow-after-init t
treemacs-is-never-other-window t
treemacs-width 40)
(treemacs-follow-mode t)
(treemacs-filewatch-mode t)
(treemacs-git-mode 'simple)
(treemacs-fringe-indicator-mode t)
(treemacs-resize-icons 11) ;; default is 22
)
:hook (after-init . treemacs)
:bind (:map global-map ("C-M-t" . treemacs)))
dev: projectile
;; projectile
(defconst modi/rg-arguments
`("--line-number" ; print line numbers
"--smart-case"
"--follow" ; follow symlinks
"--mmap" ; use memory-map optimization where available
)
"default rg args used in the `projectile` package.")
(defun modi/advice-projectile-use-rg (mode)
"always use `rg' to establish project file list"
(mapconcat 'identity
(append '("\\rg") ; unalised version of rg
modi/rg-arguments
'("--null" ; null-separated results
"--files" ; locate + print file names (don't search them)
))
" "))
(use-package projectile
:ensure t
:init (progn (projectile-mode +1)
;;(setq projectile-indexing-method 'native) -- want to use rg below
(setq projectile-project-compilation-dir "")
(setq projectile-enable-caching t)
;; using rg to identify project source files:
;; - honors .gitignore
;; - fast, too!
(when (executable-find "rg")
(progn
(advice-add 'projectile-get-ext-command
:override #'modi/advice-projectile-use-rg))))
:bind (:map projectile-mode-map
("s-p" . projectile-command-map)
("C-c p" . projectile-command-map)))
dev: treemacs+projectile integration
;; ----------------------------------------------------------------
;; treemacs-projectile
;; use
;; M-x treemacs-add-project-to-workspace make project (directory tree) showup in treemacs
;;
(use-package treemacs-projectile
:ensure t
)
dev: language server protocol (LSP)
;; ----------------------------------------------------------------
;; language-server-protocol
;; +format-with-lsp: provided by lsp-mode
(defvar +format-with-lsp)
(defvar lsp-clients-clangd-args)
;; see:
;; https://emacs-lsp.github.io/lsp-mode
(defun disable-lsp-format ()
"Disable clang-driven formatting via lsp to prefer emacs-native formatting."
(setq +format-with-lsp nil))
(use-package lsp-mode
:hook (lsp-mode . (lambda ()
;; from [[https://github.com/emacs-lsp/lsp-mode/issues/1532]] (mar 2020)
(let ((lsp-keymap-prefix "C-c l")) ; default s-l collides with windows key
(lsp-enable-which-key-integration))))
:config (progn
;; reminder: :config runs *after* package is loaded
(define-key lsp-mode-map (kbd "C-c l") lsp-command-map)
(setq lsp-enable-indentation nil) ; disable clang indentation -- doesn't preserve newlines!
(setq lsp-enable-on-type-formatting nil)
(setq lsp-headerline-breadcrumb-enable t) ;; enable path-to-this-file headerline
(setq lsp-modeline-diagnostics-enable t)
(setq lsp-completion-provider :capf)
(setq lsp-completion-show-detail t) ;; rhs of completion popup
(setq lsp-completion-show-kind t)
;; semgrep crashing incessantly, looks like can't resolve host semgrep.dev?
;; *semgrep-ls::stderr* contains
;; TLS to non-TCP currenlty unsupported: host=semgrep.dev endp=(Unknown "name resolution failed")
(setq lsp-disabled-clients '(semgrep-ls))
;;(setq lsp-signature-render-documentation t) ;; include documentation with signatures
(add-hook 'c++-mode-hook #'lsp-deferred)
(add-hook 'c++-mode-hook #'disable-lsp-format)
;; additional clangd args:
;; --compile-commands-dir=path/to/compile_comamnds.json
;; (ed: prefer better discoverable with build-specific symlink in git root for each project)
;; --fallback-style
;; (ed: could use this instead of writing .clang-format)
;; --header-insertions=iwyu|never
;; --enable-config
;; (ed: docs at
;; --pch-storage=disk|memory
(setq lsp-clients-clangd-args '("-j=4" "-background-index" "-log=error")))
;;(add-hook 'python-mode-hook #'lsp)
)
;; ----------------------------------------------------------------
;; lsp-ui-sideline: show info associated with symbols toward rhs of current line
;; lsp-ui-sideline-show-diagnostics
;; lsp-ui-sideline-show-hover
;; lsp-ui-sideline-show-code-actions
;; lsp-ui-sideline-update-mode
;; lsp-ui-sideline-delay
;;
;; lsp-ui-peek
;; examples
;; (define lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions)
;; (define lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references)
;; (lsp-ui-peek-jump-backward)
;; (lsp-ui-peek-jump-forward)
;; (lsp-ui-peek-find-workspace-symbol "pattern 0")
;; (lsp-ui-peek-find-custom 'base "$cquery/base")
;;
;; lsp-ui-peek-enable
;; lsp-ui-peek-show-directory
;;
;; lsp-ui-doc
;; lsp-ui-doc-enable
;; lsp-ui-doc-position
;; lsp-ui-doc-delay
;; lsp-ui-doc-show-with-cursor
;; lsp-ui-doc-show-with-mouse
;;
;; lsp-ui-imenu
;; lsp-ui-imenu-kind-position
;; lsp-ui-imenu-buffer-position
;; lsp-ui-imenu-window-width
;; lsp-ui-imenu-window-fix-width
;; lsp-ui-imenu--custome-mode-line-format
;; lsp-ui-imenu-auto-refresh
;;
(use-package lsp-ui
:ensure t
:config
(setq lsp-ui-sideline-show-diagnostics t)
(setq lsp-ui-doc-enable t) ;; hover dialogs
(setq lsp-ui-doc-show-with-cursor t)
)
dev: lsp+ivy integration
;; ----------------------------------------------------------------
;; LSP ivy integration
;; M-x lsp-ivy-worskpace-symbol
;; M-x lsp-ivy-global-workspace-symbol
(use-package lsp-ivy
:ensure t
:bind (:map global-map
("M-g s" . lsp-ivy-workspace-symbol)
("M-g S" . lsp-ivy-global-workspace-symbol))
)
dev: git integration
;; ----------------------------------------------------------------
;; git integration
;; C-x M-g j magit status buffer for current repo
;;
;; in status buffer:
;; d change diff parameters
;; -w suppress whitespace-only diffs
;; C-x extended menu
;; C-s save settings for future sessions
;;
(use-package magit
:ensure t
:init (progn (bind-key "C-x M-g j" 'magit-status)))
dev: nix mode
Syntax highlighting in nix files
;; ----------------------------------------------------------------
;; nix mode (syntax highlighting etc for .nix files)
;;
(use-package nix-mode :ensure t)
dev: yaml mode
Syntax highlighting in yaml files
;; yaml mode (syntax highlighting etc for .yml, .yaml files)
;;
(use-package yaml-mode :ensure t
:init (progn (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))))
org-mode
org: publishing
;; org-mode publishing
;;
(require 'ox-publish)
;; syntax highlighting in html exporter
;;
(use-package htmlize :ensure t)
;; publishing setup -- this is a kitchen sink -- it's intended to cover
;; everything we want org-mode to publish
;;
(setq org-publish-project-alist
'(
("org-howto"
:components ("org-howto-notes" "org-howto-static"))
("org-howto-notes"
:base-directory "~/proj/org-howto"
:base-extension "org"
:publishing-directory "~/proj/public_html/org-howto"
:recursive t
:publishing-function org-html-publish-to-html
:headling-levels 4
:auto-preamble t
)
("org-howto-static"
:base-directory "~/proj/org-howto"
:base-extension "md\\|css\\|html\\|js\\|svg\\|ico\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
:publishing-directory "~/proj/public_html/org-howto"
:recursive t
:publishing-function org-publish-attachment
)
;; ----- non-public org stuff -----
("org-private"
:components ("org-private-notes" "org-private-static"))
("org-private-notes"
:base-directory "~/proj/org-private"
:base-extension "org"
:publishing-directory "~/proj/private_html/org-private"
:recursive t
:publishing-function org-html-publish-to-html
:headling-levels 4
:auto-preamble t
)
("org-private-static"
:base-directory "~/proj/org-private"
:base-extension "md\\|css\\|html\\|js\\|svg\\|ico\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
:publishing-directory "~/proj/private_html/org-private"
:recursive t
:publishing-function org-publish-attachment
)
))
babel setup
For literate programming – execute code blocks, written in various languages, embedded in .org files
;; ----------------------------------------------------------------
;; org-mode babel setup
;; (execute dot/ditaa/bash/c++ etc. from .org code blocks)
;;
;; see
;; [[https://orgmode.org/worg/org-contrib/babel/intro.html]]
;; [[https://orgmode.org/worg/org-contrib/babel/languages/index.html]]
;;
;; code block:
;; #+begin_src ${language} ${switches} ${headerarguments}
;; ${body}
;; #+end_src
;;
;; use header argument
;; :results output
;; to insert code-block output (i.e. contents of stdout) into .org file below code block
;;
;; use
;; :results value
;; to just take value of last statement
;;
;; use
;; :session
;; to share language sub-process across code-blocks.
;;
;; can use
;; #+name: foo
;; to name an org-mode table; then:
;; #+begin_src ... :var myfreevar=foo
;; ...
;; #+end_src
;; with body mentioning myfreevar; .org will substitute foo
;;
;; can do inline coode block with
;; src_<${lang}>{${code}} or src_<${lang}[${args}]{${code}}
;; e.g.
;; src_python[:session]{10*x}
;;
;; notes:
;; [C-c C-v] org-babel prefix
;; [C-c C-v b] -- evaluate code blocks in buffer
;; [C-c C-v s] -- evaluate code blocks in subtree
;; [C-c C-v e] -- evaluate code block at point
;; [C-c '] M-x org-edit-src-code -- puts code block in new buffer with appropriate mode activated
;; [C-c M-b p] M-x org-babel-expand-src-block -- show expanded code block prior to evaluation
;; (org-babel-lob-ingest "path/to/file.org") to share code blogs as 'library'
(org-babel-do-load-languages
'org-babel-load-languages
'(
(C . t) ; C,C++,D [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-C.html]]
(ditaa .t) ; "diagrams through ascii art"
(dot . t) ; graphviz [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-dot.html]] see also graphviz-dot-mode
))
For ditaa, need some paths. Nix makes these obscure, need to dig out the parts we want
;; extracted from command like
;; cat $(which ditaa) | sed -n -e '/^exec/s: -jar .*$::p' | sed -e 's:^exec ::'
;; expecting result like
;; /nix/store/6g5q62wafkpg0p3w854vc9yxy9bsnwi5-openjdk-19.0.2+7/bin/java
;;
;; the /usr/bin paths + /nix/store/.*ditaa.jar exprs for shmecurity
;;
(setq org-babel-ditaa-java-cmd
(shell-command-to-string "/usr/bin/cat $(which ditaa) | /usr/bin/sed -n -e '/^exec/s: -jar .*\$::p' | /usr/bin/sed -e 's:^exec ::' | /usr/bin/tr -d '\n'"))
;; extracted from command like
;; cat $(which ditaa) | grep ' -jar ' | sed -e 's:^exec.* -jar "::' -e 's:" "\$@"::'
;; expecting result like
;; /nix/store/in2hf1xcxr1i4rijw0g423kawr3624pv-ditaa-0.11.0/lib/ditaa.jar
;;
;; the /usr/bin paths + /nix/store/.*ditaa.jar exprs for shmecurity
;;
(setq org-ditaa-jar-path
(shell-command-to-string "/usr/bin/cat $(which ditaa) | /usr/bin/grep ' -jar ' | /usr/bin/sed -e 's:^exec.* -jar \"::' -e 's:\" \"\\$@\"::' | /usr/bin/grep '^/nix/store/.*ditaa.jar' | /usr/bin/tr -d '\n'"))
;; (setq org-ditaa-eps-jar-path "path/to/related/jar") ;; not using, but if so would need it
incoming mail
Using notmuch for incoming mail (notmuch configured using notmuch setup)
;; ----------------------------------------------------------------
;; local email storage
;;
;; 1. sync email (e.g. fetch remote emails) with
;; $ mbsync -a
;;
;; 2. apply rules locally (move emails to folders etc.) with
;; $ cleanmbox
;;
;; 3. sync email again (e.g. propagate changes back to remote mailboxes)
;; $ mbsync -a
;;
;; 4. to read email from local copy, use
;; M-x notmuch
;;
;; show ;; to see everything
;;
;; use [M-x customize-group RET notmuch RET] to customize
;; use [M-x notmuch] to invoke
;; in a [*notmuch-hello*] buffer, use
;; folder:gmail/.health
;; to see messages in
;; ${MAILDIR}/gmail/.health
(require 'notmuch)
outgoing mail
(require 'smtpmail)
(setq user-mail-address "alice@gmail.com"
user-full-name "Alice Exampleton")
(setq message-send-mail-function 'smtpmail-send-it)
(setq smtpmail-stream-type 'starttls
smtpmail-smtp-server "smtp.gmail.com"
smtpmail-smtp-service 587
)
;; prevent send buffers accumulating
(setq message-kill-buffer-on-exit t)
Note: smtpmail also requires credentials in ~/.authinfo:
machine smtp.gmail.com login rconybeare@gmail.com port 587 password somegoogleapppassword
eye candy: theme selection
;; ----------------------------------------------------------------
;; theme selection
(load-theme 'misterioso t)
eye candy: default font
;; ----------------------------------------------------------------
;; default font
;; note:
;; C-x C-+ increase buffer text size
;; C-x C-= something buffer text size
;; C-x C-- decrease buffer text size
;; C-x C-0 restore default buffer text size
;; M-x describe-font display font canonical name + stats in a new buffer
;;
;; to install inconsolata on ubuntu:
;; $ sudo apt-get -y install fonts-inconsolata
;; for nix, can use package
;; nixpkgs.inconsolata-lgc
(add-to-list
'default-frame-alist
'(font . "-PfEd-Inconsolata-medium-normal-normal-*-14-*-*-*-m-0-iso10646-1"))
eye candy: initial window height
(defvar target-frame-width (+ 1 (* 2 135)))
(defun set-frame-size-from-screen-resolution ()
"Infer suitable default frame size.
Reminder: no such thing as .Xresources under WSL."
(interactive)
(if (display-graphic-p)
(progn
(let* ((horizontal-room (/ (x-display-pixel-width)
(frame-char-width)))
(using-width (min target-frame-width
horizontal-room)))
(set-frame-width (selected-frame)
using-width)
;;(add-to-list 'default-frame-alist (cons 'width using-width))
)
;; subtracting 200 pixels of vertical space
(let* ((vertical-padding 100)
(vertical-room (/ (- (x-display-pixel-height)
vertical-padding)
(frame-char-height))))
(set-frame-height (selected-frame)
vertical-room)
;;(add-to-list 'default-frame-alist (cons 'height vertical-room))
))))
(set-frame-size-from-screen-resolution)
emacsclient
EDITOR=emacsclient to adopt running emacs session when unix wants something edited.
For example when running git commit from shell.
;; + set EDITOR=emacsclient in shell
(server-start)