Skip to content

qjhart/.emacs.d

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Emacs configuration

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

Configuration

Configure use-package

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)

Configure w/ straight.el

We also use-package w/ straight as well, co-pilot eg.

Custom Auto-generated customizations

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)

Emacs Path

Include .bashrc when executing shell commands.

(use-package exec-path-from-shell
:ensure t
:config (exec-path-from-shell-initialize)
)

Tramp

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)
  )

Editor Keystrokes

Command extensions

These are some various extensions that are commonly used.

crux

Crux is a commonly used set of commands/keystrokes, used in prelude, eg.

(use-package crux)

sensible defaults

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)

Utility Functions

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)))))

Better Custom

These are just some additional customization flags, you can also find these in the Options area.

(save-place-mode t)
(show-paren-mode t)

Set Keys

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)

Editorconfig

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))

Emacs Look and Feel

Themes

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

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
0brightest-baseforegroundblack
1darkest-baseN/A
(fg+bg)/2background,15
2yellow1,9red
3orange4blue
4red3,11green
5magenta5,13magenta
6violetN/A
7blue6,14cyan
8cyan2,10yellow
9green12bright blue
blend7
blend8
;; 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

Menu Bars

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))

Set default font and configure font resizing

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)

Modeline

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
  )

avy

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

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)
  )

orderless

(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion))))
  )

consult

;; 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")))
)

dired

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"))

Wrap paragraphs automatically

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)

Helpful

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)
    )

Org Mode

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)

Look and Feel

This adds nice UTF-8 bullets to outlines

(use-package org-bullets
  :init
  (add-hook 'org-mode-hook 'org-bullets-mode))

Note Taking

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.

org-chef

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"
               ))

org-journal

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))
)

org-roam

citations

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.

Programming

Magit

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)
  )

flymake/flycheck

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

Debugging

There are two competing Language server implementations, lsp-mode and =elgot=, as well as the debugger dape

LSP-mode

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))

elgot

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))

SQL 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
  )

Sparql / TTL /TRIG

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
)

Co-pilot

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)

JSON

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))
)

Docker

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

Tree sitter packages

ts-fold

This seems to be the best folding setup.

Keystrokes

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

Babel

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

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))

htmlize

Use htmlize to ensure that exported code blocks use syntax highlighting.

(use-package htmlize)

dot

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))

Transients

(use-package transient)

Code Folding

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)

Help transient

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)

pmx-transient-toy

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

About

Sharable .emacs.d setup

Resources

License

Stars

Watchers

Forks

Packages

No packages published