Literate and modular Doom Emacs configuration.
- About
- Tangle
- Input
- Completion
- UI
- Editor
- Emacs
- Term
- Checkers
- Tools
- Lang
- App
- Other packages
- Other configs
The conventions of this org file:
- First level heading respect Doom’s order
- Configured module goes to second level heading
-
- Prerequisite packages tangled into packages.toml (
Archonly) - Bootstrap scripts tangled to install.d/
- Comment a module with C-c ; at heading
- Prerequisite packages tangled into packages.toml (
- One line config goes into * Tangle
- Often a declare in init.el
(doom!
:input
<<input>>
:completion
<<completion>>
:ui
<<ui>>
hl-todo
indent-guides
(ligatures +extra)
nav-flash
ophints
(smooth-scroll +interpolate)
(vc-gutter +pretty)
(window-select +numbers)
workspaces
;zen
:editor
<<editor>>
(format +onsave)
;file-templates
;multiple-cursors
parinfer
word-wrap
:emacs
<<emacs>>
;electric
;ibuffer
undo
vc
:term
<<term>>
:checkers
<<checkers>>
(syntax +childframe)
:tools
<<tools>>
;biblio
debugger
;editorconfig
(eval +overlay)
tree-sitter
;upload
tree-sitter
:os
;tty
:lang
<<lang>>
;(cc +lsp)
emacs-lisp
json
:email
<<email>>
:app
calendar
<<app>>
:config
literate
(default +bindings +smartparens))The order of modules in above list make sense
Extra packages from MELPA
Default tangle to config.el
(setq user-full-name "fakeGenius")
<<predefines>>Default install all packages in packages.toml
enable_default=true[chinese]
packages=["base-devel",
"librime" # for +rime
](chinese<<chinese-flags()>>)Default simplified Chinese input
(after! liberime
(liberime-try-select-schema "luna_pinyin_simp")
(setq pyim-default-scheme 'rime-quanpin))[corfu]
packages=["words"](corfu +icons +dabbrev)(setq corfu-on-exact-match 'show)
(map! :after cape :i "C-c p" cape-prefix-map)
;; dabb_ only match dabbrev not Dabbrev!
(after! dabbrev
(setq dabbrev-case-fold-search nil))(vertico +icons +childframe)tumashu/vertico-posframe#16 Disable vertico-posframe when Emacs runs in terminal
(after! vertico-multiform
(add-to-list 'vertico-multiform-commands
'(consult-line
posframe
(vertico-posframe-fallback-mode . vertico-buffer-mode))))(defun my-posframe-poshandler-frame-top-center-n-lines (info)
(let* ((pos (posframe-poshandler-frame-top-center info))
(y (cdr pos)))
(cons (car pos)
(+ y (* 3 (frame-char-height)))))) ;; 3 lines offset(after! vertico-posframe
(setq vertico-posframe-poshandler #'my-posframe-poshandler-frame-top-center-n-lines)
(setq vertico-posframe-width 88))(package! ewal-doom-themes)(use-package! ewal-doom-themes)load wal theme from command line
emacs-client -e "(load-theme 'ewal-doom-themes t)"GitHub - donniebreve/rose-pine-doom-emacs: Soho vibes for DOOM Emacs
doomrestore last selected theme
(defun load-in-doom-dir (file-name &optional dir)
(let* ((dir (or dir doom-user-dir))
(full-name (expand-file-name file-name dir)))
(if (file-exists-p full-name)
(load full-name))))
(load-in-doom-dir "theme.el" doom-cache-dir)difficult to choose theme? random it
(defun +my/random-theme ()
(interactive)
(let* ((all-themes (custom-available-themes))
(next-theme (nth (random (length all-themes)) all-themes)))
(consult-theme next-theme)
(message (format "switch to theme: %s" next-theme))))
(map! :leader
(:prefix "t"
:desc "Random theme" "t" #'+my/random-theme))track current theme for later load
(defun +my/save-theme (prev new-theme &rest args)
(let
((theme-config-file (expand-file-name "theme.el" doom-cache-dir)))
(write-region
(format "(setq doom-theme '%s)\n" new-theme) nil theme-config-file)
(message "Switch to theme: %s" new-theme)))
(add-variable-watcher 'doom-theme #'+my/save-theme)bold italic underline stride
Set default font size, WSL currently not aware dpi settings in
~/.Xresources while float size makes it work on Linux.
- doomemacs/doomemacs#6131 DPI settings are not respected by “setq doom-font”
- Change my fonts - doom/docs/faq
(setq +my/font-size (* (if (featurep :system 'wsl) 1.5 1) 12.0))
(setq doom-font (font-spec :family "Maple6 NF" :size +my/font-size))(custom-set-faces
;; quoted text in info
'(fixed-pitch-serif ((t (:slant italic :foreground "tomato"))))
;; prefer italic comment font
'(font-lock-comment-face ((t (:slant italic)))))doom-dashboard- How to change your splash screen - Configuration - Doom Emacs Discourse
- elisp - Read from a file into a Emacs lisp list - Stack Overflow
(setq fancy-splash-image (expand-file-name "assets/bitmap_512x.png" doom-user-dir))splash image not loaded in the first frame of daemon mode
- Splash image not visible initially
- Splash image tinted only on emacs daemon launch - User Support - Doom Emacs D…
- doomemacs/doomemacs#6221 Theme differences in daemon vs standard GUI for the …
- doomemacs/doomemacs#7301 {cosmetic bug} fancy-splash-image not loaded at firs…
;; Refresh the Doom dashboard on the first frame in daemon mode.
(defun +my/load-doom-theme (frame)
(select-frame frame)
(load-theme doom-theme t))
(add-hook 'after-make-frame-functions #'+my/load-doom-theme 90)
;; Remove make frame hook to avoid delays when opening a new frame.
(add-hook! 'doom-first-buffer-hook
(remove-hook 'after-make-frame-functions #'+my/load-doom-theme))[modeline]
packages=["otf-comicshanns-nerd"]modelinecustom doom-modeline font, valid on startup and persist after cmd:doom/reload-theme
(defun +my/set-mode-line-font ()
(set-face-font 'mode-line (font-spec :family "ComicShannsMono Nerd Font" :size (+ +my/font-size 1.5)))
(set-face-font 'mode-line-inactive (font-spec :family "ComicShannsMono Nerd Font" :size (+ +my/font-size 1.5))))
(add-hook 'doom-load-theme-hook #'+my/set-mode-line-font 90)(popup +defaults)(setq split-width-threshold 120)Prefer stack at right for following info windows, since they are fill-columned
(set-popup-rules!
'(("^\\*\\([Hh]elp\\|Apropos\\)" ; help messages
:side right :size 80 :slot 2 :vslot -8 :select t)
("^\\*\\(?:Wo\\)?Man "
:side right :size 80 :vslot -6 :select t)
("^\\*info\\*$"
:side right :size 80 :slot 2 :vslot 2 :select t)))[unicode]
packages=[
"quivira", # org ellipsis ⤵, ℤ
"ttf-dejavu", # org heading ◉ ✸ ∈
"ttf-sarasa-gothic-sc", # ¬
"noto-fonts-emoji", # color emoji
"ttf-nerd-fonts-symbols-mono" # nerd font
]unicodeTo get unicode block name for a character, kbd:SPC h ’ on it to get it’s lexical code, and search in Plane (Unicode) - Wikipedia
Doom’s way of change unicode font, but it will be shadowed by fn:doom-init-fonts-h if var:doom-symbol-font is set.
(after! unicode-fonts
;; ℕ, ⤵, 𝔹
(dolist (unicode-block '("Letterlike Symbols" "Supplemental Arrows-B" "Mathematical Alphanumeric Symbols"))
(push "Quivira" (cadr (assoc unicode-block unicode-fonts-block-font-mapping))))
;; ⨂
(dolist (unicode-block '("Supplemental Mathematical Operators"))
(push "DejaVu Math TeX Gyre" (cadr (assoc unicode-block unicode-fonts-block-font-mapping))))
;; ∈ ∅
(dolist (unicode-block '("Mathematical Operators"))
(push "DejaVu Sans" (cadr (assoc unicode-block unicode-fonts-block-font-mapping))))
;; ¬
(dolist (unicode-block '("Halfwidth and Fullwidth Forms"))
(push "Sarasa Gothic SC" (cadr (assoc unicode-block unicode-fonts-block-font-mapping)))))Add to var:after-setting-font-hook not work well, font display diffs after cmd:doom/reload-theme
(defun +my/unicode-fonts ()
(dolist (unicode-block '("Letterlike Symbols" "Supplemental Arrows-B"))
(push "Quivira" (cadr (assoc unicode-block unicode-fonts-block-font-mapping)))))
(add-hook 'after-setting-font-hook #'+my/unicode-fonts 60)Add hook but with fn:set-fontset-font succeed
(defun +my/unicode-fonts ()
; Supplemental Arrows-B, include ⤵
(set-fontset-font t '(#x2900 . #x297f) "Quivira")
; Mathematical symbols, 𝔹
(set-fontset-font t '(#x1d400 . #x1d7ff) "Quivira")
; Mathematical operators, ⨂
(set-fontset-font t '(#x2208 . #x22ff) "DejaVu Math TeX Gyre")
(dolist (chars '("¬")) ; keywords =not= in code ligatures
(set-fontset-font t (string-to-char chars) "Sarasa Gothic SC")))
(add-hook 'after-setting-font-hook #'+my/unicode-fonts 60)see more in Emacs, fonts and fontsets
Rongcui Dong’s Site - 如何在 Doom Emacs 中设置中文
Check alignment between Chinese and English.
Emacs is the advanced, extensible, customizable, self-documenting editor.
# Emacs is the advanced, extensible, customizable, self-documenting editor.
Emacs 是一款可扩展可自定义且自带文档的高级 editor.These settings will not work in daemon mode if added instead to
doom-init-ui-hook, as they might be overridden by unicode-fonts-setup.
Additionally, consider changing the font for all fontset instead of just
(frame-parameter nil 'font). If the emoji font is not set here, you will need
to use doom/reload-font later to enable proper color emoji display.
- GitHub - hick/emacs-chinese: Emacs 相关中文问题以及解决方案
- fonts - How do I get colour emoji to display in Emacs - Emacs Stack Exchange
(defun +my/cjk-font ()
(dolist (charset '(kana han cjk-misc bopomofo))
(set-fontset-font t charset
(font-spec :family "Maple6 SC NF")))
;; why not set color emoji font at the same time
(set-fontset-font t 'emoji "Noto Color Emoji"))
(add-hook 'after-setting-font-hook #'+my/cjk-font)(after! nerd-icons
(setq nerd-icons-scale-factor 0.9))Transparency
(defun my/toggle-transparency ()
"Toggle between opaque and semi-transparent frame."
(interactive)
(let* ((opaque 100)
(transparent 97)
(cur (or (frame-parameter nil 'alpha-background)
(let ((a (frame-parameter nil 'alpha)))
(cond ((numberp a) a)
((consp a) (or (cdr a) (car a)))
(t opaque)))
opaque))
(new (if (= cur opaque) transparent opaque)))
;; Wayland (pgtk)
(set-frame-parameter nil 'alpha-background new)
;; X11/Xwayland
(set-frame-parameter nil 'alpha (cons new new))))
(map! :leader
(:prefix "t"
:desc "Toggle transparency" "T" #'my/toggle-transparency))Line numbers
(setq display-line-numbers-type nil)notify initial time
(defun notify-init-time ()
(require 'notifications)
(notifications-notify
:image-path (expand-file-name "assets/notify.jpg" doom-user-dir)
:title "Daemon"
:sound-name "bell"
:body (format "%s initialed in %0.3fs" server-name doom-init-time)))
;; NOTE Why this keep one workspace in `emacsclient -c'?
(add-hook! 'doom-init-ui-hook
(if (and (daemonp) (not (+my/is-utility-daemon)))
(notify-init-time)))(evil +everywhere)(after! evil
(setq evil-kill-on-visual-paste nil)
;; Disabling cursor movement when exiting insert mode
(setq evil-move-cursor-back nil)
;; keep previous layout, always!
(setq evil-auto-balance-windows nil))(after! evil-surround
;; I want surround (..), not ( .. )
(evil--add-to-alist
evil-surround-pairs-alist
?\( '("(" . ")")
?\[ '("[" . "]")
?\{ '("{" . "}")
?\) '("( " . " )")
?\] '("[ " . " ]")
?\} '("{ " . " }")))Shortcut for evil normal mode
(map! :n "g U" #'browse-url-xdg-open
:n "g u" #'evil-upcase
:n "g d" #'evil-downcase)snippets(setq +snippets-dir
(expand-file-name "~/Documents/Templates/snippets"))foldwork for org-ellipsis and fold in code mode
(setq +fold-ellipsis "⤵")
(after! org
(setq org-startup-folded 'fold
org-hide-drawer-startup nil))
;; org-hide-block-startup nil(dired +dirvish +icons)(after! dired
(setq delete-by-moving-to-trash t)
(setq dired-listing-switches
"-l --almost-all --sort=time --human-readable --time-style=long-iso --group-directories-first --no-group")
;; Dirvish respects all the keybindings in `dired-mode-map'
(map! :map dired-mode-map
:n "e" #'dired-create-empty-file
:n "." #'dired-omit-mode))Better trash/restore file with trash-put, trash-restore from trash-cli package.
How restore file from trash?
gio trash in dired
(defun system-move-file-to-trash (filename)
"Trash FILENAME using the 'gio trash' command.
FILENAME should be an absolute path or resolvable from the
current 'default-directory'."
(interactive "fTrash file: ")
(let ((expanded-file (expand-file-name filename)))
(unless (executable-find "gio")
(error "'gio' command not found in your PATH."))
(let ((exit-status (call-process "gio" nil nil nil "trash" expanded-file)))
(unless (zerop exit-status)
(error "Command 'gio trash %s' failed with exit status %d"
(shell-quote-argument expanded-file) exit-status)))))(after! dired-x
;; Make dired-omit-mode hide all "dotfiles"
(setq dired-omit-files
(concat dired-omit-files "\\|^\\..*$")))[dirvish]
packages=[
"fd",
"libvips",
"imagemagick",
"ffmpegthumbnailer", # may require pipewire-jack
"mediainfo",
# "tar", # include in =base=
"unzip"
](after! dirvish
(setq dirvish-quick-access-entries
'(("h" "~/" "Home")
("d" "~/Downloads/" "Downloads")
("c" "~/.config/" "Config")
("D" "~/Documents/" "Documents")
("l" "~/lib/" "Personal Library")
("L" "~/.local/lib/" "Library")
("m" "/mnt/" "Mounts")
("n" "~/.Nextcloud/" "Nextcloud")
("p" "~/Pictures/" "Pictures")
("t" "~/.local/share/Trash/files/" "TrashCan")))
(remove-hook 'dired-mode-hook #'+dired-update-mode-line-height-h))(after! dirvish
(setq dirvish-side-width 25)
(map!
:map dirvish-mode-map
:gn "S" #'dirvish-cd-into-vterm
;; remap previous =S= to =o=
:gn "o" #'dirvish-quicksort))(defun dirvish-open-binaries-externally (file fn)
"When FN is not `dired', open binary FILE externally."
(when-let* (((not (eq fn 'dired)))
((file-exists-p file))
((not (file-directory-p file)))
((member (downcase (or (file-name-extension file) ""))
dirvish-binary-exts)))
;; return t to terminate `dirvish--find-entry'.
(prog1 t (dired-do-open))))
(add-hook 'dirvish-find-entry-hook #'dirvish-open-binaries-externally)
(after! dirvish
;; remove pdf
(setq dirvish-binary-exts (remove "pdf" dirvish-binary-exts)))Replace /home/$user to ~
(defun +my/home-to-tide (file)
"Replace /home/$user in FILE to ~."
(let ((home (getenv "HOME"))
(file-name (concat file)))
(if (s-starts-with? home file-name)
(s-replace home "~" file-name)
file-name)))
(defun +my/dirvish-copy-file-path (&optional multi-line)
"Copy filepath of marked files.
If MULTI-LINE, make every path occupy a new line."
(interactive "P")
(let* ((files (mapcar #'file-local-name (dired-get-marked-files)))
(related-files (mapcar #'+my/home-to-tide files))
(names (mapconcat #'identity related-files (if multi-line "\n" " "))))
(dirvish--kill-and-echo (if multi-line (concat "\n" names) names))))
(after! dirvish
(advice-add 'dirvish-copy-file-path :override #'+my/dirvish-copy-file-path))Goto random line, use with fn:dirvish-fd
(defun goto-random-line ()
"Go to a random line in the current buffer."
(interactive)
(let* ((total-lines (count-lines (point-min) (point-max)))
(random-line (1+ (random total-lines))))
(goto-line random-line)))alexluigit/dirvish#353 When opening m…
(use-package dirvish
:commands dirvish
:preface
(defun +my/dirvish-pre-redisplay-h (window)
"Record root WINDOW and redisplay sessions in selected frame."
(when (eq (frame-selected-window) window)
(setq dirvish--selected-window (frame-selected-window))
(when-let* ((dv (dirvish-curr))) (setf (dv-root-window dv) window))
(dirvish--redisplay)))
(advice-add 'dirvish-pre-redisplay-h :override #'+my/dirvish-pre-redisplay-h))[vterm]
packages=[
"libvterm",
"cmake",
"inetutils" # =hostname= command
]vtermhave a function to disable close confirmation on terms. work on all terms but…
(defun set-no-process-query-on-exit ()
(let ((proc (get-buffer-process (current-buffer))))
(when (processp proc)
(set-process-query-on-exit-flag proc nil))))
(after! vterm
(if (+my/is-utility-daemon)
(add-hook 'vterm-mode-hook #'set-no-process-query-on-exit)))(defun +my/vterm-switch ()
"Switch to vterm buffer in `Term' workspace.
If `Term' workspace not exist, create it.
If no vterm buffer in `Term' workspace, create it."
(interactive)
(+workspace-switch "Term" t)
(let ((vterm-buffer
;; return first vterm buffer in `Term' workspace
(catch 'foo
(dolist (buffer (+workspace-buffer-list))
(let ((bn (buffer-name buffer)))
(when (and bn
;; https://stackoverflow.com/a/2238589
(with-current-buffer bn
(eq major-mode 'vterm-mode)))
(throw 'foo bn))))))
(display-buffer-alist))
(if vterm-buffer
(switch-to-buffer vterm-buffer)
;; create vterm buffer if not exist
(+vterm/here t))))
(map! :leader
:prefix "TAB"
:desc "Switch to vterm buffer" "v" #'+my/vterm-switch)(defun +my/vterm-cd-project-root ()
(interactive)
(vterm-send-string "cd $PROOT")
(vterm-send-return))
(after! vterm
(setq vterm-buffer-name-string "%s - vterm"
vterm-ignore-blink-cursor nil)
(map! :leader
(:prefix "o"
;; vterm to current file directory (not project root)
;; use `C-Return' to project root
:desc "Toggle vterm popup" "t" (cmd!! #'+vterm/toggle t)
:desc "Open vterm here" "T" (cmd!! #'+vterm/here t)))
;; TODO fixed-pitch in bpytop like
;; (add-hook 'vterm-mode-hook
;; (lambda ()
;; (set (make-local-variable 'buffer-face-mode-face) 'fixed-pitch
;; (buffer-face-mode t))))
(define-key vterm-mode-map (kbd "M-q") #'vterm-send-escape)
(define-key vterm-mode-map [ (control return) ] #'+my/vterm-cd-project-root)
(dolist (num (number-sequence 0 9))
(define-key vterm-mode-map (kbd (format "M-%d" num)) nil)))- akermu/emacs-libvterm#666 Integrate with desktop-save-mode
- Desktop-Save Mode
- GitHub - Bad-ptr/persp-mode.el: named perspectives(set of buffers/window conf…
- examples in doom config
No text properties saved.
(after! persp-mode
;; vterm
(persp-def-buffer-save/load
:mode 'vterm-mode :tag-symbol 'def-vterm-buffer
:save-vars '(default-directory)
:save-function (lambda (buf tag vars)
(list tag (buffer-name buf) vars
(string-trim-right (buffer-string))))
;; no face and other text properties saved
;; (string-trim-right (buffer-substring-no-properties (point-min) (point-max)))))
:load-function (lambda (savelist &rest _)
(cl-destructuring-bind (_ buf-name vars buf-string) savelist
(let ((default-directory (alist-get 'default-directory vars)))
(require 'vterm)
(with-current-buffer (get-buffer-create buf-name)
(insert buf-string)
(vterm-mode)))))))like ranger
(defun dirvish-cd-into-vterm ()
"Switch into recent vterm buffer, and cd into `default-directory` of dirvish buffer."
(interactive)
(let ((cur-dirvish-dir default-directory)
(vterm-buffer (catch 'foo
(dolist (buffer (+workspace-buffer-list))
(let ((bn (buffer-name buffer)))
(when (and bn
;; https://stackoverflow.com/a/2238589
(with-current-buffer bn
(eq major-mode 'vterm-mode)))
(throw 'foo bn)))))))
(dirvish-quit)
(if vterm-buffer
(let ((cur-vterm-dir (with-current-buffer vterm-buffer
default-directory)))
(switch-to-buffer vterm-buffer)
(unless (or (string= cur-vterm-dir cur-dirvish-dir)
(not (vterm--safe-send-p)))
; NOTE only fish shell support directory jump by dir-name
; add space to ignore command from history
(vterm-send-string (concat " " (file-relative-name cur-dirvish-dir cur-vterm-dir)))
(vterm-send-return)))
(with-temp-buffer (setq-local default-directory cur-dirvish-dir)
(+vterm/here t)))))!!! Just ensure no one type rm -rf before navigate in dirvish.
(defun vterm--safe-send-p ()
"Tell if current point safe to send string (no input after prompt)."
(let ((flag (save-excursion
(vterm-reset-cursor-point)
(evil-collection-vterm-append)
(vterm--at-prompt-p))))
(evil-normal-state)
flag))[spell]
packages=["aspell", "aspell-en"](spell +aspell
+everywhere)(after! ispell
(setq ispell-personal-dictionary
(expand-file-name ".pws" "~/.Nextcloud/ispell/")))(setf (alist-get 'org-mode +spell-excluded-faces-alist)
(append '(org-level-1 font-lock-function-name-face help-key-binding)
(alist-get 'org-mode +spell-excluded-faces-alist)))
(setf (alist-get 'latex-mode +spell-excluded-faces-alist)
(append '(font-lock-constant-face tex-math font-lock-comment-face)
(alist-get 'latex-mode +spell-excluded-faces-alist)))[lookup]
packages=["sqlite", "wordnet-common"](lookup
+docsets
+dictionary)(add-to-list '+lookup-provider-url-alist '("Brave" "https://search.brave.com/search?q=%s"))llmShould always catch up with newest commit.
(unpin! gptel)
(package! gptel :recipe (:nonrecursive t))(map! (:leader :prefix "o" :desc "gptel" "g" #'gptel))
(map! "C-c g q" #'gptel-quick
"C-c g m" #'gptel-menu
"C-c g t" #'gptel-org-set-topic)Who in their right mind would map enter in org-mode to gptel-send?
(evil-define-key 'normal gptel-mode-map (kbd "RET") nil)(after! gptel
(set-popup-rule!
(lambda (bname _action)
(and (null gptel-display-buffer-action)
(buffer-local-value 'gptel-mode (get-buffer bname))))
:select t :modeline nil :side 'right :width 0.4 :quit nil :ttl nil)
(setq gptel-default-mode #'org-mode
gptel-include-reasoning 'ignore
gptel-expert-commands t
gptel-track-media t
gptel-log-level 'info)
;; avoid headings as prompt
(setf (alist-get 'org-mode gptel-prompt-prefix-alist) "** "
(alist-get 'org-mode gptel-response-prefix-alist) "*Response:*\n")
(add-hook! 'gptel-pre-response-hook
(outline-previous-heading)
(recenter-top-bottom 1))
;; (add-hook 'gptel-post-stream-hook 'gptel-auto-scroll)
;; (add-hook 'gptel-post-response-functions 'gptel-end-of-response))
(load-in-doom-dir "private/gpt.el"))After cmd:gptel-org-set-topic, remove the top heading for collect conversation.
(defun +my/gptel-org-rm-upper-heading ()
"Remove upper level heading line."
(while (re-search-backward "\\(?:^\\* .+$\\)[[:space:]]+" nil t)
(delete-region (match-beginning 0) (match-end 0))))
(add-hook 'gptel-prompt-filter-hook #'+my/gptel-org-rm-upper-heading)(defun gptel-shift-response-heading-level (start end)
"Shift all Org headings in region so smallest is level 3 (***).
If the last line at END starts with '** ', exclude it from shifting."
(interactive "r")
(save-excursion
;; Adjust end if needed
(goto-char end)
(when (and (beginning-of-line) (looking-at "^\\*\\* "))
(setq end (max start (line-end-position -1))))
;; Find min level and shift
(let ((min-level (save-excursion
(goto-char start)
(cl-loop while (re-search-forward "^\\(\\*+\\) " end t)
minimize (length (match-string 1))))))
(when (and min-level (< min-level 3))
(let ((shift (- 3 min-level)))
(goto-char start)
(while (re-search-forward "^\\(\\*+\\) " end t)
(replace-match (make-string (+ (length (match-string 1)) shift) ?*) t t)))))))
(add-hook 'gptel-post-response-functions #'gptel-shift-response-heading-level)(package! ob-gptel
:recipe (:type git :host github :repo "jwiegley/ob-gptel"))(use-package ob-gptel
:hook ((org-mode . ob-gptel-install-completions))
:defines ob-gptel-install-completions
:config
(add-to-list 'org-babel-load-languages '(gptel . t))
;; Optional, for better completion-at-point
(defun ob-gptel-install-completions ()
(add-hook 'completion-at-point-functions
'ob-gptel-capf nil t)))(after! gptel-quick
(setq gptel-quick-model 'qwen3:14b)
(setq gptel-quick-backend (cdr (assoc-string "ollama" gptel--known-backends))))Tools collection · karthink/gptel Wik…
(package! gptel-got
:recipe (:host nil
:repo "https://codeberg.org/bajsicki/gptel-got"))(use-package gptel-got :after gptel)codel have merged into this llm-tool-collection fork. see ultronozm/codel.el#2 Errors with gpte…
(package! llm-tool-collection
:recipe (:type git :host github :repo "ultronozm/llm-tool-collection"))(use-package llm-tool-collection
:after gptel
:config
(mapcar (apply-partially #'apply #'gptel-make-tool)
(llm-tool-collection-get-all)))And more in GitHub - munen/emacs.d: My emacs conf…
(lsp +eglot)magit(use-package! tramp
:commands yadm-status
:init
(defun yadm-status ()
(interactive)
(magit-status "/yadm::"))
(map! :leader
(:prefix "g"
:desc "yadm-status" "a" #'yadm-status))
:config
;; see `man yadm'
(add-to-list 'tramp-methods
'("yadm"
(tramp-remote-shell "/bin/bash")
(tramp-remote-shell-args ("-c"))
(tramp-login-program "yadm")
(tramp-login-args (("enter"))))))If you use fish shell, you may change fish_prompt. see ~/.config/fish/config.fish
cmd:magit-stage (visually stage hunks) may not work in yadm, which cause emacs
to hang, use kbd:E s (cmd:magit-ediff-stage) instead.
magit/magit#719 Magit process hangs when trying to stage a hunk
pdfdefault pdf viewer in emacs
(after! pdf-tools
(setq-default pdf-view-display-size 'fit-width))
(after! latex (setq +latex-viewers '(pdf-tools evince okular)))
;; to have the buffer refresh after compilation
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer)
;; always use midnight view mode
(add-hook! 'pdf-view-mode-hook #'pdf-view-midnight-minor-mode)Selection in pdf-tools when evil mode enabled
Correct the file name path if it is a WSL path in Windows or an absolute path
inadvertently synced with a network disk. For pdf-sync-view, the source file
was correctly identified only after making this adjustment.
(defun +my/synced-true-path (filename)
"Rewrite the FILENAME assuming it from synced netdisk (or WSL).
When from netdisk, ensure they have same directory structure with
respect to your home."
(if (s-starts-with-p "//wsl.localhost" filename)
(setq filename (replace-regexp-in-string "^//wsl.localhost/\\w+" "" filename)))
(unless (s-starts-with-p (getenv "HOME") filename)
(setq filename (replace-regexp-in-string "^/home/\\w+" (getenv "HOME") filename)))
filename)
(defun +my/pdf-sync-backward-search (x y)
"Go to the source corresponding to image coordinates X, Y.
Try to find the exact position, if
`pdf-sync-backward-use-heuristic' is non-nil."
(cl-destructuring-bind (source finder)
(pdf-sync-backward-correlate x y)
(setq source (+my/synced-true-path source))
(pop-to-buffer (or (find-buffer-visiting source)
(find-file-noselect source))
pdf-sync-backward-display-action)
(push-mark)
(funcall finder)
(run-hooks 'pdf-sync-backward-hook)))
(advice-add 'pdf-sync-backward-search :override #'+my/pdf-sync-backward-search)Auto view .ps file
(add-hook 'ps-mode-hook 'doc-view-toggle-display)[latex]
enabled="not is_wsl"
packages=[
"miktex", "texlab",
# for `latexindent.pl` to work, which is called by `+format/buffer`
"perl-yaml-tiny", "perl-file-homedir"
](latex
+lsp
+fold
+cdlatex)Invoke latex.exe on windows.
(if (featurep :system 'wsl)
(setq LaTeX-command "latex.exe"
TeX-command "latex.exe"))(after! evil-tex
(setq evil-tex-include-newlines-in-envs nil
evil-tex-select-newlines-with-envs nil))cdlatex
(map! :map cdlatex-mode-map
:i "TAB" #'cdlatex-tab)retain .bbl as it required by APS journals.
synctex.gz kept to sync tex view.
(after! latex
(setq LaTeX-clean-intermediate-suffixes
(seq-difference LaTeX-clean-intermediate-suffixes
'("\\.bbl" "\\.synctex\\.gz"))))add XeTeX mode in TeX/LaTeX
(after! tex
(add-to-list 'TeX-command-list
'("XeLaTeX" "%`xelatex%(mode) %(extraopts) %S%(PDFout)%' %t" TeX-run-TeX nil t)))fn:latex-indent cmd:LaTeX-fill-buffer
cmd:+format/buffer default installed by miktex
(after! apheleia
(set-formatter! 'latexindent '("latexindent" "-l" "-r" "--logfile=/dev/null")
:modes '(LaTeX-mode)))formatting - LaTeXTidy in Emacs - TeX - LaTeX Stack Exchange
(after! cdlatex
(setq cdlatex-insert-auto-labels-in-env-templates nil))[lua]
enabled="not is_wsl"
packages=["lua-language-server"](lua +lsp)lsp support
(after! lua-mode
(setq lsp-clients-lua-language-server-bin "/usr/bin/lua-language-server")
(setq lsp-clients-lua-language-server-main-location "/usr/lib/lua-language-server/bin/main.lua")
(setq lsp-clients-lua-language-server-args '("-E" "--logpath" "/tmp/lua-language-server"))
;; (lsp-clients-lua-language-server-command '("lua-language-server" "-E"))
(setq lsp-clients-lua-language-server-command nil))ligatures
(after! lua-mode
(set-ligatures! 'lua-mode
:def "function"
:return "return"
:and "and"
:or "or"
:not "not"
:true "true"
:false "false"
:for "for"))[org]
packages=[
"xclip",
"maim",
"graphviz"
](org
+hugo
+dragndrop
+jupyter
+noter
+present
+pandoc
+pretty
+roam)Fix function link recognized as footnote.
(use-package org-modern
:init
(setq org-modern-footnote nil)
:config
(setq org-modern-star 'replace))Not the configuration of org-modern package, but they should be in same
category.
(defun +my/org-stronger-emphasis ()
"Make *bold* and /italic/ stand out more in org buffers."
(face-remap-add-relative 'bold
'(:foreground "orange red" :weight extra-bold))
(face-remap-add-relative 'italic
'(:foreground "deep sky blue" :slant italic)))
(add-hook 'org-mode-hook #'+my/org-stronger-emphasis)Very useful package for “automatic visibility toggling depending on cursor position”! Move on following latex to test.
α1 + β2
(after! org-appear
(setq org-appear-autolinks t
org-appear-autosubmarkers t
org-appear-inside-latex t))(setq org-directory "~/Documents/org/"
org-agenda-files '("agenda/todos.org" "agenda/projects.org")
org-agenda-start-with-log-mode t
org-agenda-prefix-format '((agenda . " %i %-12:c%?-12t% s")
(todo . " ")
(tags . " %i %-12:c")
(search . " %i %-12:c"))
org-log-done 'time
org-log-into-drawer t
org-startup-numerated t
org-image-actual-width 400
org-duration-format '((special . h:mm))
org-startup-with-inline-images t
org-refile-targets '(("archive.org" :maxlevel . 1)
("projects.org")))saving - How do I automatically save org-mode buffers? - Emacs Stack Exchange
(after! org
;;(org-clock-persist 'history)
(org-clock-persistence-insinuate)
(advice-add 'org-refile :after 'org-save-all-org-buffers)
(advice-add 'org-agenda-quit :before 'org-save-all-org-buffers))custom agenda view from
(setq org-agenda-custom-commands
'(("g" "Get Things Done (GTD)"
((agenda ""
((org-agenda-skip-function
'(org-agenda-skip-entry-if 'deadline))
(org-deadline-warning-days 0)
(org-agenda-start-day "-1d")
(org-agenda-span 4)))
(todo "STRT"
((org-agenda-skip-function
'(org-agenda-skip-entry-if 'deadline))
(org-agenda-prefix-format " %i %-12:c [%e] ")
(org-agenda-overriding-header "\nTasks\n")))
(tags-todo "inbox"
((org-agenda-prefix-format " %?-12t% s")
(org-agenda-overriding-header "\nInbox\n")))
(tags "CLOSED>=\"<today>\""
((org-agenda-overriding-header "\nCompleted today\n")))))))(after! org-capture
(setq org-capture-templates
`(("i" "Inbox" entry (file "agenda/todos.org")
"* TODO %?\n%U\n%i" :empty-lines 1 :prepend t)
("@" "Inbox [mu4e]" entry (file "agenda/todos.org")
"* TODO Reply to \"%a\"\n%U\n%i" :empty-lines 1 :prepend t)
("n" "Inbox [note]" entry (file "agenda/todos.org")
"* TODO [%a] %? %^G\n%U\n%i" :empty-lines 1 :prepend t))))- emacs - org-mode capture : dynamic file name - Stack Overflow
- emacs-from-scratch/init.el at c55d0f5e309f7ed8ffa3c00bc35c75937a5184e4 · davi…
Skip executing org source blocks within commented headings. To optimize, consider advising fn:org-babel-map-executables
(defun +my/org-babel-execute-buffer (&optional arg)
"Execute source code blocks in a buffer.
Call `org-babel-execute-src-block' on every source block in
the current buffer."
(interactive "P")
(org-babel-eval-wipe-error-buffer)
(org-save-outline-visibility t
(org-babel-map-executables nil
(unless (org-in-commented-heading-p)
(if (memq (org-element-type (org-element-context))
'(babel-call inline-babel-call))
(org-babel-lob-execute-maybe)
(org-babel-execute-src-block arg))))))
(advice-add 'org-babel-execute-buffer :override #'+my/org-babel-execute-buffer)Restore window-start after execute subtree. For hook based implement for all fn:narrow-to-region see:
(defun +my/org-babel-execute-subtree (&optional arg)
"Execute source code blocks in a subtree.
Call `org-babel-execute-src-block' on every source block in
the current subtree, passing over the prefix argument ARG."
(interactive "P")
(let ((original-start (window-start)))
(save-restriction
(save-excursion
(org-narrow-to-subtree)
(org-babel-execute-buffer arg)))
(set-window-start (selected-window) original-start)))
(advice-add 'org-babel-execute-subtree :override #'+my/org-babel-execute-subtree)[jupyter]
packages=["jupyter-notebook"](package! jupyter
:pin nil)
;; :recipe (:host github :repo "fakeGenuis/jupyter"))start session only when exactly execute it.
(after! jupyter
(setq jupyter-org-auto-connect nil))doomemacs/doomemacs#7354 Jupyter fails to function after upgrade
(with-eval-after-load 'ob-jupyter
(org-babel-jupyter-aliases-from-kernelspecs))(after! ob-jupyter
;; (push :text/html jupyter-org-mime-types)
(set-popup-rule!
"^\\*jupyter-traceback"
:side 'bottom :size 10 :slot -2 :select t))To view contents of .ipynb file, see
Possible issues
- emacs-jupyter/jupyter#584 `jupyter-or…
- doomemacs/doomemacs#3171 if: Need a v…
- emacs-jupyter/jupyter#575 Remote kern…
- [ ] emacs-jupyter/jupyter#558 Jupyter and…
- [ ]
(wrong-type-argument stringp nil)
(package! jupyter-ext
:recipe (:host github
:repo "fakeGenuis/jupyter-ext"))(use-package! jupyter-ext
:commands jupyter-org-transient
:init
(map! :map org-mode-map
:n ";" #'jupyter-org-transient)
:config
;; A tweaked completion at point function for corfu
(advice-add 'jupyter-completion-at-point :override #'jupyter-ext-completion-at-point))(after! ob-core
;; with multiple output and =:async yes=, text mass up after `example` block
(setq org-babel-min-lines-for-block-output 256))Intent mainly with file:::wolfram in jupyter, respect to doom’s org babel lazy load
(defvar +my/jupyter-langs '()
"A list of language that use jupyter override.")
(add-hook '+org-babel-load-functions
(defun +org-babel-load-jupyter-override-h (lang)
;; don't multi run `org-babel-jupyter-override-src-block'
(unless (boundp 'org-babel-header-args:jupyter)
(require 'ob-jupyter))
;; or even org-babel-header-args:%s will be reset
(when-let ((lang-name (symbol-name lang))
(_ (member lang-name +my/jupyter-langs)))
(set (intern (format "org-babel-default-header-args:jupyter-%s" lang-name))
(symbol-value (intern (format "org-babel-default-header-args:%s" lang-name))))
(org-babel-jupyter-override-src-block lang-name)))
-90)Session async have been include in org mode, see how to implement async using built in method.
- GitHub - jackkamm/ob-session-async: Asynchronous org-mode session evaluation
- emacs/etc/ORG-NEWS at a7cb220523d881449a2dba683e7358b3312fd482 · emacs-mirror…
This branch mainly fix apply: Wrong number of arguments of advice
cmd:ob-async-org-babel-execute-src-block
(package! ob-async
:pin nil
:recipe (:host github
:repo "stsquad/ob-async"
:branch "update-signature-skip-session"))(after! org-noter
(org-noter-set-doc-split-fraction '(0.75 . 0.25)))(setq org-roam-directory (expand-file-name "roam/" org-directory))
(after! org-roam
(setq org-roam-dailies-capture-templates
'(("d" "default" entry "* %?\n[%<%Y-%m-%d %H:%M>]\n"
:if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")))))(after! org-roam
(setq org-roam-graph-viewer "librewolf")
(setq org-roam-graph-link-hidden-types
'("file" "http" "https" "attachment" "zotero"
"fuzzy" "doom-module" "kbd" "fn")))kbd:SPC s b should work as expected
revert native org-cycle style, see doom-modules:lang/org/README.org
(after! evil-org
(remove-hook 'org-tab-first-hook #'+org-cycle-only-current-subtree-h))hlissner/doom-emacs#5436 org-src-window-setup not working correctly
(after! org-src
(setq org-src-window-setup 'reorganize-frame)
(set-popup-rule! "^\\*Org Src" :ignore t))format org-src
(map! :after org :map evil-org-mode-map
:n "g Q" #'+format:region)org-format
(use-package org-format
:defer 10
;; dawn lazy load
;; :commands (apheleia-format-org-buffer)
:init
(add-to-list 'load-path (expand-file-name "org-format" org-directory)))(cl-defun apheleia-format-org-buffer
(&key buffer scratch callback &allow-other-keys)
"Copy BUFFER to SCRATCH, then format scratch, then call CALLBACK."
;; ugly implement!
(with-current-buffer scratch
;; FIXME so many local value to copy
(let ((buffer-file-name (buffer-local-value 'buffer-file-name buffer))
(org-format-ignore-link (buffer-local-value 'org-format-ignore-link buffer))
(org-format-keep-empty-below-heading (buffer-local-value 'org-format-keep-empty-below-heading buffer)))
(org-format-buffer))
(funcall callback)))
(after! org
(set-formatter! 'orgfmt #'apheleia-format-org-buffer :modes '(org-mode)))(after! org
(setq org-archive-location ".bak/%s_archive::"))Avoid lengthy title
(after! org-cliplink
(setq org-cliplink-max-length 40))(package! org-modern-indent
:recipe (:type git :host github :repo "jdtsmith/org-modern-indent"))(use-package org-modern-indent
:config ; add late to hook
(add-hook 'org-mode-hook #'org-modern-indent-mode 90))[python]
packages=[
"pyright",
"tree-sitter-python"
](python +lsp +pyright +tree-sitter)doomemacs/doomemacs#3171 if: Need a v…
(with-eval-after-load 'ob-core
(setq org-babel-default-header-args:jupyter-python
'((:kernel . "python3"))))[sh]
packages=["shellcheck-bin", "bash-language-server", "shfmt"](sh +fish +lsp +powershell)fish shell ligatures
(after! fish-mode
(set-ligatures! 'fish-mode
:def "function"
:return "return"
:and "&&"
:or "||"
:not "not"
:true "true"
:false "false"
:for "for"))[yaml]
packages=["yaml-language-server"](yaml +lsp)[wolfram]
enabled="not is_wsl"
packages=["mathematica"](package! wolfram-mode
:recipe (:local-repo "~/lib/wolfram-mode/"))(use-package! wolfram-mode
:defer t)wolfram-format
(after! apheleia
(load "~/lib/wolframFormatter/wolfram-format.el"))Note that apheleia-formatter not work well with org-src block, turn
org-indent-mode off and then run kbd:g Q and then turn on org-indent-mode.
(after! (wolfram-mode ligature)
(set-ligatures! 'wolfram-mode
:and "&&"
:or "||"
:not "!"
:null "None"
:true "True"
:false "False"))WLPATH="~/.local/lib/lsp-wl/"
[[ -d "$WLPATH" ]] || git clone https://github.com/kenkangxgwe/lsp-wl.git "$WLPATH"PacletInstall["CodeParser"]
PacletInstall["CodeInspector"]
PacletInstall["ZeroMQLink"] (* 1.2.6+ *)
eglot is far faster than LSP!
(let ((wlserver (expand-file-name "~/.local/lib/lsp-wl/init.wls")))
(when (and (file-exists-p wlserver) (executable-find "wolframscript"))
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
`(wolfram-mode . ("wolframscript" "-f" ,wlserver
"--tcp-server" :autoport))))))Completion seems not work with 12.3.
(add-to-list '+my/jupyter-langs "Wolfram-Language")
(after! org-src
(add-to-list 'org-src-lang-modes '("Wolfram-Language" . wolfram))
(setq org-babel-default-header-args:Wolfram-Language
'((:kernel . "wolframforjupyter")
(:async . "yes")
(:results . "scalar"))))(add-to-list '+org-babel-native-async-langs 'Wolfram-Language)<> in Wolfram org-src break parentheses match.
(defun +my/remove-angle-brackets-from-syntax ()
(modify-syntax-entry ?< "." (syntax-table)) ;; Treat < as punctuation
(modify-syntax-entry ?> "." (syntax-table))) ;; Treat > as punctuation
(add-hook 'org-mode-hook #'+my/remove-angle-brackets-from-syntax)(after! (wolfram-mode yasnippet)
(let ((key-templates '()))
(dolist (key wolfram-structure-keywords)
(push `(,key ,(format "(* ::%s:: *)\n(*$1*)\n\n" key)) key-templates))
(yas-define-snippets 'wolfram-mode key-templates)))[markdown]
packages=[
"pandoc-bin"
]markdown["typst-mode"]
packages=[
"typst",
"tree-sitter-typst-git", # tree sitter grammar for typst, demand by typst-ts-mode
"tinymist" # language server
# "typst-lsp-bin" # alternative language server
](package! typst-ts-mode
:recipe (:host codeberg
:repo "meow_king/typst-ts-mode"
:files (:defaults "*.el")))(use-package! typst-ts-mode
:mode ("\\.typ\\'")
:custom
(typst-ts-watch-options "--open")
(typst-ts-mode-grammar-location (expand-file-name "tree-sitter/libtree-sitter-typst.so" user-emacs-directory))
(typst-ts-mode-enable-raw-blocks-highlight t)
:config
(setq typst-ts-mode-indent-offset 2)
(keymap-set typst-ts-mode-map "C-c C-c" #'typst-ts-tmenu))use pdf-tools to preview
(defun typst-pdf-tools-preview (&optional buffer)
"Use `pdf-tools' to preview compiled pdf."
(interactive)
(find-file-other-window (typst-ts-compile-get-result-pdf-filename buffer)))
(advice-add 'typst-ts-preview :override #'typst-pdf-tools-preview)language server
(with-eval-after-load 'eglot
(with-eval-after-load 'typst-ts-mode
(add-to-list 'eglot-server-programs
`((typst-ts-mode) .
,(eglot-alternatives `(,typst-ts-lsp-download-path
"tinymist"
"typst-lsp"))))))more configuration on Tinymist Docs
css
(prependq! auto-mode-alist '(("\\.rasi\\'" . css-mode)))defer is not work, same to immediate!
(after! parinfer-rust-mode
(setq parinfer-rust-check-before-enable 'defer))[mu4e]
packages=[
"isync",
"mu",
"pass",
"msmtp"
#"imagemagick"
]Example for initialing mu and mbsync
mkdir -p ~/.mail/$mailname
mu init --maildir=~/.mail --my-address=...@...
mu index
mbsync -c ~/.config/isync/$mbsyncrc -V -a(mu4e +gmail +org)(set-popup-rule! "^\\*mu4e-\\(main\\|headers\\)\\*" :ignore t)(setq mu4e-update-interval 300)
(after! mu4e
(setq mu4e-split-view 'vertical
mu4e-change-filenames-when-moving t
mu4e-attachment-dir "~/Downloads"
;; every new email composition gets its own frame!
mu4e-compose-in-new-frame t
mu4e-use-fancy-chars t))send email by msmtp, see ~/.config/msmtp/config
(after! mu4e
(setq sendmail-program (executable-find "msmtp")
send-mail-function #'smtpmail-send-it
message-sendmail-f-is-evil t
message-sendmail-extra-arguments '("--read-envelope-from")
message-send-mail-function #'message-send-mail-with-sendmail))private variables mu4e-get-mail-command and mu4e-contexts
(after! mu4e
(load-in-doom-dir "private/mu4e.el"))(rss +org)Read your RSS feeds in emacs with elfeed | Pragmatic Emacs
(after! elfeed
(add-hook! 'elfeed-search-mode-hook 'elfeed-update)
(setq elfeed-db-directory (concat (getenv "NCDIR") "elfeed/db/")
elfeed-enclosure-default-dir (concat (getenv "NCDIR") "elfeed/enclosures/")
;; elfeed-search-filter "@1-month-ago +unread"
rmh-elfeed-org-files (list (expand-file-name "elfeed.org" org-directory)))
(map! :leader
(:prefix "o"
:desc "elfeed" "e" #'elfeed)))
(after! elfeed-goodies
(setq elfeed-goodies/entry-pane-size 0.5))everywhere[everywhere]
packages=[
"xclip",
"xdotool",
"xorg-xprop",
"xorg-xwininfo"
](package! rainbow-mode)(package! gt)(use-package gt
:bind ("C-c t" . gt-translate)
:config
(setq gt-langs '(en zh))
(setq gt-default-translator
(gt-translator
:engines (list (gt-youdao-dict-engine) (gt-youdao-suggest-engine))
;; :engines (gt-google-engine)
:render (gt-buffer-render)))
(set-popup-rule!
"^\\*gt-result\\*"
:side 'left :size 60 :slot -2 :select t))(package! keycast)tarsius/keycast#7 Add support for moody and doom-modeline.
(use-package! keycast
:commands (keycast-mode)
:init
(map! :leader
(:prefix "t"
:desc "Toggle keycast" "k" #'keycast-mode))
:config
(define-minor-mode keycast-mode
"Show current command and its key binding in the mode line (fix for use with doom-mode-line)."
:global t
(if keycast-mode
(progn (add-hook 'pre-command-hook 'keycast--update t)
(setq keycast-mode-line-window-predicate
'keycast-active-frame-bottom-right-p))
(remove-hook 'pre-command-hook 'keycast--update)
(setq keycast-mode-line-window-predicate 'ignore)))
(add-to-list 'global-mode-string '("" keycast-mode-line)))(package! screenshot
:recipe (:host github :repo "yangsheng6810/screenshot"))(use-package! screenshot
:commands screenshot
:init
(map! (:leader :prefix "o"
:desc "sreenshot within emacs" "S" #'screenshot)))Allow attach the screenshot.
(after! screenshot
(screenshot--def-action
"attach"
(set-process-sentinel
;; NOTE feh not transparent well when shadow is included
(start-process "feh" nil "feh"
"--class=attached_window"
screenshot--tmp-file)
(lambda (process event) (delete-file screenshot--tmp-file))))
(transient-append-suffix 'screenshot-transient '(-1 1)
'("a" "Attach" screenshot-attach)))alias --save convert magick in fish shell to suppress the warning
WARNING: The convert command is deprecated in IMv7, use “magick” instead of “convert” or “magick convert”
Issues
- Region not correctly selected in
vtermbuffer - When select in visual line mode, newline not stripped
(package! zotxt)(defun org-zotxt-get-attachment-path ()
"Get attachment file path"
(interactive "P")
(let ((item-id (org-zotxt-extract-link-id-at-point)))
(deferred:$
(zotxt--request-deferred
(format "%s/items" zotxt-url-base)
:params `(("key" . ,item-id) ("format" . "paths"))
:parser 'json-read)
(deferred:nextc it
(lambda (response)
(let ((paths (cdr (assq 'paths (elt (request-response-data response) 0)))))
(org-zotxt-choose-path paths))))
(deferred:error it #'zotxt--deferred-handle-error)
(if zotxt--debug-sync (deferred:sync! it)
(deferred:nextc it
(lambda (path) path))))))
(defun +my/tilde-home-path (path)
"covert path starts with /home/$usr/ to '~'"
(interactive)
(let ((home (getenv "HOME")))
(if (string-prefix-p home path)
(string-join `("~" ,(string-remove-prefix home path)) "")
path)))
(defun org-zotxt-copy-attachment-path ()
"Open attachment of Zotero items linked at point.
Opens with `org-open-file', see for more information about ARG."
(interactive)
(deferred:$
(deferred:next
(lambda ()
(org-zotxt-get-attachment-path)))
(deferred:nextc it
(lambda (path)
(let ((new-path (+my/tilde-home-path path)))
(kill-new new-path)
(message "\"%s\" send to system clipboard!" new-path))))))A research workflow with Zotero and Org mode | mkbehr.com
(use-package zotxt
:hook (org-mode . org-zotxt-mode)
:config
(setq zotxt-default-bibliography-style "american-physical-society-et-al"))
(map! :map org-zotxt-mode-map
:desc "org-zotxt-insert-selected"
;; use <quote> in in case it pollute balanced brackets
"C-c <quote> <quote>" (cmd!! #'org-zotxt-insert-reference-link '(4))
:desc "org-zotxt-copy-attachment-path"
"C-c <quote> c" #'org-zotxt-copy-attachment-path)open attachment with point at arxiv link
(defun org-zotxt-open-arxiv-attachment ()
"open attachment from arxiv link, by zotxt"
(interactive)
(let* ((link (org-element-context))
(desc (buffer-substring-no-properties (org-element-property :contents-begin link)
(org-element-property :contents-end link))))
(org-zotxt-insert-reference-link)))converting comments into ascii arts
[figlet]
packages=["figlet"](package! figlet)(use-package! figlet
:defer t
:config
(setq figlet-options '("-W" "-f" "script")))(package! tldr)(package! inline-diff
:recipe (:host nil :repo "https://code.tecosaur.net/tec/inline-diff"))gptel‐rewrite addons · karthink/gptel Wiki · GitHub
;; Updated version available at https://github.com/karthink/gptel/wiki
(use-package gptel-rewrite
:after gptel
:bind (:map gptel-rewrite-actions-map
("C-c C-i" . gptel--rewrite-inline-diff))
:config
(defun gptel--rewrite-inline-diff (&optional ovs)
"Start an inline-diff session on OVS."
(interactive (list (gptel--rewrite-overlay-at)))
(unless (require 'inline-diff nil t)
(user-error "Inline diffs require the inline-diff package."))
(when-let* ((ov-buf (overlay-buffer (or (car-safe ovs) ovs)))
((buffer-live-p ov-buf)))
(with-current-buffer ov-buf
(cl-loop for ov in (ensure-list ovs)
for ov-beg = (overlay-start ov)
for ov-end = (overlay-end ov)
for response = (overlay-get ov 'gptel-rewrite)
do (delete-overlay ov)
(inline-diff-words
ov-beg ov-end response)))))
(when (boundp 'gptel--rewrite-dispatch-actions)
(add-to-list
'gptel--rewrite-dispatch-actions '(?i "inline-diff")
'append)))change key map
(after! inline-diff
(define-key inline-diff-overlay-map (kbd "M-a") #'inline-diff-apply)
(define-key inline-diff-overlay-map (kbd "M-r") #'inline-diff-reject)
;; optional: drop the old keys
(define-key inline-diff-overlay-map (kbd "M-RET") nil)
(define-key inline-diff-overlay-map (kbd "M-DEL") nil))doomemacs/doomemacs#8287 eldoc error: (invalid-function incf)
(package! eldoc :built-in t)
(package! track-changes :built-in t)(defun +my/is-utility-daemon ()
"If current session run from daemon called `utility`."
(and (daemonp) (boundp 'server-name) (string= server-name "utility")))(defun +my/reverse-words (beg end)
"Reverse the order of words in region."
(interactive "*r")
(apply
'insert
(reverse
(split-string
(delete-and-extract-region beg end) "\\b"))))- EmacsWiki: Unfill Paragraph
- GitHub - purcell/unfill: Functions providing the inverse of Emacs’ fill-parag…
;;; Stefan Monnier <foo at acm.org>. It is the opposite of fill-paragraph
(defun unfill-paragraph (&optional region)
"Takes a multi-line paragraph and makes it into a single line of text."
(interactive (progn (barf-if-buffer-read-only) '(t)))
(let ((fill-column (point-max))
;; This would override `fill-column' if it's an integer.
(emacs-lisp-docstring-fill-column t))
(fill-paragraph nil region)))
;; Handy key definition
(define-key global-map "\M-Q" 'unfill-paragraph)thank you, fish 4.0😄️
(after! tramp
(add-to-list 'process-environment "SHELL=/bin/bash"))- akermu/emacs-libvterm#689 Tramp-login-shells custom doesn’t match type
- akermu/emacs-libvterm#706 Allow using the default login shell for remote conn…
- ~/.config/emacs/modules/tools/magit/config.el
- magit/transient#338 Transient window doesn’t come back if display-action is s…
- karthink/gptel#583 Transient issue wh…
(after! (transient magit gptel)
(setq transient-display-buffer-action
'(display-buffer-below-selected
(dedicated . t)
(inhibit-same-window . t)))
(setq transient-show-during-minibuffer-read t))see also karthink/gptel#583 Transient issue when selecting a model in `gptel-menu`
transient-posframe/transient-posframe…
(defun my/transient-posframe-display-buffer (buffer alist)
"Display transient BUFFER in a child frame at bottom-center of the current frame.
Return the window showing BUFFER, or nil to let display-buffer try other actions."
(when (and (fboundp 'posframe-show) (posframe-workable-p))
(let* ((pf (posframe-show
buffer
:poshandler #'posframe-poshandler-frame-bottom-center
;; :timeout 7
:font "ComicShannsMono Nerd Font 10"
:min-width 40
:border-width 2
:border-color "gray50")))
(when (frame-live-p pf)
(frame-root-window pf)))))- [ ] still buggy, only work after manually execute this block. And sometimes
makes
minibufferheight increase unintended.
(after! (:or magit dirvish gptel)
(setq transient-display-buffer-action
'(my/transient-posframe-display-buffer
(dedicated . t)
(inhibit-same-window . t))))- [ ] try to fixed transient menu in
dirvish
(defun transient-posframe--delete ()
"Delete transient posframe."
(posframe-delete-frame transient--buffer-name)
(posframe--kill-buffer transient--buffer-name))
(advice-add 'transient--delete-window :override #'transient-posframe--delete)(after! projectile
(setq projectile-indexing-method 'alien
projectile-sort-order 'recently-active
projectile-file-exists-remote-cache-expire (* 10 60)
projectile-track-known-projects-automatically nil
;; projectile-require-project-root t
projectile-auto-discover t)
;; (projectile-file-exists-local-cache-expire (* 5 60)))
(add-to-list 'projectile-globally-ignored-directories
"*\\.run\\.tmp$")
(pushnew! projectile-globally-ignored-modes
"helpful-mode" "dired-mode")
(add-to-list 'projectile-globally-ignored-buffers "*doom*"))For non git project, better add following in project root .dir-locals.el
((nil . ((projectile-indexing-method . hybrid))))and add ignored files in .projectile.
(setq url-proxy-services
`(("no_proxy" . "^\\(localhost\\|10\\..*\\|192\\.168\\..*\\)")
("http" . ,(shell-command-to-string "echo -n $ALL_PROXY"))
("https" . ,(shell-command-to-string "echo -n $ALL_PROXY"))))Open link with host Librewolf browser
(if (featurep :system 'wsl)
(setq browse-url-firefox-program "librewolf.exe"))(defvar rx-arxiv-regexp
(rx (= 4 num) "." (= 5 num))
"Regular expression for arxiv id.")
(defun org-insert-arxiv-link ()
"Insert arxiv link with arxiv id as description."
(interactive)
(let* ((ring (current-kill 0))
(id (if (string-match rx-arxiv-regexp ring)
(match-string 0 ring)
(read-string "Input arxiv id:"))))
(insert " ")
(org-insert-link nil (concat "https://arxiv.org/abs/" id) id)))(add-to-list '+lookup-provider-url-alist '("Inspire" "https://inspirehep.net/literature?q=%s"))(map! :leader
:desc "Eval expression" ":" #'pp-eval-expression
:desc "M-x" ";" #'execute-extended-command
:desc "Org agenda" "=" #'org-agenda)