This is my emacs configuration file, it’s the strategy from the https://github.com/hrs/dotfiles. Which is pretty terrific. I also got inspiration from https://github.com/gjstein/emacs.d. That’s where I decided to only add in the .emacs.d components in their seperate repository.
The most crazy example of this might be https://github.com/rougier/dotemacs/blob/master/dotemacs.org
Some other examples I’ve looked at, that are mostly for science-based installations, include Awesome Emacs, and SciMax. Prelude is also worth a look since it has a lot of very nice ideas on good packages to be using.
You should be able to clone this repo onto a new machine, and when you start it up, your default emacs installation jsut comes up naturally for you. This is due, in part, to the use-package setup that allows more auto-matic generation of your personal emacs setup.
This is setup by cloning, but remember to use `–recurse-submodules` to get any submodules. Otherwise, you’ll have to `git submodule init; git submodule update`.
git clone --recurse-submodules https://github.com/qjhart/.emacs.d.git
I use use-package
to install and configure my packages. My init.el
includes
the initial setup for package.el
and ensures that use-package
is installed,
since I wanna do that right away.
This makes sure that use-package
will install the package if it’s not already
available. It also means that I should be able to open Emacs for the first time
on a fresh Debian box and have my whole environment automatically installed. I’m
not totally sure about that, but we’re gettin’ close.
(require 'use-package-ensure)
(setq use-package-always-ensure t)
Always compile packages, and use the newest version available.
(use-package auto-compile
:config (auto-compile-on-load-mode))
(setq load-prefer-newer t)
We want to be able to customize our minor modes using :delight
in the
use-package
configurations. This allows us to set minor visibility on here.
(use-package delight :ensure t)
We also use-package w/ straight as well, co-pilot eg.
I don’t want any customizations stored in my init.el
file, that just
confuses things. Instead store it seperately.
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file :noerror)
Include .bashrc when executing shell commands.
(use-package exec-path-from-shell
:ensure t
:config (exec-path-from-shell-initialize)
)
You can setup some customizations for tramp. In particular, you can setup
connection parameters. By default, we want to connect using bash, which allows
us to include the PATH as defined by bashrc. I’m not sure about the point in
using use-package
in this case. This seems to be working, but still doesn’t
fix that fact that eglot
over tramp can’t find executables.
connection-local-set-profiles is a standard emacs setup. Run
tramp-cleanup-all-connections
if you make some changes here.
(use-package tramp
:ensure t
:config
(add-to-list 'tramp-connection-properties
(list (regexp-quote "/ssh:quinn.library.ucdavis.edu:")
"remote-shell" "/usr/bin/bash"))
;; nil selects all
(add-to-list 'tramp-connection-properties
(list nil "remote-shell" "/bin/bash"))
(connection-local-set-profile-variables
'remote-bash
'((explicit-shell-file-name . "/bin/bash")
(explicit-bash-args . ("-i"))))
(connection-local-set-profile-variables
'own-remote-path
'((tramp-remote-path . (tramp-own-remote-path tramp-default-remote-path))))
(connection-local-set-profiles
'(:application tramp ) 'own-remote-path)
(connection-local-set-profiles
'(:application tramp ) 'remote-bash)
)
These are some various extensions that are commonly used.
Crux is a commonly used set of commands/keystrokes, used in prelude, eg.
(use-package crux)
Lots of people have made some small initial modifications to some of the emacs defaults. There are a lot, like better-defaults.el, but I like a few of the items in sensible-defaults. This is also a good way to show how you can use git submodules to include other peoples’ packages that aren’t in the emacs repo. These are stored in the ~/.emacs.d/plugins]] location. However, we are using less and less of these entries, and pretty soon, we might be ready to move on without this.
(load-file "~/.emacs.d/plugins/sensible-defaults.el/sensible-defaults.el")
;; (sensible-defaults/open-files-from-home-directory)
(sensible-defaults/increase-gc-threshold)
;; (sensible-defaults/delete-trailing-whitespace)
;; (sensible-defaults/treat-camelcase-as-separate-words)
(sensible-defaults/automatically-follow-symlinks)
(sensible-defaults/make-scripts-executable)
;; (sensible-defaults/single-space-after-periods)
(sensible-defaults/offer-to-create-parent-directories-on-save)
(sensible-defaults/apply-changes-to-highlighted-region)
(sensible-defaults/overwrite-selected-text)
;; (sensible-defaults/ensure-that-files-end-with-newline)
(sensible-defaults/confirm-closing-emacs)
(sensible-defaults/quiet-startup)
(sensible-defaults/make-dired-file-sizes-human-readable)
(sensible-defaults/shorten-yes-or-no)
(sensible-defaults/always-highlight-code)
(sensible-defaults/refresh-buffers-when-files-change)
(sensible-defaults/show-matching-parens)
(sensible-defaults/flash-screen-instead-of-ringing-bell)
(sensible-defaults/set-default-line-length-to 80)
;; (sensible-defaults/open-clicked-files-in-same-frame-on-mac)
(sensible-defaults/yank-to-point-on-mouse-click)
;; These are the keybindings
(sensible-defaults/bind-commenting-and-uncommenting)
;; (sensible-defaults/bind-home-and-end-keys)
;; (sensible-defaults/bind-keys-to-change-text-size)
;; Save backups to /tmp
(sensible-defaults/backup-to-temp-directory)
;; Double space users rule
(setq sentence-end-double-space t)
These are used for more emacs customizations.
(defun hrs/view-buffer-name ()
"Display the filename of the current buffer."
(interactive)
(message (buffer-file-name)))
(defun hrs/generate-scratch-buffer ()
"Create and switch to a temporary scratch buffer with a random
name."
(interactive)
(switch-to-buffer (make-temp-name "scratch-")))
(defun hrs/de-unicode ()
"Tidy up a buffer by replacing all special Unicode characters
(smart quotes, etc.) with their more sane cousins"
(interactive)
(let ((unicode-map '(("[\u2018\|\u2019\|\u201A\|\uFFFD]" . "'")
("[\u201c\|\u201d\|\u201e]" . "\"")
("\u2013" . "--")
("\u2014" . "---")
("\u2026" . "...")
("\u00A9" . "(c)")
("\u00AE" . "(r)")
("\u2122" . "TM")
("[\u02DC\|\u00A0]" . " "))))
(save-excursion
(loop for (key . value) in unicode-map
do
(goto-char (point-min))
(replace-regexp key value)))))
(defun hrs/beautify-json ()
"Pretty-print the JSON in the marked region. Currently shells
out to `jsonpp'--be sure that's installed!"
(interactive)
(save-excursion
(shell-command-on-region (mark) (point) "jsonpp" (buffer-name) t)))
(defun hrs/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)))
(defun hrs/kill-current-buffer ()
"Kill the current buffer without prompting."
(interactive)
(kill-buffer (current-buffer)))
(defun hrs/visit-last-dired-file ()
"Open the last file in an open dired buffer."
(end-of-buffer)
(previous-line)
(dired-find-file))
(defun hrs/visit-last-migration ()
"Open the last file in 'db/migrate/'. Relies on projectile. Pretty sloppy."
(interactive)
(dired (expand-file-name "db/migrate" (projectile-project-root)))
(hrs/visit-last-dired-file)
(kill-buffer "migrate"))
(defun hrs/add-auto-mode (mode &rest patterns)
"Add entries to `auto-mode-alist' to use `MODE' for all given file `PATTERNS'."
(dolist (pattern patterns)
(add-to-list 'auto-mode-alist (cons pattern mode))))
(defun hrs/find-file-as-sudo ()
(interactive)
(let ((file-name (buffer-file-name)))
(when file-name
(find-alternate-file (concat "/sudo::" file-name)))))
These are just some additional customization flags, you can also find these in the Options area.
(save-place-mode t)
(show-paren-mode t)
In addition to normal set keys, we also want to use keychord extensions
(use-package key-chord
:init
(key-chord-mode 1)
:custom
(key-chord-two-keys-delay 0.1) ; default 0.1
(key-chord-one-key-delay 0.2) ; default 0.2
)
Here are some of the common keybindings from crux
;;(global-set-key (kbd "C-k") 'crux-smart-kill-line)
Assume that I always want to kill the current buffer when hitting C-x k
.
(global-set-key (kbd "C-x k") 'hrs/kill-current-buffer)
Use System style C-x
C-c
C-v
.
(cua-mode t)
These are some of the default keystrokes from HRS.
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(define-key global-map "\C-cc" 'org-capture)
It’s better to use the editorconfig files to set your ending whitespace, tab width, etc. This allows you to play better with other editors or collaborators.
(use-package editorconfig
:ensure t
:delight;;" .ec"
:config
(editorconfig-mode 1))
There are many,many themes. Emacs Themes is a good place to see alot of these.
If you want to interactively see how they affect your page, you can try M-x
custom-themes
(use-package solarized-theme
:ensure t)
It’s important to remember to fix your theme whenever you see a problem. This note on Emacs Custom Colors is a good summary. The basic idea is that when you see a bad color, select it and use ~C-u C-x = ~
Theme-Magic needs to have pywal installed. The best way is to install this as a
user with pip3 install --user pywal
. pywal is able to set the colors for the
alacritty terminals dynamically, but I’m not exactly sure how that’s done.
(use-package theme-magic
:config
(theme-magic-export-theme-mode)
:delight theme-magic-export-theme-mode
:ensure t)
Solarized Emacs theme allows you to use their setup, with any 8 color theme. The order in solarized is: darkest-base,brightest-base,yellow,orange,red,magenta,violet,blue,cyan,green.
These are converted in to .Xdefaults as:
sol # | sol col | .X # | .X col |
---|---|---|---|
0 | brightest-base | foreground | black |
1 | darkest-base | N/A | |
(fg+bg)/2 | background,15 | ||
2 | yellow | 1,9 | red |
3 | orange | 4 | blue |
4 | red | 3,11 | green |
5 | magenta | 5,13 | magenta |
6 | violet | N/A | |
7 | blue | 6,14 | cyan |
8 | cyan | 2,10 | yellow |
9 | green | 12 | bright blue |
blend | 7 | ||
blend | 8 |
;; inspired vim's jellybeans color-theme
(solarized-create-theme-file-with-palette 'light 'solarized-jellybeans-light
'("#202020" "#ffffff"
"#ffb964" "#8fbfdc" "#a04040" "#b05080" "#805090" "#fad08a" "#99ad6a" "#8fbfdd"))
(solarized-create-theme-file-with-palette 'dark 'solarized-jellybeans-dark
'("#202020" "#ffffff"
"#ffb964" "#8fbfdc" "#a04040" "#b05080" "#805090" "#fad08a" "#99ad6a" "#8fbfdd"))
;; https://marketingtoolbox.ucdavis.edu/brand-guide/colors
(solarized-create-theme-file-with-palette 'light 'solarized-ucd-light
'("#022851" "#FFF9E5"
"#79242F" "#003A5D" "#266041" "#79242F" "#AADA91" "#008EAA" "#266041" "#F18A00")
'((custom-theme-set-faces
theme-name
`(org-block-begin-line
((,class(:foreground ,(solarized-color-blend base03 base3 0.05 2)
:background ,(solarized-color-blend base03 base3 0.95 2)))))
`(org-block
((,class (:background ,(solarized-color-blend base03 base3 0.95 2)))))
`(org-block-end-line
((,class (:foreground ,(solarized-color-blend base03 base3 0.05 2)
:background ,(solarized-color-blend base03 base3 0.95 2)))))
)
`(mode-line
((,class (:foreground ,base2 :background ,(solarized-color-blend base03 base3 0.5 2)))))
`(mode-line-inactive
((,class (:foreground ,base00 :background ,(solarized-color-blend base03 "black" 0.85 2)))))
`(mode-line-buffer-id ((,class (:foreground ,base3 :weight bold))))
)
)
(solarized-create-theme-file-with-palette 'dark 'solarized-ucd-dark
'("#022851" "#FFF9E5"
"#79242F" "#003A5D" "#266041" "#79242F" "#AADA91" "#008EAA" "#266041" "#F18A00")
'((custom-theme-set-faces
theme-name
`(org-block-begin-line
((,class(:foreground ,(solarized-color-blend base03 base3 0.05 2)
:background ,(solarized-color-blend base03 base3 0.95 2)))))
`(org-block
((,class (:background ,(solarized-color-blend base03 base3 0.95 2)))))
`(org-block-end-line
((,class (:foreground ,(solarized-color-blend base03 base3 0.05 2)
:background ,(solarized-color-blend base03 base3 0.95 2)))))
))
)
I like the idea of using a seperate color for source blocks. There is a good example of colored blocks for the lueven theme, which also discusses block fontification. There is an example of using the solarization theme builder, but w/ custom faces in the wombat theme
The toolbar and scroll bar aren’t super useful, but I can never remember all the items in the menubar, so I leave that on.
(tool-bar-mode 0)
(menu-bar-mode 1)
(when window-system
(scroll-bar-mode -1))
The standard text-scale-
functions just resize the text in the current buffer;
I’d generally like to resize the text in every buffer, and I usually want to
change the size of the modeline, too (this is especially helpful when
presenting). These functions and bindings let me resize everything all together!
Note that this overrides the default font-related keybindings from
sensible-defaults
.
This sets the font to inconsolata, which usually isn’t available on a fresh
install. You can either comment that out, or install that font. On debian
machines that is the fonts-inconsolata
package.
(setq hrs/default-font "monospace")
(setq hrs/default-font-size 18)
(setq hrs/current-font-size hrs/default-font-size)
(setq hrs/font-change-increment 1.1)
(defun hrs/set-font-size ()
"Set the font to `hrs/default-font' at `hrs/current-font-size'."
(set-frame-font
(concat hrs/default-font "-" (number-to-string hrs/current-font-size))))
(defun hrs/reset-font-size ()
"Change font size back to `hrs/default-font-size'."
(interactive)
(setq hrs/current-font-size hrs/default-font-size)
(hrs/set-font-size))
(defun hrs/increase-font-size ()
"Increase current font size by a factor of `hrs/font-change-increment'."
(interactive)
(setq hrs/current-font-size
(ceiling (* hrs/current-font-size hrs/font-change-increment)))
(hrs/set-font-size))
(defun hrs/decrease-font-size ()
"Decrease current font size by a factor of `hrs/font-change-increment', down to a minimum size of 1."
(interactive)
(setq hrs/current-font-size
(max 1
(floor (/ hrs/current-font-size hrs/font-change-increment))))
(hrs/set-font-size))
(define-key global-map (kbd "C-)") 'hrs/reset-font-size)
(define-key global-map (kbd "C-+") 'hrs/increase-font-size)
(define-key global-map (kbd "C-=") 'hrs/increase-font-size)
(define-key global-map (kbd "C-_") 'hrs/decrease-font-size)
(define-key global-map (kbd "C--") 'hrs/decrease-font-size)
(hrs/reset-font-size)
moody
gives a truly lovely ribbon-based modeline.
(setq-default mode-line-format (delete '(vc-mode vc-mode) mode-line-format))
(use-package moody
:config
(setq x-underline-at-descent-line t)
(moody-replace-mode-line-buffer-identification))
;; Set visual-line-mode and change auto-fill-mode to " AF".
(use-package emacs
:delight
(auto-fill-function ".⏎")
(js-mode "JS")
(sh-mode "SH")
(eldoc-mode nil "eldoc")
:custom
(find-file-run-dired 1) ;; set to nill to disable
)
Years ago, I tried avy, and liked it, but it didn’t get into my normal
pattern. Avy can do anything, is an article that lays avy out in more detail.
The avy-setup-default
binds C-'
to avy-search in isearch.
(use-package avy
:ensure t
;; :config
;; (avy-setup-default)
:custom
(avy-timeout-seconds 0.5)
:bind
(
;;("C-c C-j" . avy-resume)
("C-;" . avy-resume)
("C-:" . avy-goto-char-timer)
:map isearch-mode-map
("C-'" . avy-isearch)
)
)
Vertico is a low level completion component. Basically, this just gives you better access to potential matches in your search buffer, in a vertical Vfashion.
(use-package vertico
:init
(vertico-mode)
;; Different scroll margin
;; (setq vertico-scroll-margin 0)
;; Show more candidates
;; (setq vertico-count 20)
;; Grow and shrink the Vertico minibuffer
;; (setq vertico-resize t)
;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
;; (setq vertico-cycle t)
)
(use-package orderless
:ensure t
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion))))
)
;; Example configuration for Consult
(use-package consult
;; Replace bindings. Lazily loaded due by `use-package'.
:bind (;; C-c bindings (mode-specific-map)
("C-c h" . consult-history)
("C-c m" . consult-mode-command)
("C-c k" . consult-kmacro)
;; C-x bindings (ctl-x-map)
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
;; Custom M-# bindings for fast register access
("M-#" . consult-register-load)
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
("C-M-#" . consult-register)
;; Other custom bindings
("M-y" . consult-yank-pop) ;; orig. yank-pop
("<help> a" . consult-apropos) ;; orig. apropos-command
;; M-g bindings (goto-map)
("M-g e" . consult-compile-error)
("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-g o" . consult-outline) ;; Alternative: consult-org-heading
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-g i" . consult-imenu)
("M-g I" . consult-imenu-multi)
;; M-s bindings (search-map)
("M-s d" . consult-find)
("M-s D" . consult-locate)
("M-s g" . consult-greprep)
("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-s m" . consult-multi-occur)
("M-s k" . consult-keep-lines)
("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map isearch-mode-map
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
;; Minibuffer history
:map minibuffer-local-map
("M-s" . consult-history) ;; orig. next-matching-history-element
("M-r" . consult-history)) ;; orig. previous-matching-history-element
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI.
:hook (completion-list-mode . consult-preview-at-point-mode)
;; The :init configuration is always executed (Not lazy)
:init
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
(setq register-preview-delay 0.5
register-preview-function #'consult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
;; Configure other variables and modes in the :config section,
;; after lazily loading the package.
:config
;; Optionally configure preview. The default value
;; is 'any, such that any key triggers the preview.
;; (setq consult-preview-key 'any)
;; (setq consult-preview-key (kbd "M-."))
;; (setq consult-preview-key (list (kbd "<S-down>") (kbd "<S-up>")))
;; For some commands and buffer sources it is useful to configure the
;; :preview-key on a per-command basis using the `consult-customize' macro.
(consult-customize
consult-theme
:preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-recent-file
consult--source-project-recent-file
;; :preview-key "M-."
)
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
(setq consult-narrow-key "<") ;; (kbd "C-+")
;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
;; By default `consult-project-function' uses `project-root' from project.el.
;; Optionally configure a different project root function.
;; There are multiple reasonable alternatives to chose from.
;;;; 1. project.el (the default)
;; (setq consult-project-function #'consult--default-project--function)
;;;; 2. projectile.el (projectile-project-root)
;; (autoload 'projectile-project-root "projectile")
;; (setq consult-project-function (lambda (_) (projectile-project-root)))
;;;; 3. vc.el (vc-root-dir)
;; (setq consult-project-function (lambda (_) (vc-root-dir)))
;;;; 4. locate-dominating-file
;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")))
)
You can use use-package
t configure parts of emacs as well. One thing, you
can do is alter your ls
listing for your favorite look in dired
.
(use-package dired
:ensure nil
:custom
(dired-listing-switches "-aBhl --group-directories-first"))
AutoFillMode
automatically wraps paragraphs, kinda like hitting M-q
. I wrap
a lot of paragraphs, so this automatically wraps ‘em when I’m writing text,
Markdown, or Org.
(add-hook 'text-mode-hook 'turn-on-auto-fill)
(add-hook 'gfm-mode-hook 'turn-on-auto-fill)
(add-hook 'org-mode-hook 'turn-on-auto-fill)
Sometimes, though, I don’t wanna wrap text. This toggles wrapping with C-c q
:
(global-set-key (kbd "C-c q") 'auto-fill-mode)
This is an updated help module. One reason I added it was as a test for a Help transient, that uses it. I guess I should still use the globals to get help at a point.
(use-package helpful
:config
;; Note that the built-in `describe-function' includes both functions
;; and macros. `helpful-function' is functions only, so we provide
;; `helpful-callable' as a drop-in replacement.
(global-set-key (kbd "C-h f") #'helpful-callable)
(global-set-key (kbd "C-h v") #'helpful-variable)
(global-set-key (kbd "C-h k") #'helpful-key)
;; Lookup the current symbol at point. C-c C-d is a common keybinding
;; for this in lisp modes.
(global-set-key (kbd "C-c C-d") #'helpful-at-point)
;; Look up *F*unctions (excludes macros).
;;
;; By default, C-h F is bound to `Info-goto-emacs-command-node'. Helpful
;; already links to the manual, if a function is referenced there.
(global-set-key (kbd "C-h F") #'helpful-function)
;; Look up *C*ommands.
;;
;; By default, C-h C is bound to describe `describe-coding-system'. I
;; don't find this very useful, but it's frequently useful to only
;; look at interactive functions.
(global-set-key (kbd "C-h C") #'helpful-command)
)
Custom vars: use a UTF-8 arrow, instead of the usual ellipsis (...
) that org
displays when there’s stuff under a header; Use syntax highlighting in source
blocks while editing; Make TAB act as if it were issued in a buffer of the
language’s major mode; When editing a code snippet, use the current window
rather than popping open a new one Editing Source Code.
(use-package org
:mode (( "\\.org$" . org-mode ))
:ensure org
:custom
(require 'ox-md)
(org-directory "~/.org")
(org-ellipsis "⤵")
(org-src-fontify-natively t)
(org-src-tab-acts-natively t)
(org-src-window-setup 'current-window)
(org-datetree-add-timestamp 'active)
(org-default-notes-file (concat org-directory "/notes.org"))
(org-agenda-files '("~/.org/"))
)
(use-package org-capture
:ensure nil
:after org
)
(require 'ox-md)
I’d like the initial scratch buffer to be in Org:
(setq initial-major-mode 'org-mode)
This adds nice UTF-8 bullets to outlines
(use-package org-bullets
:init
(add-hook 'org-mode-hook 'org-bullets-mode))
I’m looking into the best method for note taking. Originally, I was going
directly to org-roam
, and while I do like the literature notes, I think it’s
worth looking at the original emacs tools as well.
Agendas are a standard part of
org-mode
and can be used to find TODOS
etc. You can extend the standard
journals with =org-journal= which splits days up a bit more, maybe useful for
sharing via git. Two explainations of useing these are
http://cachestocaches.com/2016/9/my-workflow-org-agenda/,
http://www.howardism.org/Technical/Emacs/journaling-org.html and
http://doc.norang.ca/org-mode.html. There are some complaints that
org-journal
is too slow for searching, and more judicious use of org-capture
might also work. They seem a bit more complex, though, so I might just start w/
org-journal
.
I found this really great looking recipe mode.
(use-package org-chef
:ensure t)
(add-to-list 'org-capture-templates
'("j" "Journal entry" plain (function org-journal-find-location)
"** %(format-time-string org-journal-time-format)%^{Title}\n%i%?"
:jump-to-captured t :immediate-finish t))
(add-to-list 'org-capture-templates
'("c" "Cookbook" entry (file "~/org/cookbook.org")
"%(org-chef-get-recipe-from-url)"
:empty-lines 1))
(add-to-list 'org-capture-templates
'("m" "Manual Cookbook" entry (file "~/org/cookbook.org")
"* %^{Recipe title: }\n :PROPERTIES:\n :source-url:\n :servings:\n :prep-time:\n :cook-time:\n :ready-in:\n :END:\n** Ingredients\n %?\n** Directions\n\n"
))
Okay, our original plan will be to integrate org-journal into my framework,
but using org-capture
templates as the methodology to do this. I’m
currently expecting that
(use-package org-journal
:ensure t
:demand t
:init
(defun org-journal-find-location ()
;; Open today's journal, but specify a non-nil prefix argument in order to
;; inhibit inserting the heading; org-capture will insert the heading.
(org-journal-new-entry t)
(unless (or
(eq org-journal-file-type 'daily)
(eq org-journal-file-type 'weekly))
(org-narrow-to-subtree))
(goto-char (point-max)))
(defun org-journal-date-location (&optional scheduled-time)
(let ((scheduled-time (or scheduled-time (org-read-date nil nil nil "Date:"))))
(setq org-journal--date-location-scheduled-time scheduled-time)
(org-journal-new-entry t (org-time-string-to-time scheduled-time))
(unless (or
(eq org-journal-file-type 'daily)
(eq org-journal-file-type 'weekly))
(org-narrow-to-subtree))
(goto-char (point-max))))
:custom
(org-journal-prefix-key "C-c j ")
(org-journal-file-type 'daily)
(org-journal-dir "~/.org/journal")
(org-journal-file-format "%Y/%m/%Y%m%d")
(org-journal-date-format "%A,%Y%m%d")
(org-journal-enable-agenda-integration t)
:config
(add-to-list 'auto-mode-alist '("~.org/journal/[0-9]*$" . org-mode))
(add-to-list 'org-capture-templates
'("j" "Journal entry" plain (function org-journal-find-location)
"** %(format-time-string org-journal-time-format)%^{Title}\n%i%?"
:jump-to-captured t :immediate-finish t))
(add-to-list 'org-capture-templates
'("t" "TODO" plain (function org-journal-date-location)
"** TODO %?\n <%(princ org-journal--date-location-scheduled-time)>\n"
:jump-to-captured t))
)
Once we have our citations in org-roam, org-roam-bibtext shows how to incorporate into your paper writing utilities. Citar shows selection of citations, then.
There are some suggestions from HRS, bradwright, about good ways to use this, although I’m not sure about the
(use-package magit
:bind (("C-c g" . magit-status)
("C-c C-g l" . magit-file-log)
("C-c f" . magit-grep))
:config
; (use-package git-commit)
; (use-package magit-section)
; (use-package with-editor)
(magit-add-section-hook 'magit-status-sections-hook 'magit-insert-modules-overview 'append t)
(setq magit-push-always-verify t
git-commit-summary-max-length 50)
)
(use-package flymake
:config
(setq flymake-mode-line-title "x")
)
I’ve turned off global flychecking mode, to better test eglot as a checker.
;;(use-package flycheck
;; :ensure t
;; :init (global-flycheck-mode))
There are two competing Language server implementations, lsp-mode
and
=elgot=, as well as the debugger dape
dape is a debugger. I followed their install instructions for javascript, js-debug-dap-v1.94.0.tar.gz.
(use-package dape
:preface
;; By default dape shares the same keybinding prefix as `gud'
;; If you do not want to use any prefix, set it to nil.
;; (setq dape-key-prefix "\C-x\C-a")
;;:hook
;; Save breakpoints on quit
;; ((kill-emacs . dape-breakpoint-save)
;; Load breakpoints on startup
;; (after-init . dape-breakpoint-load))
:config
;; Turn on global bindings for setting breakpoints with mouse
;; (dape-breakpoint-global-mode)
;; Info buffers to the right
;; (setq dape-buffer-window-arrangement 'right)
;; Info buffers like gud (gdb-mi)
;; (setq dape-buffer-window-arrangement 'gud)
;; (setq dape-info-hide-mode-line nil)
;; Pulse source line (performance hit)
;; (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)
;; Showing inlay hints
;; (setq dape-inlay-hints t)
;; Save buffers on startup, useful for interpreted languages
;; (add-hook 'dape-start-hook (lambda () (save-some-buffers t t)))
;; Kill compile buffer on build success
;; (add-hook 'dape-compile-hook 'kill-buffer)
;; Projectile users
;; (setq dape-cwd-fn 'projectile-project-root)
)
;; Enable repeat mode for more ergonomic `dape' use
(use-package repeat
:config
(repeat-mode))
2022-12-20 elgot
is or soon will be supported directly in EMACS base, so it’s seems
like it’s making a large splash in the community. For using javascript I
also needed to do snap install typescript-language-server
in order to get
the javascript supported.
I was having trouble getting good intergration w/ the bash-language-server, but it turns out that was just because I didn’t have shellcheck installed, which provides alot of the functionality.
(use-package eglot
)
(add-to-list 'major-mode-remap-alist '(js-mode . js-ts-mode))
(add-to-list 'major-mode-remap-alist '(bash-mode . bash-ts-mode))
We can use the standard sql-mode, but we really need to add in the sql-indent minor mode, esp for source code blocks.
(use-package sql-indent
:after sql
)
I think that sparql-mode just assumes that ob-http (which is super old), just exists.
(use-package ob-http)
(use-package sparql-mode
:mode (( "\\.sparql$" . sparql-mode )
( "\\.ru$" . sparql-mode )
( "\\.rq$" . sparql-mode )
)
:ensure sparql-mode
)
We should try and use co-pilot via emacs tutorial
(use-package jsonrpc)
(use-package copilot
:vc (:url "https://github.com/copilot-emacs/copilot.el"
:rev :newest
:branch "main"))
(define-key copilot-completion-map (kbd "<tab>") 'copilot-accept-completion)
(define-key copilot-completion-map (kbd "TAB") 'copilot-accept-completion)
(add-hook 'prog-mode-hook 'copilot-mode)
Although, I don’t use it often, jq-mode
can be useful for longish jq
scripts. More importantly, it can be used with babel
for literate programming.
n
(use-package flymake-collection
:hook (after-init . flymake-collection-hook-setup)
)
(use-package json-mode
:mode (("\\.json(ld)?$" . json-mode))
:flymake-hook
:custom
(js-indent-level 2)
(json-mode
(flymake-collection-jsonlint ; Added when predicate is true.
:predicate (lambda ()
(executable-find "jsonlint"))))
)
(use-package jq-mode
:mode (("\\.jq$" . jq-mode))
)
There are a few things that make life more simple in docker. One of them is being able to easily edit files within a container. This is a super great feature, you can also use eshell within a tramp docker session. This is standard in emacs now
This seems to be the best folding setup.
(global-set-key (kbd "M-<tab>") 'ts-fold-toggle)
;; (key-chord-define-global "" 'ts-fold-open-all)
I’m building a transient for Code Folding.
Second only to org-mode, babel
is the greatest component for literate
programming, it allows for multiple languages to be added to SRC blocks.
;; (use-package gnuplot)
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(sql . t)
(shell . t)
(ruby . t)
(dot . t)
(jq . t)
(sparql . t)
(http . t)
(js . t)
(eshell . t)
(gnuplot . t)
))
Don’t ask before evaluating code blocks.
(setq org-confirm-babel-evaluate nil)
Translate regular ol’ straight quotes to typographically-correct curly quotes when exporting.
(setq org-export-with-smart-quotes t)
UML diagrams is not super well supported currently, but you can
(setq org-plantuml-jar-path
(expand-file-name "/usr/share/plantuml/plantuml.jar"))
(add-to-list 'org-src-lang-modes '("uml" . plantuml))
Use htmlize
to ensure that exported code blocks use syntax highlighting.
(use-package htmlize)
Associate the “dot” language with the graphviz-dot
major mode.
(use-package graphviz-dot-mode)
(add-to-list 'org-src-lang-modes '("dot" . graphviz-dot))
(use-package transient)
I’m building this out myself
(transient-define-prefix ts-fold-transient()
"Program folding"
["Folding Commands"
("c" "close" ts-fold-close)
("C-o" "open recursively" ts-fold-open-recursively)
("o" "open" ts-fold-open)
("O" "open all" ts-fold-open-all)
("<tab>" "toggle" ts-fold-toggle)
]
["Mode Setup"
("m" "mode" tree-sitter-mode)
]
)
(global-set-key (kbd "C-c f") 'ts-fold-transient)
(global-set-key (kbd "M-<tab>") 'ts-fold-toggle)
;; (global-set-key (kbd "C-<tab>") 'ts-fold-toggle)
;; Need to add keychord
;; (global-set-key (kbd "C-<tab> C-<tab>") 'ts-fold-open-all)
This example found on reddit. It’s a good lisp internal example.
(transient-define-prefix hrm-help-transient ()
"Help commands that I use. A subset of C-h with others thrown in."
["Help Commands"
["Mode & Bindings"
("m" "Mode" describe-mode)
("b" "Major Bindings" which-key-show-full-major-mode)
("B" "Minor Bindings" which-key-show-full-minor-mode-keymap)
("d" "Descbinds" counsel-descbinds)
("t" "Top Bindings " which-key-show-top-level)
]
["Describe"
("C" "Command" helpful-command)
("f" "Function" helpful-callable)
("v" "Variable" helpful-variable)
("k" "Key" helpful-key)
("c" "Key Briefly" describe-key-briefly)
]
["Info on"
("C-c" "Emacs Command" Info-goto-emacs-command-node)
("C-f" "Function" counsel-info-lookup-symbol) ; s for symbol?
("C-v" "Variable" counsel-info-lookup-symbol) ; . for symbol?
("C-k" "Emacs Key" Info-goto-emacs-key-command-node)
]
["Goto Source"
("L" "Library" find-library-other-frame)
("F" "Function" find-function-other-frame)
("V" "Variable" find-variable-other-frame)
("K" "Key" find-function-on-key-other-frame)
]
]
[
["Internals"
("I" "Input Method" describe-input-method)
("G" "Language Env" describe-language-environment)
("S" "Syntax" describe-syntax)
("O" "Coding System" describe-coding-system)
("C-o" "Coding Brief" describe-current-coding-system-briefly)
("T" "Display Table" describe-current-display-table)
("e" "Echo Messages" view-echo-area-messages)
("l" "Lossage" view-lossage)
]
["Describe"
("s" "Symbol" helpful-symbol)
("." "At Point " helpful-at-point)
("C-f" "Face" counsel-describe-face)
("w" "Where Is" where-is)
("=" "Position" what-cursor-position)
]
;; ["Info Manuals"
;; ("C-i" "Info" info)
;; ("C-4" "Other Window " info-other-window)
;; ("C-e" "Emacs" info-emacs-manual)
;; ("C-l" "Elisp" info-elisp-manual)
;; ]
;; ["External"
;; ("W" "Dictionary" lookup-word-at-point)
;; ("D" "Dash" dash-at-point)
;; ]
]
)
(global-set-key (kbd "C-S-h") 'hrm-help-transient)
(require 'cl-lib)
(transient-define-suffix pmx-show-prefix ()
"Show the prefix that invoked this suffix"
:description "prefix"
(interactive)
(message "Current prefix key: %s" transient-current-prefix))
(transient-define-suffix pmx-show-command ()
"Show this command"
:description "current command"
(interactive)
(message "Current command: %s" transient-current-command))
(transient-define-suffix pmx-show-suffixes ()
"Show the current suffixes"
:description "suffixes"
(interactive)
(message "Current suffixes: %s" (cl-mapcar
(lambda (obj)
(oref obj description))
transient-current-suffixes)))
(transient-define-suffix pmx-show-args ()
"Show current infix args"
:description "infix args"
(interactive)
(message "Current infix args: %s" (transient-args transient-current-command)))
(transient-define-suffix pmx-send-message ()
"Send message to minibuffer"
:description "send message"
:transient t
(interactive)
(message "Message sent at %s. Happy?" (shell-command-to-string "echo -n $(date)")))
(transient-define-argument pmx-affirmative ()
"Are we affirmative?"
:description "affirmative"
:argument "affirmative")
(transient-define-argument pmx-yep-nope ()
"Is it yep or is it nope?"
:description "yep or nope"
:class 'transient-option
:shortarg "-y"
:argument "--yepnope="
:choices '("yep" "nope"))
(transient-define-argument pmx-abc ()
"Which letters do you like?"
:description "abc"
:class 'transient-option
:shortarg "-a"
:argument "--abc="
:choices '("A" "B" "C"))
(defvar pmx--variable "A string" "A variable brought to you by pmx")
(transient-define-argument pmx-set-lisp-variable ()
"Set a lisp variable, pmx--variable. Won't show up in infix arguments."
:description "set pmx--variable"
:class 'transient-lisp-variable
:shortarg "-l"
:variable 'pmx--variable
:argument "--letters=")
(transient-define-suffix pmx-show-lisp-variable ()
"Access pmx--variable"
:description "show pmx--variable"
(interactive)
(message "Current value of pmx--variable: %s" pmx--variable))
(transient-define-suffix pmx-dynamic-suffix ()
"Description depends on pmx--variable"
:if-not '(lambda () (string-equal pmx--variable "abc"))
:description '(lambda () (format "pmx %s" pmx--variable))
(interactive)
(message "Current value of pmx--variable: %s" pmx--variable))
(transient-define-prefix pmx-nested-transient ()
"Some subcommands, like tree menus from the land of mice"
["Switches"
("-s" "another switch" ("-x" "--conflicting"))]
["Sub Command Introspection"
("i" pmx-show-args)
("p" pmx-show-prefix)
("s" pmx-show-suffixes)
("c" pmx-show-command)]
["Dynamic Commands"
("d" pmx-dynamic-suffix)])
(transient-define-prefix pmx-transient-toy ()
"Figure out how to use transient's API properly"
[:class transient-columns
["Things"
("-w" "switch" ("-w" "--switch"))]
["Others"
("i" pmx-show-args)
("p" pmx-show-prefix)
("s" pmx-show-suffixes)
("c" pmx-show-command)
("m" pmx-send-message)]
["More"
("f" pmx-affirmative)
("y" pmx-yep-nope)
("a" pmx-abc)
("l" pmx-set-lisp-variable)
("w" pmx-show-lisp-variable)]
["Drilldown"
("d" "drilldown" pmx-nested-transient)]])
(global-set-key (kbd "M-o") 'pmx-transient-toy)