emacs configuration
TODO Tangling with lob blocks
I used to use this file header
# -*- eval: (add-hook 'after-save-hook 'my-tangle-init nil t); -*-
and this function
(defun my-tangle-init ()
(mapcar 'org-babel-lob-ingest (directory-files "~/data/org/config" nil ".*.org"))
(org-babel-tangle-file "~/data/org/config/emacs.org"))
to add config blocks to the library of babel (lob) so they could be called from any file.
But now I think this is better:
And really I should see if org upstream would just let file references in non-called noweb references.
So noweb references like this <<website.org:org-publish-project-blk>> work instead of needing to go through babel execution.
Currently this relys on org src block execution semantics always returning the contents and isn’t technically semantically correct because were putting noweb references to elisp code into an org mode src block…
early-init.el
Take a look at https://github.com/hlissner/doom-emacs/blob/develop/early-init.el
;;; early-init.el -*- lexical-binding: t; -*-
;; A big contributor to startup times is garbage collection. We up the gc
;; threshold to temporarily prevent it from running, then reset it later by
;; enabling `gcmh-mode'. Not resetting it will cause stuttering/freezes.
; (setq gc-cons-threshold most-positive-fixnum)
(setq package-enable-at-startup nil)
;(push '(undecorated-round . t) default-frame-alist)
(push '(undecorated . t) default-frame-alist)
(push '(fullscreen . maximized) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)
(push '(font . "Menlo 12") default-frame-alist)
- DejaVu Sans Mono is also a nice font on which Menlo is based
.emacs
header
;; -*- mode: emacs-lisp; lexical-binding: t; -*-
; Do not edit this file directly!
; This file was generated by running ~org-babel-tangle~ on dotfiles.org
elpaca
(defvar elpaca-installer-version 0.11)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1 :inherit ignore
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (<= emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let* ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
;; Install use-package support
(elpaca elpaca-use-package
;; Enable use-package :ensure support for Elpaca.
(elpaca-use-package-mode)
(setq use-package-always-ensure t))
(setq elpaca-ignored-dependencies
(delq 'transient
(delq 'org elpaca-ignored-dependencies)))
(elpaca-wait) ;; Block until current queue processed.
;; https://github.com/progfolio/elpaca/issues/181
(use-package auctex
:ensure (auctex :pre-build (("./autogen.sh")
("./configure"
"--without-texmf-dir")
("make"))))
(elpaca-wait) ;; esure auctex is installed properly
(use-package compat) ; might as well add it here so elpaca doesn't show it as an orphan
TODO exec-path-from-shell
figure out why not picking up stuff from .profile?
(use-package exec-path-from-shell
:config
(when (memq window-system '(mac ns x))
(exec-path-from-shell-initialize)))
better-defaults
;(menu-bar-mode -1)
(tool-bar-mode -1)
(when window-system (scroll-bar-mode -1))
(setq frame-resize-pixelwise t)
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)
(require 'saveplace)
(setq-default save-place t)
(show-paren-mode 1)
(setq-default indent-tabs-mode nil)
(setq apropos-do-all t
require-final-newline t
load-prefer-newer t
ediff-window-setup-function 'ediff-setup-windows-plain
save-place-file (concat user-emacs-directory "places")
backup-directory-alist `(("." . ,(concat user-emacs-directory
"backups"))))
;; Speed up tramp
;; https://www.gnu.org/software/emacs/manual/html_node/tramp/Frequently-Asked-Questions.html
(setq vc-ignore-dir-regexp
(format "\\(%s\\)\\|\\(%s\\)"
vc-ignore-dir-regexp
tramp-file-name-regexp))
;; Ensure tramp works on guix remotes
;; https://lists.gnu.org/archive/html/help-guix/2016-10/msg00049.html
(require 'tramp)
(setq tramp-remote-path
(append tramp-remote-path
'(tramp-own-remote-path
"~/.guix-profile/bin" "~/.guix-profile/sbin"
"/run/current-system/profile/bin"
"/run/current-system/profile/sbin")))
(setq tramp-remote-process-environment
'("GUIX_LOCPATH=\"$HOME/.guix-profile/lib/locale\""))
(blink-cursor-mode 0)
;; When emacs asks for "yes" or "no", let "y" or "n" suffice
(fset 'yes-or-no-p 'y-or-n-p)
(setq inhibit-startup-message t)
(setq ring-bell-function 'ignore)
(setq confirm-kill-emacs 'yes-or-no-p)
(setq-default fill-column 80)
(setq sentence-end-double-space nil)
(setq auth-source-save-behavior nil)
(setq custom-file (concat user-emacs-directory "custom.el"))
(setq woman-fill-frame t)
(load custom-file)
(setq user-full-name "Akira Kyle"
user-mail-address "akira@akirakyle.com")
(setq css-indent-offset 2)
eww
(use-package eww
:ensure nil
:custom
(eww-auto-rename-buffer 'title)
;; https://github.com/alphapapa/unpackaged.el#eww-imenu-support
:config
(defun unpackaged/imenu-eww-headings ()
"Return alist of HTML headings in current EWW buffer for Imenu.
Suitable for `imenu-create-index-function'."
(let ((faces '(shr-h1 shr-h2 shr-h3 shr-h4 shr-h5 shr-h6 shr-heading)))
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(cl-loop for next-pos = (next-single-property-change (point) 'face)
while next-pos
do (goto-char next-pos)
for face = (get-text-property (point) 'face)
when (cl-typecase face
(list (cl-intersection face faces))
(symbol (member face faces)))
collect (cons (buffer-substring (point-at-bol) (point-at-eol)) (point))
and do (forward-line 1))))))
(add-hook 'eww-mode-hook
(lambda ()
(setq-local imenu-create-index-function #'unpackaged/imenu-eww-headings)))
)
theme
(use-package doom-themes
:config
(load-theme 'doom-one t)
(doom-themes-org-config))
(use-package all-the-icons)
doom-modeline
M-x all-the-icons-install-fonts
(use-package doom-modeline
:init
(setq doom-modeline-icon t);(display-graphic-p)
(column-number-mode 1)
(doom-modeline-mode 1)
;;(setq doom-modeline-window-width-limit 80);;fill-column
;;(setq doom-modeline-minor-modes nil)
)
minibuffer-statusbar
(use-package minibuffer-statusbar
:straight (minibuffer-statusbar :type git :host github
:repo "akirakyle/minibuffer-statusbar")
:config
(minibuffer-statusbar-mode t)
(global-eldoc-mode -1))
frames and windows
(setq split-height-threshold nil) ;40)
(setq split-width-threshold 160) ;100) ;nil)
hl-line-mode
;(use-package hl-line-mode
; :no-require t
; :config
(global-hl-line-mode t)
(make-variable-buffer-local 'global-hl-line-mode)
(add-hook 'vterm-mode-hook (lambda () (setq global-hl-line-mode nil)))
;)
highlight column 80
(use-package whitespace
:ensure nil
:config
(setq whitespace-style '(face lines-char))
(add-hook 'prog-mode-hook 'whitespace-mode))
general
(use-package general
:demand t
:config
;;(define-key key-translation-map (kbd "C-h") (kbd "<DEL>"))
(general-define-key
;;:keymaps 'override
"C-h" (general-simulate-key "<backspace>"))
(general-define-key
:keymaps 'override
"C-<tab>" #'(lambda () (interactive) (switch-to-buffer nil)))
(defun my-start-app (command)
(interactive (list (read-shell-command "$ ")))
(start-process-shell-command command nil command))
(defun my-toggle-window-split ()
(interactive)
(if (eq (count-windows) 1)
(progn
(split-window-right)
(other-window 1)
(switch-to-buffer nil)
(other-window 1))
(delete-other-windows)))
(general-create-definer my-leader-def
:prefix "SPC"
:prefix-command 'my-leader-prefix-cmd
:states '(normal visual motion)
:keymaps 'override)
(general-define-key
:keymaps '(override exwm-mode-map)
"C-SPC" 'my-leader-prefix-cmd)
;; make iterated prefix commands like C-u C-u C-u actually work
(general-define-key
:keymaps 'universal-argument-map
"SPC u" 'universal-argument-more
"C-SPC u" 'universal-argument-more)
(general-create-definer my-local-leader-def
:prefix ","
:states '(normal visual motion)
:keymaps 'override)
(my-leader-def
"SPC" 'execute-extended-command
"u" 'universal-argument
"'" 'vterm
"a" '(:ignore t :which-key "apps")
"as" '(:ignore t :which-key "shell")
"ase" 'eshell
"ass" 'shell
"ast" 'ansi-term
"asv" 'vterm
"aw" 'woman
"w" '(:ignore t :which-key "windows")
"ww" 'my-toggle-window-split
"w/" 'split-window-right
"w-" 'split-window-below
"w=" 'balance-windows
"wd" 'delete-window
"b" 'consult-buffer ;'switch-to-buffer
"C-b" 'consult-buffer ;'switch-to-buffer
;;"c" '(:ignore t :which-key "cd")
"c" '(:ignore t :which-key "buffers")
"cc" 'ibuffer
"ck" 'kill-current-buffer
"cu" 'revert-buffer
"cd" 'cd
"cw" 'widen
"q" '(:ignore t :which-key "quit")
"qq" 'save-buffers-kill-emacs
"f" '(:ignore t :which-key "files")
"ff" 'find-file
"fs" 'save-buffer
"fa" 'save-some-buffers
;;"h" 'help
"h" '(:ignore t :which-key "help")
"hh" 'describe-symbol
"hm" 'describe-mode
"hk" 'describe-key
"hf" 'describe-function
"hv" 'describe-variable
"hb" 'describe-bindings
"j" '(:ignore t :which-key "jump")
"ji" 'consult-imenu ;'imenu
"s" '(:ignore t :which-key "search")
"e" 'my-start-app
"z" 'describe-bindings
"tv" 'visual-line-mode
"tt" 'toggle-truncate-lines
"tw" 'whitespace-mode
)
)
(elpaca-wait)
which-key
(use-package which-key
:config
(which-key-mode)
)
evil
I edited
(defun evil-search-message (string forward) “Prefix STRING with the search prompt.” (format “%s%s%s” (isearch-lazy-count-format) (evil-search-prompt forward) string))
;(use-package undo-tree
; :init
; (setq undo-tree-auto-save-history nil)
; :config
; (global-undo-tree-mode)
; )
(use-package vundo)
(use-package evil
:init
(setq evil-want-keybinding nil
evil-disable-insert-state-bindings t
;; evil-want-minibuffer t
evil-want-C-u-scroll t
evil-want-C-i-jump nil
evil-move-cursor-back nil
evil-move-beyond-eol t
evil-undo-system 'undo-redo)
(setq evil-normal-state-cursor '(box "DarkGoldenrod2")
evil-insert-state-cursor '((bar . 2) "chartreuse3")
evil-emacs-state-cursor '(box "SkyBlue2")
evil-hybrid-state-cursor '((bar . 2) "SkyBlue2")
evil-replace-state-cursor '((hbar . 2) "chocolate")
evil-evilified-state-cursor '(box "LightGoldenrod3")
evil-visual-state-cursor '((hbar . 2) "gray")
evil-motion-state-cursor '(box "plum3")
evil-lisp-state-cursor '(box "HotPink1")
evil-iedit-state-cursor '(box "firebrick1")
evil-iedit-insert-state-cursor '((bar . 2) "firebrick1")
)
:config
(evil-mode 1)
(evil-set-initial-state 'term-mode 'emacs)
(define-key evil-normal-state-map (kbd "j") 'evil-next-visual-line)
(define-key evil-normal-state-map (kbd "k") 'evil-previous-visual-line)
)
(use-package evil-collection
:after evil
;;:custom
;;(evil-collection-setup-minibuffer nil)
:config
; see https://github.com/emacs-evil/evil-collection/pull/397
; overshadows bindings in emacs-webkit and xwidget-webkit
;(setq evil-collection-mode-list (delete 'simple evil-collection--supported-modes))
(evil-collection-init)
)
(use-package evil-matchit
:after evil
:config
(global-evil-matchit-mode 1))
(use-package evil-surround
:after evil
:config
; https://github.com/emacs-evil/evil-surround/pull/48
;(evil-define-key 'visual evil-surround-mode-map "s" 'evil-surround-region)
;(evil-define-key 'visual evil-surround-mode-map "S" 'evil-substitute)
(global-evil-surround-mode 1))
(use-package evil-tex
:after evil
)
;;(use-package evil-easymotion
;; :config
;; (evilem-default-keybindings "SPC j")
;; )
TODO smartparens and rainbow-delimiters
(use-package smartparens
:config
(sp-local-pair 'org-mode "$" "$")
(sp-local-pair 'org-mode '"\\[" "\\]")
(add-hook 'prog-mode-hook #'smartparens-mode)
(add-hook 'org-mode-hook #'smartparens-mode)
)
(use-package rainbow-delimiters
:config
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
)
ivy
What I really want is just for buffer switching to be in a centered posframe over everything? https://oremacs.com/swiper/#key-bindings https://siawyoung.com/blog/code/2020-02-10-vterm-ibuffer
(use-package ivy
:init
(setq recentf-max-saved-items 50)
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t)
(setq ivy-count-format "(%d/%d) ")
(setq ivy-height 20)
:config
(ivy-mode 1)
(general-def
:keymaps 'ivy-minibuffer-map
"C-<return>" 'ivy-immediate-done
"C-d" 'ivy-scroll-up-command
"C-u" 'ivy-scroll-down-command
)
)
(use-package counsel
:config
(counsel-mode 1)
(my-leader-def "sa" 'counsel-ag)
(my-leader-def "fg" 'counsel-git)
)
(use-package swiper
:config
(general-define-key "C-s" 'swiper)
(my-leader-def "ss" 'swiper)
)
(use-package ivy-avy)
(use-package amx)
(use-package ivy-rich
:init
(setq ivy-rich-parse-remote-buffer nil)
;;(setq ivy-format-function #'ivy-format-function-line)
:config
(ivy-rich-mode 1)
(ivy-rich-project-root-cache-mode 1)
)
;use-package ivy-posframe
; :config
; (put 'ivy-posframe 'face-alias 'default)
; (setq ivy-posframe-border-width 5)
; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-center)))
; (setq ivy-posframe-display-functions-alist
; '((swiper . ivy-posframe-display-at-point)
; (complete-symbol . ivy-posframe-display-at-point)
; (t . ivy-posframe-display-at-frame-center)))
; ;(ivy-posframe-mode 1)
; )
vertico
(use-package vertico
:ensure (vertico :files (:defaults "extensions/*"))
:init
(vertico-mode)
(setq vertico-count 16
vertico-cycle t)
;(require 'vertico-directory)
(general-def
:keymaps 'vertico-map
"C-d" 'vertico-scroll-up
"C-u" 'vertico-scroll-down
;"RET" 'vertico-directory-enter
"DEL" 'vertico-directory-delete-char
)
)
(use-package vertico-directory
:ensure nil
:after vertico)
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:ensure nil
:init
(savehist-mode))
(use-package emacs
:ensure nil
:init
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t))
orderless
(use-package orderless
:init
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles . (partial-completion))))))
consult
(use-package consult
:config
(consult-customize
consult-buffer
:preview-key "M-.")
; https://github.com/minad/consult/issues/651
(defun consult--buffer-sort-mru(xs)
(append (cdr xs) (list (car xs))))
(plist-put consult--source-buffer :items
(lambda() (consult--buffer-query :sort 'mru :as #'buffer-name)))
(general-define-key "C-s" 'consult-line)
(my-leader-def "ss" 'consult-line)
(my-leader-def "sa" 'consult-ripgrep)
(my-leader-def "fp" 'consult-project-buffer)
(recentf-mode)
; from the consult wiki https://github.com/minad/consult/wiki
(defvar consult--previous-point nil
"Location of point before entering minibuffer.
Used to preselect nearest headings and imenu items.")
(defun consult--set-previous-point ()
"Save location of point. Used before entering the minibuffer."
(setq consult--previous-point (point)))
(advice-add #'consult-org-heading :before #'consult--set-previous-point)
(advice-add #'consult-outline :before #'consult--set-previous-point)
(advice-add #'vertico--update :after #'consult-vertico--update-choose)
(defun consult-vertico--update-choose (&rest _)
"Pick the nearest candidate rather than the first after updating candidates."
(when (and consult--previous-point
(memq current-minibuffer-command
'(consult-org-heading consult-outline)))
(setq vertico--index
(max 0 ; if none above, choose the first below
(1- (or (seq-position
vertico--candidates
consult--previous-point
(lambda (cand point-pos) ; counts on candidate list being sorted
(> (cl-case current-minibuffer-command
(consult-outline
(car (consult--get-location cand)))
(consult-org-heading
(get-text-property 0 'consult--candidate cand)))
point-pos)))
(length vertico--candidates))))))
(setq consult--previous-point nil))
)
;(use-package consult-ag
; :config
; (my-leader-def "sa" 'consult-ag)
; )
marginalia
(use-package all-the-icons-completion
:config
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup)
)
(use-package marginalia
:init
(marginalia-mode))
embark
(use-package embark
:bind
(("C-." . embark-act))
;("C-;" . embark-dwim) ;; good alternative: M-.
;("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
:config
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none))))
(defvar my-org-roam-map
(let ((map (make-sparse-keymap)))
;(define-key map (kbd "t") 'org-roam-buffer-toggle)
(define-key map (kbd "i") 'org-roam-node-insert)
(define-key map (kbd "f") 'org-roam-node-find)
;(define-key map (kbd "r") 'org-roam-ref-find)
;(define-key map (kbd "g") 'org-roam-show-graph)
;(define-key map (kbd "c") 'org-roam-capture)
;(define-key map (kbd "j") 'org-roam-dailies-capture-today)
map)
"Keymap for 'org-roam' v2.")
; make available my-org-roam-map to embark-act
(add-to-list 'embark-keymap-alist '(org-roam-node . my-org-roam-map))
)
;; Consult users will also want the embark-consult package.
(use-package embark-consult
:after (embark consult))
avy
(use-package avy
:config
(avy-setup-default)
(setq avy-all-windows nil)
(setq avy-keys '(?a ?o ?e ?u ?h ?t ?n ?s))
(setq avy-timeout-seconds 0.2)
(general-define-key :states 'normal "gc" 'evil-avy-goto-char-timer);;evil-avy-goto-char-2)
(general-define-key :states '(normal insert) "C-'" 'evil-avy-goto-char-timer);;evil-avy-goto-char-2)
)
ace
(use-package ace-link
:config
(ace-link-setup-default)
(general-define-key :states 'normal :keymaps 'Info-mode-map "o" 'ace-link-info)
(general-define-key :states 'normal :keymaps 'help-mode-map "o" 'ace-link-help)
(general-define-key :states 'normal :keymaps 'help-mode-map "o" 'ace-link-help)
(my-local-leader-def :keymaps 'org-mode-map "o" 'ace-link-org)
)
(use-package ace-window
:config
(setq aw-keys '(?h ?t ?n ?s))
(setq aw-scope 'frame)
(general-define-key :keymaps 'override "M-<tab>" 'ace-window)
)
corfu
(use-package corfu
:init
(setq tab-always-indent 'complete
;corfu-auto t
;corfu-auto-delay 0
corfu-preselect-first nil
corfu-quit-at-boundary nil
;corfu-quit-no-match t
)
:config
(global-corfu-mode)
(defun corfu-enable-always-in-minibuffer ()
"Enable Corfu in the minibuffer if Vertico is not active."
(unless (bound-and-true-p vertico--input)
;; (setq-local corfu-auto nil) Enable/disable auto completion
(corfu-mode 1)))
(add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1)
)
(use-package kind-icon
:after corfu
:custom
(kind-icon-default-face 'corfu-default) ; to compute blended backgrounds correctly
:config
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
tempel
modified tempel.el
@@ -598,7 +598,8 @@ This is meant to be a source in `tempel-template-sources'."
(let ((completion-at-point-functions (list capf))
completion-cycle-threshold)
(tempel--save)
- (or (completion-at-point) (user-error "%s: No completions" capf))))
+ (completion-at-point)))
+ ;(or (completion-at-point) (user-error "%s: No completions" capf))))
(defun tempel--completion-table (templates)
"Return a completion table for a list of TEMPLATES.
(use-package tempel
:bind
(:map tempel-map
([tab] . tempel-next)
([backtab] . tempel-previous))
:init
;;(add-to-list 'org-structure-template-alist '("p" . "src python"))
(defun my-templates ()
(cond ((derived-mode-p 'org-mode)
'((today (format-time-string "%Y-%m-%d"))
(bl "#+begin_" (p "src" block) " " p n r n "#+end_" (s block))
(py "#+begin_src python" n r n "#+end_src")
(jl "#+begin_src julia" n r n "#+end_src")
(el "#+begin_src emacs-lisp" n> r> n> "#+end_src")
(ll "#+begin_src gptel" n> r> n> "#+end_src")
(be "\\begin{" (p "align" env) "}" n r n "\\end{" (s env) "}")
))
((derived-mode-p 'tex-mode)
'(
(be "\\begin{" (p "align" env) "}" n r n "\\end{" (s env) "}")
))))
(setq tempel-template-sources '(my-templates))
)
cape
(use-package cape
:init
(setq cape-dabbrev-check-other-buffers 'some)
:config
(bind-key "C-c l" 'cape-tex)
(defun my-org-emacs-lisp-capf ()
(when (and (org-in-src-block-p 'inside)
(string= "emacs-lisp"
(org-element-property
:language (org-element-at-point))))
(elisp-completion-at-point)))
(defun my-org-capf ()
(setq-local completion-at-point-functions
'(tempel-expand ;tempel-complete
;jupyter-org-completion-at-point
my-org-emacs-lisp-capf
pcomplete-completions-at-point
cape-dabbrev
cape-file t)))
(add-hook 'org-mode-hook #'my-org-capf)
(setq completion-at-point-functions
'(tempel-expand ;tempel-complete
pcomplete-completions-at-point
cape-dabbrev
cape-file t))
;(add-hook 'prog-mode-hook 'tempel-setup-capf)
;(add-hook 'text-mode-hook 'tempel-setup-capf)
)
lsp/eglot
(use-package consult-eglot
:init
(my-leader-def "al" 'consult-eglot-symbols)
)
(use-package lsp-mode
:init
;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
(setq lsp-keymap-prefix nil)
(defun my-lsp-which-key-setup ()
(let ((lsp-keymap-prefix "SPC a l"))
(my-leader-def "al" lsp-command-map)
(lsp-enable-which-key-integration t)))
(setq lsp-enable-snippet nil)
:hook ((latex-mode . lsp)
;(lsp-mode . lsp-enable-which-key-integration)
(lsp-mode . my-lsp-which-key-setup))
:commands lsp)
(use-package lsp-ui :commands lsp-ui-mode)
(use-package consult-lsp :commands consult-lsp-diagnostics)
;; optionally if you want to use debugger
;;(use-package dap-mode)
;; (use-package dap-LANGUAGE) to load the dap adapter for your language
flyspell
(use-package flyspell
:ensure nil
:init
(setq ispell-program-name "aspell")
:config
(add-hook 'org-mode-hook #'flyspell-mode)
(add-hook 'TeX-mode-hook #'flyspell-mode)
(add-hook 'message-mode-hook #'flyspell-mode)
)
(use-package flyspell-correct
:config
(my-leader-def
"sc" 'flyspell-correct-wrapper
)
)
(use-package consult-flyspell
:config
(setq consult-flyspell-select-function nil
consult-flyspell-set-point-after-word t
consult-flyspell-always-check-buffer nil))
org
org
https://github.com/integral-dw/org-superstar-mode
’(org-cycle-hide-archived-subtrees org-cycle-show-empty-lines org-optimize-window-after-visibility-change)) https://www.mail-archive.com/emacs-orgmode@gnu.org/msg127537.html
(use-package org
:ensure (org :repo "~/data/code/org")
:after evil
:init
(setq org-agenda-files (list "~/data/todo.org")
org-agenda-span 10
org-edit-src-content-indentation 0
org-agenda-window-setup 'current-window
org-startup-with-inline-images t
org-src-tab-acts-natively t
org-adapt-indentation nil
org-src-window-setup 'current-window
org-export-with-smart-quotes t
org-log-done t
;;org-export-in-background t
org-highlight-latex-and-related '(native latex scripts entities)
org-ellipsis "⤵"
org-imenu-depth 4
org-cycle-hook '(org-cycle-hide-archived-subtrees org-cycle-show-empty-lines org-optimize-window-after-visibility-change)
org-cycle-include-plain-lists nil
org-latex-prefer-user-labels t
)
(add-hook 'org-mode-hook #'visual-line-mode)
;; TODO: fix this so org-scheduled today actually applied correctly in org-faces.el
;; (- 1 (/ (float diff) (max wdays 0)))
;; (upcoming? (and today? (> deadline today)))
(setq org-deadline-warning-days 0)
(setq org-agenda-deadline-faces '((1.01 . org-scheduled-previously)
(1.0 . org-scheduled)
(0.99 . org-sheduled-today)
(0.0 . org-scheduled)))
(setq org-confirm-babel-evaluate nil)
;; better to set :eval no-export than (setq org-export-use-babel nil)
(setq org-babel-default-header-args '((:session . "none")
(:results . "replace")
(:exports . "both")
(:cache . "no")
(:noweb . "no")
(:hlines . "no")
(:tangle . "no")
(:eval . "no-export")
(:comments . "link")))
(setq org-babel-default-header-args:emacs-lisp '((:lexical . "yes")))
(setq org-babel-default-header-args:latex '((:results . "file raw")
(:buffer . "no")
(:exports . "both")
(:noweb . "no-export")))
;(setq org-babel-default-header-args:jupyter-python '((:kernel . "python3")
; (:async . "yes")))
;(setq org-babel-default-header-args:jupyter-julia '((:kernel . "julia-1.12")
; (:async . "yes")))
(defun my-org-ctrl-c-ctrl-c-latex-preview-hook ()
(let ((element (car (org-element-context))))
(if (or (eq element 'latex-fragment) (eq element 'latex-environment))
(org-latex-preview))))
;(add-hook 'org-ctrl-c-ctrl-c-final-hook
(add-hook 'org-ctrl-c-ctrl-c-hook
'my-org-ctrl-c-ctrl-c-latex-preview-hook)
:config
(require 'org-indent) ; Prevents "Invalid face reference: org-indent"
(evil-define-key 'normal org-mode-map (kbd "RET") 'org-open-at-point)
(add-to-list 'org-src-lang-modes '("conf" . conf))
(setq org-preview-latex-default-process 'dvisvgm
org-preview-latex-image-directory "~/.cache/org-preview-latex/"
org-format-latex-options
'(:foreground default :background "Transparent" :scale 1.0
:html-scale 1.0
:matchers ("begin" "$1" "$" "$$" "\\(" "\\["))
)
(defun my-org-modified-hook ()
(setq-local time-stamp-start "^#\\+modified:[ ]+\\\\?"
time-stamp-end "$"
time-stamp-format "\[%Y-%m-%d %a\]")
(add-hook 'before-save-hook #'time-stamp nil 'local))
(add-hook 'org-mode-hook #'my-org-modified-hook)
(defun my-org-format-web-link ()
(interactive)
(let ((el (org-element-context)))
(when (and (eq (org-element-type el) 'link)
(let ((type (org-element-property :type el)))
(or (string= type "http") (string= type "https"))))
(let* ((url (org-element-property :raw-link el))
(title (with-current-buffer (url-retrieve-synchronously url)
(dom-text
(dom-by-tag
(libxml-parse-html-region (point-min) (point-max))
'title)))))
(delete-region (org-element-property :begin el)
(org-element-property :end el))
(insert (org-link-make-string url title))))))
(my-local-leader-def
:keymaps 'org-mode-map
"'" 'org-edit-special
"c" 'org-capture
"l" 'org-latex-export-to-pdf
"h" 'org-latex-export-to-html
;; Clock
;; These keybindings should match those under the "aoC" prefix (below)
"Cc" 'org-clock-cancel
"Cd" 'org-clock-display
"Ce" 'org-evaluate-time-range
"Cg" 'org-clock-goto
"Ci" 'org-clock-in
"CI" 'org-clock-in-last
"Cj" 'spacemacs/org-clock-jump-to-current-clock
"Co" 'org-clock-out
"CR" 'org-clock-report
"Cr" 'org-resolve-clocks
"dd" 'org-deadline
"ds" 'org-schedule
"dt" 'org-time-stamp
"dT" 'org-time-stamp-inactive
"e" 'org-export-dispatch
"fi" 'org-feed-goto-inbox
"fu" 'org-feed-update-all
"a" 'org-agenda
"p" 'org-priority
"Tc" 'org-toggle-checkbox
"Te" 'org-toggle-pretty-entities
"Ti" 'org-link-preview
"Tl" 'org-toggle-link-display
"Tt" 'org-show-todo-tree
"TT" 'org-todo
"TV" 'space-doc-mode
"Tx" 'org-latex-preview
"Ts" 'org-toggle-timestamp-type
;; More cycling options (timestamps, headlines, items, properties)
"L" 'org-shiftright
"H" 'org-shiftleft
"J" 'org-shiftdown
"K" 'org-shiftup
;; Change between TODO sets
"C-S-l" 'org-shiftcontrolright
"C-S-h" 'org-shiftcontrolleft
"C-S-j" 'org-shiftcontroldown
"C-S-k" 'org-shiftcontrolup
;; Subtree editing
"sa" 'org-toggle-archive-tag
"sA" 'org-archive-subtree
"sb" 'org-tree-to-indirect-buffer
"sh" 'org-promote-subtree
"sj" 'org-move-subtree-down
"sk" 'org-move-subtree-up
"sl" 'org-demote-subtree
"sn" 'org-narrow-to-subtree
"sN" 'widen
"sr" 'org-refile
"ss" 'org-sparse-tree
"sS" 'org-sort
;; tables
"ta" 'org-table-align
"tb" 'org-table-blank-field
"tc" 'org-table-convert
"tdc" 'org-table-delete-column
"tdr" 'org-table-kill-row
"te" 'org-table-eval-formula
"tE" 'org-table-export
"th" 'org-table-previous-field
"tH" 'org-table-move-column-left
"tic" 'org-table-insert-column
"tih" 'org-table-insert-hline
"tiH" 'org-table-hline-and-move
"tir" 'org-table-insert-row
"tI" 'org-table-import
"tj" 'org-table-next-row
"tJ" 'org-table-move-row-down
"tK" 'org-table-move-row-up
"tl" 'org-table-next-field
"tL" 'org-table-move-column-right
"tn" 'org-table-create
"tN" 'org-table-create-with-table.el
"tr" 'org-table-recalculate
"ts" 'org-table-sort-lines
"ttf" 'org-table-toggle-formula-debugger
"tto" 'org-table-toggle-coordinate-overlays
"tw" 'org-table-wrap-region
;; Source blocks / org-babel
"bp" 'org-babel-previous-src-block
"bn" 'org-babel-next-src-block
"be" 'org-babel-execute-maybe
"bo" 'org-babel-open-src-block-result
"bv" 'org-babel-expand-src-block
"bu" 'org-babel-goto-src-block-head
"bg" 'org-babel-goto-named-src-block
"br" 'org-babel-goto-named-result
"bb" 'org-babel-execute-buffer
"bs" 'org-babel-execute-subtree
"bd" 'org-babel-demarcate-block
"bt" 'org-babel-tangle
"bf" 'org-babel-tangle-file
"bc" 'org-babel-check-src-block
"bj" 'org-babel-insert-header-arg
"bl" 'org-babel-load-in-session
"bi" 'org-babel-lob-ingest
"bI" 'org-babel-view-src-block-info
"bz" 'org-babel-switch-to-session
"bZ" 'org-babel-switch-to-session-with-code
"ba" 'org-babel-sha1-hash
"bx" 'org-babel-do-key-sequence-in-edit-buffer
"vk" 'org-babel-remove-result-one-or-many
"vm" 'org-babel-mark-block
;; Multi-purpose keys
"," 'org-ctrl-c-ctrl-c
"*" 'org-ctrl-c-star
"-" 'org-ctrl-c-minus
"#" 'org-update-statistics-cookies
"RET" 'org-ctrl-c-ret
"M-RET" 'org-meta-return
;; attachments
"A" 'org-attach
;; insertion
"ib" 'org-insert-structure-template
"id" 'org-insert-drawer
"ie" 'org-set-effort
"if" 'org-footnote-new
"ih" 'org-insert-heading
"iH" 'org-insert-heading-after-current
"iK" 'spacemacs/insert-keybinding-org
"il" 'org-insert-link
"ir" 'org-roam-node-insert
"in" 'org-add-note
"ip" 'org-set-property
"is" 'org-insert-subheading
"it" 'org-set-tags-command
"ii" 'my-org-format-web-link
)
(my-leader-def
;; org-agenda
"ao#" 'org-agenda-list-stuck-projects
"ao/" 'org-occur-in-agenda-files
"aoa" 'org-agenda-list
"aoc" 'org-capture
"aoe" 'org-store-agenda-views
"aofi" 'org-feed-goto-inbox
"aofu" 'org-feed-update-all
"aol" 'org-store-link
"aom" 'org-tags-view
"aoo" 'org-agenda
"aos" 'org-search-view
"aot" 'org-todo-list
)
)
(elpaca-wait) ;; avoid elpaca's async loading of builtin org as dep of other pkgs
(use-package org-contrib)
(use-package ox
:ensure nil
:config
<<website.org:org-publish-project-blk()>>
)
org-roam
https://org-roam.discourse.group/t/org-roam-major-redesign/1198/181?page=9
(use-package org-roam
:init
(my-leader-def "ar" 'my-org-roam-node-find)
(my-leader-def "ac" 'org-roam-capture)
(my-local-leader-def
:keymaps 'org-mode-map
"Tr" 'org-roam-buffer-toggle)
(setq org-roam-directory "~/data/org")
;(setq org-roam-node-display-template
; (concat "${title:*} "
; (propertize "${tags:10}" 'face 'org-tag)))
(setq org-roam-capture-templates
'(("d" "default" plain "%?" :target
(file+head
"notebook/${slug}.org"
"#+title: ${title}\n#+date: %u\n#+modified: %u\n")
:unnarrowed t)))
(setq org-id-link-to-org-use-id 'create-if-interactive)
(setq org-roam-graph-link-hidden-types '("file" "https"))
:config
(org-roam-db-autosync-mode)
(require 'org-roam-export)
(defun my-org-roam-node-find ()
(interactive)
(org-roam-node-find
nil nil (lambda (node)
(not (file-in-directory-p
(org-roam-node-file node)
(expand-file-name "ref-notes" org-roam-directory))))))
;; https://github.com/org-roam/org-roam/wiki/User-contributed-Tricks
(cl-defmethod org-roam-node-directories ((node org-roam-node))
(if-let ((dirs (file-name-directory (file-relative-name (org-roam-node-file node) org-roam-directory))))
(format "(%s)" (car (split-string dirs "/")))
""))
(cl-defmethod org-roam-node-backlinkscount ((node org-roam-node))
(let* ((count (caar (org-roam-db-query
[:select (funcall count source)
:from links
:where (= dest $s1)
:and (= type "id")]
(org-roam-node-id node)))))
(format "[%d]" count)))
(setq org-roam-node-display-template "${backlinkscount:4} ${directories:12} ${title:110}")
(setq org-roam-node-annotation-function
(lambda (node) (marginalia--time (org-roam-node-file-mtime node))))
;; https://github.com/org-roam/org-roam/wiki/User-contributed-Tricks#overriding-the-slug-function
(cl-defmethod org-roam-node-slug ((node org-roam-node))
"Return the slug of NODE."
(let ((title (org-roam-node-title node))
(slug-trim-chars '(;; Combining Diacritical Marks https://www.unicode.org/charts/PDF/U0300.pdf
768 ; U+0300 COMBINING GRAVE ACCENT
769 ; U+0301 COMBINING ACUTE ACCENT
770 ; U+0302 COMBINING CIRCUMFLEX ACCENT
771 ; U+0303 COMBINING TILDE
772 ; U+0304 COMBINING MACRON
774 ; U+0306 COMBINING BREVE
775 ; U+0307 COMBINING DOT ABOVE
776 ; U+0308 COMBINING DIAERESIS
777 ; U+0309 COMBINING HOOK ABOVE
778 ; U+030A COMBINING RING ABOVE
779 ; U+030B COMBINING DOUBLE ACUTE ACCENT
780 ; U+030C COMBINING CARON
795 ; U+031B COMBINING HORN
803 ; U+0323 COMBINING DOT BELOW
804 ; U+0324 COMBINING DIAERESIS BELOW
805 ; U+0325 COMBINING RING BELOW
807 ; U+0327 COMBINING CEDILLA
813 ; U+032D COMBINING CIRCUMFLEX ACCENT BELOW
814 ; U+032E COMBINING BREVE BELOW
816 ; U+0330 COMBINING TILDE BELOW
817 ; U+0331 COMBINING MACRON BELOW
)))
(cl-flet* ((nonspacing-mark-p (char) (memq char slug-trim-chars))
(strip-nonspacing-marks (s) (string-glyph-compose
(apply #'string
(seq-remove #'nonspacing-mark-p
(string-glyph-decompose s)))))
(cl-replace (title pair) (replace-regexp-in-string (car pair) (cdr pair) title)))
(let* ((pairs `(("[^[:alnum:][:digit:]]" . "-") ;; convert anything not alphanumeric
("--*" . "-") ;; remove sequential underscores
("^-" . "") ;; remove starting underscore
("-$" . ""))) ;; remove ending underscore
(slug (-reduce-from #'cl-replace (strip-nonspacing-marks title) pairs)))
(downcase slug)))))
)
ox-latex
(use-package ox-latex
:ensure nil
:config
;(add-to-list 'org-latex-minted-langs '(jupyter-python "python"))
;;(setq org-latex-image-default-width "\\linewidth")
;;(setq org-latex-src-block-backend 'minted)
(setq org-latex-packages-alist '(("" "physics" t)))
;("" "tikz" t)
;("" "mathtools" t))
;("" "lmodern" nil)
;("" "svg" nil)
;("" "caption" nil)))
;;("" "minted" nil)
;;("margin=1in,headsep=0.4in,headheight=14pt" "geometry" nil)
;;("" "fancyhdr" nil)
;;("" "parskip" nil)))
(add-to-list 'org-latex-classes
'("moderncv"
"\\documentclass{moderncv}"
("\\section{%s}" . "\\section{%s}")
("\\subsection{%s}" . "\\subsection{%s}")))
(setq org-latex-pdf-process '("latexmk -f -pdf -%latex -interaction=nonstopmode -shell-escape -output-directory=%o %f"))
(setq org-latex-image-default-width nil)
)
ox-pluto
(use-package ox-pluto
:ensure (ox-pluto :host github :repo "tecosaur/ox-pluto")
)
ox-ipynb
(use-package ox-ipynb
:ensure (ox-ipynb :host github :repo "jkitchin/ox-ipynb")
)
evil-org
(use-package evil-org
:after org
:init
(setq evil-org-key-theme
'(navigation insert textobjects additional calendar todo))
:config
(add-hook 'org-mode-hook #'evil-org-mode)
(require 'evil-org-agenda)
(evil-org-agenda-set-keys)
)
htmlize
(use-package htmlize)
TODO bibtex and citar
Perhaps interesting idea to use org-bibtex https://github.com/emacs-citar/citar/issues/397
Which is now called ol-bibtex and yes I should really do this then consider just basically turning my current system into this in one (or a few) big org files so that I keep my comments light there and if it’s more significant just link to it in its own roam file!
Also now these files could just live inside notebook/ then.
I think my goal really should be to reduce everything with a collab-url and maybe someday simplify just to one notebook/ dir that I even put talks into since maybe someday they can just always come out within some reasonable time period (like paper publication?)
Alternative to biblio: https://github.com/teeann/scholar-import
I should move this to configuration for this website since it’s relevant to all the publishing infrastructure that’s there now.
(use-package bibtex
:ensure nil
:init
(setq bibtex-autokey-year-title-separator "-"
bibtex-autokey-titleword-separator "-"
bibtex-entry-format t
bibtex-align-at-equal-sign t
bibtex-autokey-edit-before-use nil)
:config
(setq bibtex-autokey-titleword-ignore
(remove "[^[:upper:]].*" bibtex-autokey-titleword-ignore))
(setq bibtex-BibTeX-entry-alist
(mapcar (lambda (e) (cons (downcase (car e)) (cdr e)))
bibtex-BibTeX-entry-alist))
(setq bibtex-biblatex-entry-alist
(mapcar (lambda (e) (cons (downcase (car e)) (cdr e)))
bibtex-BibTeX-entry-alist))
)
(use-package citeproc)
(use-package citar
;:bind (("C-c b" . citar-insert-citation)
; :map minibuffer-local-map
; ("M-b" . citar-insert-preset))
;(:map org-mode-map :package org ("C-c b" . #'org-cite-insert))
:after (org)
:custom
(org-cite-export-processors '((t csl)))
(org-cite-insert-processor 'citar)
(org-cite-follow-processor 'citar)
(org-cite-activate-processor 'citar)
(org-cite-global-bibliography '("~/data/org/references.bib"
"~/data/org/references-arxiv.bib"
"~/data/org/references-non-article.bib"))
(citar-bibliography org-cite-global-bibliography)
(citar-library-paths '("~/data/ref-pdfs/"))
:init
(my-leader-def "ab" 'citar-open)
:config
(defvar citar-indicator-files-icons
(citar-indicator-create
:symbol (all-the-icons-faicon
"file-o"
:face 'all-the-icons-green
:v-adjust -0.1)
:function #'citar-has-files
:padding " " ; need this because the default padding is too low for these icons
:tag "has:files"))
(defvar citar-indicator-links-icons
(citar-indicator-create
:symbol (all-the-icons-octicon
"link"
:face 'all-the-icons-orange
:v-adjust 0.01)
:function #'citar-has-links
:padding " "
:tag "has:links"))
(defvar citar-indicator-notes-icons
(citar-indicator-create
:symbol (all-the-icons-material
"speaker_notes"
:face 'all-the-icons-blue
:v-adjust -0.3)
:function #'citar-has-notes
:padding " "
:tag "has:notes"))
(setq citar-indicators
(list citar-indicator-files-icons
citar-indicator-links-icons
citar-indicator-notes-icons))
(add-to-list 'savehist-additional-variables 'citar-history)
;(setq citar-at-point-function 'embark-act)
)
(use-package citar-embark
:after citar embark
:no-require
:config (citar-embark-mode))
(use-package citar-org-roam
:after citar org-roam
;;:custom
;;(citar-org-roam-note-title-template "")
:config
(citar-org-roam-mode)
(defun citar--shorten-name (name)
(car (last (split-string name " "))))
(setq citar-display-transform-functions
`((sn . (citar--shorten-names))
(etal . (citar--shorten-names 1 "&"))))
(setq citar-org-roam-note-title-template "${author:%etal} ${year}")
(add-to-list 'org-roam-capture-templates
'("n" "ref note" plain "%?" :target
(file+head
"ref-notes/${citar-citekey}.org"
"#+title: ${note-title}\n#+subtitle: ${citar-title}\n#+date: %u\n#+modified: %u\n#+print_bibliography:\n[cite/n:@${citar-citekey}]\n")
:unnarrowed t))
(setq citar-org-roam-capture-template-key "n")
(defun my-citar-org-roam--create-capture-note (citekey entry)
(citar-org-roam--create-capture-note citekey entry)
(org-set-property "DOI" (citar-format--entry "${doi}" entry)))
(citar-register-notes-source
'my-citar-org-roam-source
(list :name "Org-Roam Notes"
:category 'org-roam-node
:items 'citar-org-roam--get-candidates
:hasitems 'citar-org-roam-has-notes
:open 'citar-org-roam-open-note
:create 'my-citar-org-roam--create-capture-note
:annotate 'citar-org-roam--annotate))
(setq citar-notes-source 'my-citar-org-roam-source)
)
(use-package doi2bib
:ensure (doi2bib :repo "~/data/code/emacs-doi2bib")
:after citar
:init
(setq doi2bib-bibtex-file (car citar-bibliography))
(setq doi2bib-disable-bibtex-prompt t)
;;(defun my-add-doi-to-org-roam ()
;; (interactive)
;; (citar-create-note
;; (cdr (assoc "=key=" (call-interactively 'doi2bib-add-bibtex-entry-from-doi)))))
;;(my-leader-def "ad" 'my-add-doi-to-org-roam)
;;(my-leader-def "ad" 'doi2bib-add-bibtex-entry-from-doi)
(defun my-citar-add-file-to-library (citekey)
(interactive (list (citar-select-ref)))
(let* ((filepath (expand-file-name citekey (car citar-library-paths)))
(url (read-string "Add file URL: ")))
(url-copy-file url (concat filepath ".pdf"))))
(defun my-add-doi ()
(interactive)
(let* ((bibtex (call-interactively 'doi2bib-add-bibtex-entry-from-doi))
(citekey (cdr (assoc "=key=" bibtex))))
(my-citar-add-file-to-library citekey)
(citar-open-notes (list citekey))))
(my-leader-def "ad" 'my-add-doi)
)
Cleaning up references
Here’s some code I’ve used to cleanup my bibfiles
(with-current-buffer "references.bib"
(bibtex-map-entries (lambda (key start end) (bibtex-clean-entry))))
(with-current-buffer "references.bib"
(setq my-no-doi nil)
(defun my-bibtex-doi (key start end)
(let* ((entry (bibtex-parse-entry))
(key (cdr (assoc "=key=" entry)))
(doi (cdr (assoc "doi" entry))))
;(message "%S" key)
(unless doi
(add-to-list 'my-no-doi key))))
(bibtex-map-entries 'my-bibtex-doi))
(with-current-buffer "references.bib"
(setq my-arxiv nil)
(defun my-bibtex-arxiv (key start end)
(let* ((entry (bibtex-parse-entry))
(key (cdr (assoc "=key=" entry)))
(doi (cdr (assoc "doi" entry)))
(publisher (cdr (assoc "publisher" entry))))
;(message "%S" publisher)
(when (string= publisher "{arXiv}")
(add-to-list 'my-arxiv key))))
(bibtex-map-entries 'my-bibtex-arxiv))
(with-current-buffer "references.bib"
(defun my-bibtex-cleaner (key start end)
(let* ((entry (bibtex-parse-entry))
(key (cdr (assoc "=key=" entry)))
(doi (cdr (assoc "doi" entry)))
(doi (substring doi 1 -1)))
(if (not doi) (error "no DOI! %S" key)
(delete-region start end)
(doi2bib-insert-bibtex-entry-from-doi doi))))
(bibtex-map-entries 'my-bibtex-cleaner))
(with-current-buffer "references_arxiv.bib"
(setq my-arxiv nil)
(defun my-bibtex-arxiv (key start end)
(let* ((entry (bibtex-parse-entry))
(key (cdr (assoc "=key=" entry)))
(doi (cdr (assoc "doi" entry)))
(publisher (cdr (assoc "publisher" entry))))
;(message "%S" publisher)
(when (string= publisher "{arXiv}")
(add-to-list 'my-arxiv key))))
(bibtex-map-entries 'my-bibtex-arxiv))
org-pdftools
(use-package org-pdftools
:init (setq org-pdftools-use-isearch-link t)
:hook (org-mode . org-pdftools-setup-link))
simple-httpd
(use-package simple-httpd)
geiser
;(use-package geiser
; :init
; (setq geiser-active-implementations '(guile)))
jupyter
(use-package jupyter
:after (org ob-gptel)
;:defer t
;:ensure (jupyter :host github :repo "akirakyle/emacs-jupyter")
:config
(org-babel-do-load-languages
'org-babel-load-languages
'(
(emacs-lisp . t)
(org . t)
(shell . t)
(latex . t)
(julia . t)
(python . t)
(gptel . t)
(jupyter . t) ; must be last
))
; prevents warning: ‘org-element-at-point’ cannot be used in non-Org buffer
;(remove-hook 'org-mode-hook 'jupyter-org-interaction-mode)
)
buffer-env
https://amodernist.com/texts/emacs-guix.html
(use-package buffer-env
:config
(eval-when-compile (require 'cl-lib))
(defun buffer-env-inherit (fn &rest args)
"Call FN with ARGS using the buffer-local process environment.
Intended as an advice around commands that start a process after
switching buffers."
(cl-letf (((default-value 'process-environment) process-environment)
((default-value 'exec-path) exec-path))
(apply fn args)))
(add-hook 'hack-local-variables-hook 'buffer-env-update)
(advice-add 'shell-command-to-string :around #'buffer-env-inherit)
(advice-add 'async-shell-command :around #'buffer-env-inherit)
(advice-add 'org-babel-eval :around #'buffer-env-inherit)
(advice-add 'jupyter-command :around #'buffer-env-inherit)
;; order matters for the following!
(advice-add 'vterm-mode :around #'buffer-env-inherit)
(advice-add 'vterm-mode :before #'buffer-env-update)
)
LaTeX
Someday solve the cause of this issue: https://emacs.stackexchange.com/questions/61957/mode-line-always-shows-compiling-after-compile-a-tex-file-with-typos
for now just (setq compilation-in-progress nil)
(use-package tex-mode
:ensure nil
:init
(setq TeX-view-program-selection '((output-pdf "pdf-tools")))
(setq TeX-view-program-list '(("pdf-tools" "TeX-pdf-tools-sync-view")))
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer)
(add-hook 'LaTeX-mode-hook #'visual-line-mode)
(add-hook 'LaTeX-mode-hook (lambda () (whitespace-mode -1)))
(setq TeX-command-extra-options "\"-shell-escape\"")
)
cdlatex
https://github.com/tecosaur/LaTeX-auto-activating-snippets https://karthinks.com/software/latex-input-for-impatient-scholars/ Probably prefer laas to this?
(use-package cdlatex
:init
(org-defkey org-cdlatex-mode-map ";" 'cdlatex-math-symbol)
(setq cdlatex-math-symbol-prefix ?\;)
(defun my-tempel-expand ()
(tempel-expand t))
; I've edited tempel--interactive not to error so this works
(add-hook 'cdlatex-tab-hook #'my-tempel-expand)
(add-hook 'LaTeX-mode-hook #'turn-on-cdlatex)
(add-hook 'org-mode-hook #'turn-on-org-cdlatex)
)
diff --git a/cdlatex.el b/cdlatex.el
index 4c85b87..0d657dd 100644
--- a/cdlatex.el
+++ b/cdlatex.el
@@ -443,7 +443,8 @@ indicating the label types for which it should be true."
(defcustom cdlatex-math-symbol-prefix ?`
"Prefix key for `cdlatex-math-symbol'.
-This may be a character, a string readable with `read-kbd-macro', or a
+This may be a character, a string readable with `read-kbd-macro'
+(doesn't work because of format specificer in cdlatex-math-symbol) , or a
Lisp vector."
:group 'cdlatex-math-support
:type '(choice
laas auto-activating-snippets
- laas.el isn’t much code at all, and I really don’t care for the laas-subscript-snippets, and I could probably better tailor laas-basic-snippets to my needs, so consider just copying it here
(use-package laas
:ensure (laas :repo "~/data/code/LaTeX-auto-activating-snippets")
:hook ((LaTeX-mode org-mode) . laas-mode)
:init
(setq laas-enable-auto-space nil)
)
pdf-tools
(use-package pdf-tools
:mode (("\\.pdf\\'" . pdf-view-mode))
:config
(evil-collection-define-key 'normal 'pdf-view-mode-map
"u" 'pdf-view-scroll-down-or-previous-page
"d" 'pdf-view-scroll-up-or-next-page
"J" 'pdf-view-next-page-command
"K" 'pdf-view-previous-page-command
"<right>" 'image-forward-hscroll
"<left>" 'image-backward-hscroll
(kbd "C-u") 'pdf-view-scroll-down-or-previous-page
(kbd "C-d") 'pdf-view-scroll-up-or-next-page
(kbd "C-s") 'pdf-occur
)
(setq pdf-view-use-scaling t)
(setq pdf-view-resize-factor 1.1)
(setq pdf-cache-image-limit 8)
(setq image-cache-eviction-delay 1)
; https://github.com/politza/pdf-tools/issues/467
; https://github.com/politza/pdf-tools/issues/177
(add-hook 'pdf-view-mode-hook #'pdf-links-minor-mode)
(add-hook 'pdf-view-mode-hook #'pdf-isearch-minor-mode)
(add-hook 'pdf-view-mode-hook #'pdf-history-minor-mode)
; Not quite the same issue I was having but relevant since it still fixes it
; https://github.com/politza/pdf-tools/issues/201
; This fixes the performance issue switching evil states
; I suspect this was due to changing the cursor and was especially bad on large monitors
;(evil-set-initial-state 'pdf-view-mode 'normal)
(add-hook 'pdf-view-mode-hook
(lambda ()
(set (make-local-variable 'evil-normal-state-cursor) (list nil))))
(setq pdf-annot-activate-created-annotations t)
(setq pdf-annot-default-annotation-properties
`((t (label . ,user-full-name))
(text (icon . "Comment")
(color . "#ff0000"))
(highlight (color . "yellow"))
(squiggly (color . "orange"))
(strike-out(color . "red"))
(underline (color . "blue"))))
)
epub
(use-package nov
:mode (("\\.epub\\'" . nov-mode))
)
markdown
(use-package markdown-mode)
lua
(use-package lua-mode
:config
)
julia
https://github.com/emacs-jupyter/jupyter/issues/426
(use-package julia-vterm)
(use-package ob-julia-vterm
:after (org)
:config
(defalias 'org-babel-execute:julia 'org-babel-execute:julia-vterm)
(defalias 'org-babel-variable-assignments:julia 'org-babel-variable-assignments:julia-vterm)
)
(use-package julia-snail
:ensure (julia-snail :repo "akirakyle/julia-snail")
:hook (julia-mode . julia-snail-mode)
:init
(setq julia-snail-extensions '(ob-julia))
:config
(org-babel-do-load-languages
'org-babel-load-languages
'(
(emacs-lisp . t)
(org . t)
(shell . t)
(latex . t)
(julia . t)
(python . t)
;(gptel . t)
))
)
(use-package julia-mode)
(use-package ob-julia
:ensure (ob-julia :repo "~/data/code/emacs-ob-julia")
:after (gptel)
:config
(org-babel-do-load-languages
'org-babel-load-languages
'(
(emacs-lisp . t)
(org . t)
(shell . t)
(latex . t)
(julia . t)
(python . t)
(gptel . t)
))
)
json
(use-package json-mode)
haskell+tidal
(use-package haskell-mode)
;(use-package tidal
; :config
; (add-hook 'tidal-mode-hook (lambda () (interactive-haskell-mode 0))))
swift
(use-package swift-mode)
ibuffer
(use-package ibuffer
:ensure nil
:config
(general-def
:states 'normal
:keymaps 'ibuffer-mode-map
"<tab>" 'ibuffer-visit-buffer-other-window-noselect)
)
dired
(setq delete-by-moving-to-trash t)
(setq trash-directory "~/.Trash")
(setq dired-listing-switches "-alhv")
(setq dired-guess-shell-alist-user
(list (list "\\.pdf" "open")))
(put 'dired-find-alternate-file 'disabled nil)
(general-def
:keymaps 'dired-mode-map
:states 'normal
"gj" 'dired-next-subdir
"gk" 'dired-prev-subdir
)
eshell
(elpaca-wait)
(add-hook 'eshell-mode-hook
#'(lambda ()
(define-key eshell-mode-map (kbd "<tab>") 'completion-at-point)))
(evil-define-key 'insert eshell-mode-map
(kbd "C-p") 'eshell-previous-input
(kbd "C-n") 'eshell-next-input)
comint
(setq shell-default-height 40)
(setq shell-default-position 'full)
(setq shell-default-full-span nil)
(setq shell-default-term-shell "/usr/local/bin/bash")
;;(setq shell-default-shell 'shell)
(push (cons "\\*shell\\*" display-buffer--same-window-action) display-buffer-alist)
;;(setq term-color-black ((t (:foreground "dim gray"))))
(evil-define-key 'normal comint-mode-map (kbd "C-p") 'comint-previous-input
(kbd "C-n") 'comint-next-input)
(evil-define-key 'insert comint-mode-map (kbd "C-p") 'comint-previous-input
(kbd "C-n") 'comint-next-input)
(evil-define-key 'normal comint-mode-map (kbd "C-l") 'comint-clear-buffer)
(evil-define-key 'insert comint-mode-map (kbd "C-l") 'comint-clear-buffer)
(evil-define-key 'normal term-raw-map (kbd "C-p") 'term-send-up
(kbd "C-n") 'term-send-down)
(evil-define-key 'insert term-raw-map (kbd "C-p") 'term-send-up
(kbd "C-n") 'term-send-down)
(setq term-char-mode-point-at-process-mark nil)
vterm
(use-package vterm)
magit
(use-package magit
:init
(setq magit-diff-refine-hunk 'all
magit-process-connection-type nil)
:config
(my-leader-def
"g" '(:ignore t :which-key "git")
"gs" 'magit-status
)
(define-key magit-mode-map (kbd "M-<tab>") nil)
(define-key magit-section-mode-map (kbd "C-<tab>") nil)
(define-key magit-section-mode-map (kbd "M-<tab>") nil)
(evil-collection-define-key 'normal 'magit-section-mode-map
[C-tab] nil
[M-tab] nil
)
)
TODO mu4e
Maybe build with this patch to speed things up: https://github.com/d12frosted/homebrew-emacs-plus/blob/master/community/patches/aggressive-read-buffering/emacs-31.patch
(use-package mu4e
:ensure nil
:load-path "/opt/homebrew/share/emacs/site-lisp/mu/mu4e/"
:init
(setq mu4e-completing-read-function 'completing-read)
(setq mu4e-change-filenames-when-moving t
mu4e-headers-time-format "%I:%M %p"
mu4e-headers-date-format "%y-%m-%d"
;;mu4e-split-view 'vertical
;;mu4e-split-view 'single-window
;;mu4e-headers-visible-columns 80
mu4e-get-mail-command "mbsync -a"
mu4e-headers-fields '((:maildir . 12)
(:flags . 4)
(:human-date . 9)
;;(:mailing-list . 10)
(:from . 24)
(:subject))
mu4e-headers-sort-field ':date
mu4e-headers-sort-direction 'ascending
mu4e-view-show-addresses t
mu4e-compose-format-flowed t
mu4e-compose-dont-reply-to-self t
mu4e-headers-results-limit 1000
message-send-mail-function 'message-smtpmail-send-it ; For message-mode (Gnus)
send-mail-function 'smtpmail-send-it ; For mail-mode (Rmail)
;;smtpmail-stream-type 'starttls
;;mu4e-view-prefer-html nil
)
;; customize the reply-quote-string
(setq message-citation-line-format "On %a, %b %d, %Y at %I:%M %p, %f wrote:\n")
;; choose to use the formatted string
(setq message-citation-line-function 'message-insert-formatted-citation-line)
:config
(general-define-key
:states 'normal
:keymaps 'mu4e-view-mode-map
"o" 'ace-link-mu4e
"O" 'mu4e-view-open-attachment)
;;(define-key mu4e-view-mode-map (kbd "f") 'mu4e-view-go-to-url)
(my-leader-def
"am" 'mu4e
)
<<email.org:mu4e-blk()>>
;;(defun my-mu4e-html2text (msg)
;; "My html2text function; shows short message inline, show
;;long messages in some external browser (see `browse-url-generic-program')."
;; (let ((html (or (mu4e-message-field msg :body-html) "")))
;; (if (> (length html) 20000)
;; (progn
;; (mu4e-action-view-in-browser msg)
;; "[Viewing message in external browser]")
;; (mu4e-shr2text msg))))
(setq mu4e-html2text-command 'mu4e-shr2text); my-mu4e-html2text
(defun my-mu4e-action-view-in-browser (msg)
"Show current MSG in browser if it includes an HTML-part.
The variables `browse-url-browser-function',
`browse-url-handlers', and `browse-url-default-handlers'
determine which browser function to use."
(with-temp-buffer
(insert-file-contents-literally
(mu4e-message-field msg :path) nil nil nil t)
(run-hooks 'gnus-article-decode-hook)
(when (re-search-forward "<!DOCTYPE[^>]*>" nil t)
(replace-match ""))
(when (re-search-forward "<html[^>]*>" nil t)
(replace-match "<html>"))
(let ((header (cl-loop for field in '("from" "to" "cc" "date" "subject")
when (message-fetch-field field)
concat (format "%s: %s\n" (capitalize field) it)))
(parts (mm-dissect-buffer t t)))
;; If singlepart, enforce a list.
(when (and (bufferp (car parts))
(stringp (car (mm-handle-type parts))))
(setq parts (list parts)))
;; Process the list
(unless (gnus-article-browse-html-parts parts header)
(mu4e-warn "Message does not contain a \"text/html\" part"))
(mm-destroy-parts parts))))
(setq mu4e-view-actions
'(("capture message" . mu4e-action-capture-message)
("view in browser" . my-mu4e-action-view-in-browser)
("show this thread" . mu4e-action-show-thread)))
(add-hook 'mu4e-view-mode-hook (lambda () (visual-line-mode 1)))
(custom-theme-set-faces
'user
'(variable-pitch ((t (:family "DejaVu Sans" :height 120)))))
(add-hook 'message-mode-hook (lambda () (whitespace-mode -1)))
(add-hook 'message-mode-hook (lambda () (auto-fill-mode -1)))
(add-hook 'message-mode-hook (lambda () (visual-line-mode 1)))
)
pass
Super inconvient bug preventing saving of files https://dev.gnupg.org/T6481
;(use-package pass)
xwidget-webkit
;(add-hook 'xwidget-webkit-mode-hook 'posframe-delete-all)
webkit
(use-package webkit
:straight (webkit :type git :host github :repo "akirakyle/emacs-webkit"
:branch "main"
:files (:defaults "*.js" "*.css" "*.so")
:pre-build ("nix-shell" "--command" "make clean && make"))
:init
(setq browse-url-browser-function 'webkit-browse-url)
;(setq browse-url-browser-function 'xwidget-webkit-browse-url)
(setq webkit-browse-url-force-new t)
(setq webkit-search-prefix "https://google.com/search?q=")
(setq webkit-ace-chars "aoeuidhtns")
;(setq webkit-dark-mode t)
:config
(my-leader-def
"," 'webkit
)
(defun webkit--display-progress (progress)
(setq webkit--progress-formatted
(if (equal progress 100.0)
""
(format "%s%.0f%% " (all-the-icons-faicon "spinner") progress)))
(force-mode-line-update))
(defun my-mu4e-action-view-in-webkit (msg)
(add-hook 'webkit-new-hook #'webkit-enable-javascript)
(webkit-browse-url (concat "file://"
(mu4e~write-body-to-html msg)) t)
(remove-hook 'webkit-new-hook #'webkit-enable-javascript))
;(add-to-list 'mu4e-view-actions
; '("open in browser" . mu4e-action-view-in-browser) t)
(defun my-webkit-secure ()
(interactive)
(let ((cookie-file "~/.emacs.d/webkit/cookies-centos"))
(webkit-set-proxy "socks://localhost:8000")
(delete-file (expand-file-name cookie-file))
(webkit-set-cookie-file cookie-file)))
(defun my-webkit-secure-start ()
(interactive)
(start-process "socks" "*socks*" "ssh" "centos" "ip a")
(start-process "socks" "*socks*" "ssh" "-CND" "8000" "centos"))
)
(use-package webkit-ace
:straight nil)
(use-package webkit-dark
:straight nil)
(use-package evil-collection-webkit
:straight nil
:config
(evil-collection-xwidget-setup)
)
gptel
- need to fix:
- insert deleting spaces in inline-diff,
- advice for websearch causing gpt5 not to work
(use-package gptel
:init
(setq gptel-default-mode 'org-mode)
:config
(gptel-make-anthropic "Claude" :stream t :key gptel-api-key)
(gptel-make-preset 'org-gpt5
:description "Preset for gpt5 in org mode"
:backend "ChatGPT"
:system "You are a large language model and a helpful assistant living in an Emacs org mode buffer. Respond concisely."
:model 'gpt-5
)
(gptel-make-preset 'org-opus
:description "Preset for opus 4.5 in org mode"
:backend "Claude"
:system "You are a large language model and a helpful assistant living in an Emacs org mode buffer. Respond concisely."
:model 'claude-opus-4-5-20251101
)
(gptel-make-preset 'org-sonnet
:description "Preset for Claude Sonnet 4.5 in org mode"
:backend "Claude"
:system "You are a large language model and a helpful assistant living in an Emacs org mode buffer. Respond concisely."
:model 'claude-sonnet-4-5-20250929
)
;(advice-add
; 'gptel--request-data
; :around
; (lambda (orig-fn &rest args)
; (when (cl-typep (car args) 'gptel-anthropic)
; (let ((result (apply orig-fn args)))
; (cons :tools (cons '[(:type "web_search_20250305"
; :name "web_search"
; :max_uses 5)] result))))))
)
(use-package ob-gptel
:ensure (ob-gptel :repo "~/data/code/ob-gptel")
:hook ((org-mode . ob-gptel-install-completions))
:defines ob-gptel-install-completions
:init
(setq gptel-use-context 'system)
:config
;(add-to-list 'org-babel-load-languages '(gptel . t)) ;; added in jupyter config...
;; Optional, for better completion-at-point
(defun ob-gptel-install-completions ()
(add-hook 'completion-at-point-functions
'ob-gptel-capf nil t)))
(use-package inline-diff
:ensure (inline-diff :repo "https://code.tecosaur.net/tec/inline-diff")
:config
(my-leader-def "dd" 'inline-diff-transient)
)
(use-package gptel-inline-diff
:ensure nil
:after (gptel inline-diff)
:config
(my-leader-def "dg" 'gptel-inline-diff-region)
)
Desktop
;;(use-package desktop
;; :init
;; (setq desktop-restore-frames nil)
;; )
GCMH
(use-package gcmh
:init
(setq gcmh-high-cons-threshold #x10000000)
:config
(gcmh-mode 1)
)
Server
;(server-start)