#+TITLE: Doom Emacs Configuration :DRAWER: #+startup: overview #+language: en #+email: dehaeze.thomas@gmail.com #+author: Dehaeze Thomas #+html_link_home: ./index.html #+html_link_up: ./index.html #+html_head: #+html_head: #+property: header-args:emacs-lisp :tangle ~/.config/doom/config.el :results none :padline no :END: * Introduction and Resources https://medium.com/urbint-engineering/emacs-doom-for-newbies-1f8038604e3b https://noelwelsh.com/posts/2019-01-10-doom-emacs.html https://dotdoom.netlify.com/config.html https://emacs.christianbaeuerlein.com/ https://github.com/nmartin84/.doom.d/blob/master/config.org https://tecosaur.github.io/emacs-config/config.html#intro Documentation: - https://github.com/hlissner/doom-emacs/blob/develop/docs/index.org When changing =init.el= or =package.el=, tangle the files and then run =doom sync=. After that, restart Emacs with =spc q r=. * Useful Bindings - =align-regexp=: equivalent of [[https://github.com/junegunn/vim-easy-align][vim-easy-align]]. Very useful to align tables and stuff ** General Bindings | =spc := | Execute command | | =spc <= | Switch to buffer | | =spc X= | org-capture | | =spc s s= | Search in buffer with swiper | | =spc s p= | Search in project | | =spc p p= | Switch project | | =spc p t= | TODOs in project | | =spc o f= | Create frame | | =spc o e= | Toggle Eshell | | =spc n l= | Store link | | =spc g g= | Magit status | | =spc f r= | Open recent file | | =spc b B= | Switch to buffer | | =spc b d= | Kill current buffer | | =spc b i= | ibuffer | | =spc tab .= | Switch to workspace | | =spc tab n= | New workspace | | =spc tab r= | Rename workspace | | =spc m A= | org-archive-subtree | | =spc m I= | org-toggle-inline-images | | =spc m d= | org-deadline | | =spc m e= | org-export-dispatch | | =spc m o= | org-set-property | | =spc m s= | org-schedule | | =spc m t= | org-todo | ** Org-Babel Bindings | =C-c C-v p= | org-babel-previous-src-block | | =C-c C-v n= | org-babel-next-src-block | | =C-c C-v e= | org-babel-execute-maybe | | =C-c C-v o= | org-babel-open-src-block-result | | =C-c C-v v= | org-babel-expand-src-block | | =C-c C-v u= | org-babel-goto-src-block-head | | =C-c C-v g= | org-babel-goto-named-src-block | | =C-c C-v r= | org-babel-goto-named-result | | =C-c C-v b= | org-babel-execute-buffer | | =C-c C-v s= | org-babel-execute-subtree | | =C-c C-v d= | org-babel-demarcate-block | | =C-c C-v t= | org-babel-tangle | | =C-c C-v f= | org-babel-tangle-file | | =C-c C-v c= | org-babel-check-src-block | | =C-c C-v j= | org-babel-insert-header-arg | | =C-c C-v l= | org-babel-load-in-session | | =C-c C-v i= | org-babel-lob-ingest | | =C-c C-v I= | org-babel-view-src-block-info | | =C-c C-v z= | org-babel-switch-to-session-with-code | | =C-c C-v a= | org-babel-sha1-hash | | =C-c C-v h= | org-babel-describe-bindings | | =C-c C-v x= | org-babel-do-key-sequence-in-edit-buffer | Timers: - =C-c C-x 0=: Start Timer - =C-c C-x .=: Insert timestamp - =C-c C-x ,=: Pause Timer - =C-c C-x _=: Stop Timer Tables: - =S-RET=: copy and increment the cell at point ** Evil bindings | ~gv~ | Selects the previous visual | | ~o~ in visual mode | go to the `Other` end of the selection | | ~g=~ and ~g-~ | Increase/decrement number | | ~t~ followed by any char | goes "till" next character (not included) | | ~f~ followed by any char | "find" next character (included) | | ~yt.~ | yank until next ~.~ | * Basic Configuration ** Personal Information #+begin_src emacs-lisp (setq user-full-name "Dehaeze Thomas" user-mail-address "dehaeze.thomas@gmail.com") #+end_src ** Doom Config Fonts #+begin_src emacs-lisp (setq doom-font (font-spec :family "Hack Nerd Font Mono" :size 12 :weight 'semi-light) doom-variable-pitch-font (font-spec :family "Hack Nerd Font Mono") doom-unicode-font (font-spec :family "Hack Nerd Font Mono" :size 12) doom-big-font (font-spec :family "Hack Nerd Font Mono" :size 19)) #+end_src Theme #+begin_src emacs-lisp ;; (setq doom-theme 'leuven) (setq doom-theme 'doom-gruvbox-light) #+end_src Line numbers #+begin_src emacs-lisp (setq display-line-numbers-type t) #+end_src Mode Line #+begin_src emacs-lisp (use-package doom-modeline :hook (after-init . doom-modeline-mode) :custom (doom-modeline-height 25) (doom-modeline-bar-width 1) (doom-modeline-icon t) (doom-modeline-major-mode-icon t) (doom-modeline-major-mode-color-icon t) (doom-modeline-buffer-file-name-style 'truncate-upto-project) (doom-modeline-buffer-state-icon t) (doom-modeline-buffer-modification-icon t) (doom-modeline-minor-modes nil) (doom-modeline-enable-word-count nil) (doom-modeline-buffer-encoding t) (doom-modeline-indent-info nil) (doom-modeline-checker-simple-format t) (doom-modeline-vcs-max-length 12) (doom-modeline-env-version t) (doom-modeline-irc-stylize 'identity) (doom-modeline-github-timer nil) (doom-modeline-gnus-timer nil)) #+end_src ** Evil #+begin_src emacs-lisp (after! evil (map! :m "-" #'dired-jump) (setq evil-respect-visual-line-mode nil) (modify-syntax-entry ?_ "w") ;; https://emacs.stackexchange.com/questions/9583/how-to-treat-underscore-as-part-of-the-word ) #+end_src Make horizontal movement cross lines #+begin_src emacs-lisp (setq-default evil-cross-lines t) #+end_src ** Which Key #+begin_src emacs-lisp (after! which-key (setq which-key-idle-delay 0.5 which-key-idle-secondary-delay 0.01 which-key-sort-order 'which-key-key-order-alpha)) #+end_src ** Visual Automatic line wrap. #+begin_src emacs-lisp (global-visual-line-mode nil) #+end_src Turn off auto-fill mode that add line breaks. #+begin_src emacs-lisp (auto-fill-mode -1) (remove-hook 'text-mode-hook #'turn-on-auto-fill) (after! org ;; turn off auto-fill for org-mode (add-hook 'org-mode-hook 'turn-off-auto-fill)) (after! auctex (add-hook 'latex-mode-hook 'turn-off-auto-fill)) #+end_src ** Change default alert backend #+begin_src emacs-lisp (setq alert-default-style 'libnotify) #+end_src ** Spell Check #+begin_src emacs-lisp (setq ispell-dictionary "en") (setq ispell-program-name "aspell") #+end_src Correct last work using =C-.=. #+begin_src emacs-lisp (defun tdh-correct-last-word () (interactive) (save-excursion (+spell/previous-error) (+spell/correct) ) ) (map! :map org-mode-map :i "C-." #'tdh-correct-last-word) #+end_src Go to previous/next spell mistake using =g[= and =g]=: #+begin_src emacs-lisp (map! :map evil-normal-state-map "g]" #'spell-fu-goto-next-error) (map! :map evil-normal-state-map "g[" #'spell-fu-goto-previous-error) #+end_src ** C-cedilla issue This tells GTK builds of Emacs to use native input method handling #+begin_src emacs-lisp (setq x-gtk-use-system-tooltips nil) (setq x-gtk-use-native-input t) #+end_src ** Lockfiles #+begin_src emacs-lisp (setq create-lockfiles nil) #+end_src ** Disable highlight of current line This helps to speed-up emacs. #+begin_src emacs-lisp (global-hl-line-mode -1) (after! org (add-hook 'org-mode-hook (lambda() (hl-line-mode -1) (global-hl-line-mode -1)) 't )) #+end_src ** Remap =jump-forward= key binding #+begin_src emacs-lisp (with-eval-after-load 'better-jumper (map! :desc "Jump Forward" "C-i" #'better-jumper-jump-forward)) #+end_src ** Magit #+begin_src emacs-lisp (setenv "GIT_ASKPASS" "git-gui--askpass") ;; (after! magit ;; (setq magit-diff-refine-hunk 'all) ;; (setq magit-repolist-columns '(("Name" 25 magit-repolist-column-ident nil) ;; ("Status" 7 magit-repolist-column-flag) ;; ("BU" 3 magit-repolist-column-unpushed-to-upstream ;; ((:right-align t) ;; (:help-echo "Local changes not in upstream"))) ;; ("Path" 99 magit-repolist-column-path nil))) ;; ) #+end_src ** Dired - =C-c C-e= Writable Dired mode, when changes are done =C-c C-c=. This works also with =C-x C-q= - =C-c C-r= use =rsync= to copy file in the background - =+= Create a directory - =R= Rename / move - =C= Copy - =d= Delete - =m= Mark - =U= unmark all marked - =t= invert the selection - =u= unmark / undelete - =x= actually delete files/directories marked for deletion - =!= Execute shell command on this file, or currently marked files - =%m= mark by pattern - =o= sort by time/name - =(= Hide details - =)= Show git infos #+begin_src emacs-lisp (after! magit (setq dired-listing-switches "-lAGh1v --group-directories-first") (add-hook 'dired-mode-hook (lambda () (dired-hide-details-mode) (dired-sort-toggle-or-edit))) ) #+end_src ** PDF-Tools Function that opens current pdf page as an SVG file with Inkscape. #+begin_src emacs-lisp (defun tdh-screenshot-page () "Open current page as an SVG file with Inkscape" (interactive) (if (string-match "_" (file-name-base buffer-file-name)) (setq filename (read-string "Enter file name:" (car (split-string (file-name-base buffer-file-name) "_")))) (setq filename (read-string "Enter file name:"))) (setq filepath (concat "/tmp/" filename ".svg")) (shell-command (concat "pdftk " buffer-file-name " cat " (number-to-string (pdf-view-current-page)) " output /tmp/pdf_page.pdf")) (shell-command (concat "pdf2svg /tmp/pdf_page.pdf " filepath)) (start-process "" nil "inkscape" filepath)) (after! pdf-tools (map! :map pdf-view-mode-map (:desc "Screenshot" :ni "C-c s" 'tdh-screenshot-page) )) #+end_src ** Flycheck Disable flycheck for now with orgmode buffers: #+begin_src emacs-lisp (defun disable-flycheck-mode () (interactive) (flycheck-mode -1)) (add-hook 'org-mode-hook 'disable-flycheck-mode) #+end_src ** Tramp #+begin_src emacs-lisp (after! tramp (add-to-list 'tramp-remote-process-environment "GIT_AUTHOR_EMAIL=thomas.dehaeze@esrf.fr") (add-to-list 'tramp-remote-process-environment "GIT_AUTHOR_NAME='Thomas Dehaeze'") (add-to-list 'tramp-remote-process-environment "GIT_COMMITTER_EMAIL=thomas.dehaeze@esrf.fr") (add-to-list 'tramp-remote-process-environment "GIT_COMMITTER_EMAIL='Thomas Dehaeze'") ) #+end_src ** Helm AG Increase the number of "columns" when search for text: #+begin_src emacs-lisp (setq counsel-rg-base-command "rg --max-columns 1000 --with-filename --no-heading --line-number --color never %s") #+end_src ** Others #+begin_src emacs-lisp (setq auto-save-default t) #+end_src * Org Mode - http://cachestocaches.com/2016/9/my-workflow-org-agenda/ - http://doc.norang.ca/org-mode.html#TodoKeywords - https://emacs.cafe/emacs/orgmode/gtd/2017/06/30/orgmode-gtd.html ** Org General Config #+begin_src emacs-lisp (setq org-directory "~/Cloud/org/") (after! org (setq org-directory "~/Cloud/org/") ;; Replace the content marker, “⋯”, with a nice unicode arrow. (setq org-ellipsis " ⤵") (setq org-default-notes-file "~/Cloud/org/refile.org") ;; Avoid accidentally editing folded regions, say by adding text after an Org “⋯”. (setq org-catch-invisible-edits 'show-and-error) ;; The following setting hides blank lines between headings which keeps folded view nice and compact. (setq org-cycle-separator-lines 0) ;; Indent according to the outline structure (setq org-startup-indented t) (setq org-startup-folded t) ;; Record the information of when the task was marked as DONE (setq org-log-done 'time) ;; begining of line on heading behavior (setq org-special-ctrl-a/e nil) ;; Automatic save all org buffers after 30s of innactivity (add-hook 'after-save-hook 'org-save-all-org-buffers) ) #+end_src TAB was changed to toggle only the visibility state of the current subtree, rather than cycle through it recursively. This can be reversed with: #+begin_src emacs-lisp (after! evil-org (remove-hook 'org-tab-first-hook #'+org-cycle-only-current-subtree-h)) #+end_src https://github.com/doomemacs/doomemacs/issues/6478#issuecomment-1406167570 #+begin_src emacs-lisp (after! evil (setq org-fold-core-style 'overlays) (evil-select-search-module 'evil-search-module 'evil-search) ) #+end_src ** Org Inline Images Display the real size of images and not the one set with =attr_latex: :width \linewidth= for instance. #+begin_src emacs-lisp (after! org (setq org-image-actual-width t)) #+end_src ** Org Links #+begin_src emacs-lisp (after! org (setq org-link-abbrev-alist '(("bib" . "~/Cloud/brain/biblio/references.bib::%s") ("notes" . "~/Cloud/brain/%s.org") ("papers" . "~/Cloud/pdfs/%s.pdf"))) ) #+end_src #+begin_src emacs-lisp (defun tdh/pdf-link (filename) (start-process "" nil "zathura" (concat "~/Cloud/pdfs/" filename ".pdf")) "") (after! org (org-link-set-parameters "pdf" :follow #'tdh/pdf-link) ) #+end_src ** Org Tagging #+begin_src emacs-lisp (after! org ;; Align Tags and flush right (setq org-tags-column -78) ;; Tags with fast selection keys (setq org-tag-alist (quote (("@home" . ?h) ("@work" . ?w) ("@christophe" . ?c) ("@veijo" . ?v)))) ) #+end_src ** Org Refile #+begin_src emacs-lisp (after! org (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6)))) ) #+end_src ** Org TODO #+begin_src emacs-lisp (after! org ;; Tags with fast selection keys (setq org-todo-keywords '( (sequence "TODO(t)" "MAIL(m)" "|" "DONE(d)") (sequence "READ(r)" "|" "DONE(d)") (sequence "WAIT(w@/!)" "DELE(e)" "|" "CANC(c@/!)") (sequence "QUES(q)" "|" "ANSW(a)") )) ;; Display of the keywords (setq org-todo-keyword-faces '(("TODO" . (:foreground "#cc241d" :weight bold)) ;; red ("MAIL" . (:foreground "#cc241d" :weight bold)) ;; red ("READ" . (:foreground "#cc241d" :weight bold)) ;; red ("ANSW" . (:foreground "#689d6a" :weight bold)) ;; aqua ("DONE" . (:foreground "#689d6a" :weight bold)) ;; aqua ("QUES" . (:foreground "#d65d0e" :weight bold)) ;; orange ("WAIT" . (:foreground "#d65d0e" :weight bold)) ;; orange ("CANC" . (:foreground "#a89984" :weight bold)) ;; grey ("DELE" . (:foreground "#98971a" :weight bold)))) ;; green ) #+end_src ** Org Archive https://gist.github.com/Fuco1/e86fb5e0a5bb71ceafccedb5ca22fcfb Archive subtrees under the same hierarchy as original in the archive files #+begin_src emacs-lisp (after! org (defadvice org-archive-subtree (around fix-hierarchy activate) (let* ((fix-archive-p (and (not current-prefix-arg) (not (use-region-p)))) (location (org-archive--compute-location org-archive-location)) (afile (car location)) (offset (if (= 0 (length (cdr location))) 1 (1+ (string-match "[^*]" (cdr location))))) (buffer (or (find-buffer-visiting afile) (find-file-noselect afile)))) ad-do-it (when fix-archive-p (with-current-buffer buffer (goto-char (point-max)) (while (> (org-current-level) offset) (org-up-heading-safe)) (let* ((olpath (org-entry-get (point) "ARCHIVE_OLPATH")) (path (and olpath (split-string olpath "/"))) (level offset) tree-text) (when olpath (org-mark-subtree) (setq tree-text (buffer-substring (region-beginning) (region-end))) (let (this-command) (org-cut-subtree)) (goto-char (point-min)) (save-restriction (widen) (-each path (lambda (heading) (if (re-search-forward (rx-to-string `(: bol (repeat ,level "*") (1+ " ") ,heading)) nil t) (org-narrow-to-subtree) (goto-char (point-max)) (unless (looking-at "^") (insert "\n")) (insert (make-string level ?*) " " heading "\n")) (cl-incf level))) (widen) (org-end-of-subtree t t) (org-paste-subtree level tree-text)))))))) ) #+end_src ** Org Agenda General configuration #+begin_src emacs-lisp (after! org ;; File to save todo items (setq org-agenda-files (list "~/Cloud/org/")) ;; Include archived files (setq org-agenda-archives-mode nil) ;; Set priority range from A to C with default A (setq org-highest-priority ?A) (setq org-lowest-priority ?C) (setq org-default-priority ?C) ;; Set colours for priorities (setq org-priority-faces '((?A . (:foreground "#FB4934")) (?B . (:foreground "#FABD2F")) (?C . (:foreground "#98971A")))) ;; Open agenda in current window (setq org-agenda-window-setup 'current-window) ;; Set default first day of agenda (setq org-agenda-start-day nil) (setq org-agenda-start-on-weekday 1) (setq org-agenda-span 7) (setq org-agenda-prefix-format '((agenda . " %?-12t% s") (todo . "") ;; Don't show the filename for reading agenda (tags . " %-12:c") (search . " %-12:c")) ) ) #+end_src Org Agenda Custom Views #+begin_src emacs-lisp (after! org-agenda (defun tdh-org-agenda-skip-scheduled () (org-agenda-skip-entry-if 'scheduled 'deadline 'regexp "\n]+>")) (defun tdh-org-agenda-phd-files () (seq-mapcat (lambda (subdir) (directory-files subdir t "\\.org$" t)) (seq-filter #'file-directory-p (directory-files "~/Cloud/work-projects/ID31-NASS/phd-thesis-chapters" t "^[^.]" t)))) (setq org-agenda-custom-commands '(("T" "test" ((org-ql-block '(planning) ((org-ql-block-header "To refill"))) )) ("p" "PhD Thesis" ((agenda "" ((org-agenda-span 3) (org-deadline-warning-days 0) (org-agenda-block-separator nil) (org-agenda-format-date "%A %-e %B %Y") (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-overriding-header "Next:"))) (org-ql-block '(and (not (tags "@home")) (not (tags "@biblio")) (todo "TODO") (priority "A")) ((org-ql-block-header "Important:"))) (org-ql-block '(and (not (tags "@home")) (todo "DELE")) ((org-ql-block-header "Delegated:"))) (org-ql-block '(and (not (tags "@home")) (todo "WAIT")) ((org-ql-block-header "On hold:"))) ) ((org-agenda-files (tdh-org-agenda-phd-files)))) ("w" "Work" ((agenda "" ((org-agenda-span 3) (org-deadline-warning-days 0) (org-agenda-block-separator nil) (org-agenda-format-date "%A %-e %B %Y") (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-overriding-header "Next:"))) (org-ql-block '(and (not (tags "@home")) (not (tags "@biblio")) (todo "TODO") (priority "A")) ((org-ql-block-header "Important:"))) (org-ql-block '(and (not (tags "@home")) (todo "DELE")) ((org-ql-block-header "Delegated:"))) (org-ql-block '(and (not (tags "@home")) (todo "WAIT")) ((org-ql-block-header "On hold:"))) (org-ql-block '(and (tags "inbox")) ((org-ql-block-header "To refill:"))) )) ("h" "Home" ((org-ql-block '(and (tags "@home") (todo "TODO") (priority "A")) ((org-ql-block-header "Things to do"))) (org-ql-block '(and (tags "@home") (todo "TODO") (priority "B")) ((org-ql-block-header "Things to do"))) (org-ql-block '(and (tags "@home") (todo "TODO") (priority "C")) ((org-ql-block-header "Things to do"))))) ("q" "Questions to ask" ((org-ql-block '(and (todo "QUES") (tags "@christophe")) ((org-ql-block-header "Questions to Christophe"))) (org-ql-block '(and (todo "QUES") (tags "@veijo")) ((org-ql-block-header "Questions to Veijo"))) (org-ql-block '(and (todo "QUES") (not (tags "@veijo" "@christophe"))) ((org-ql-block-header "Other Questions"))))) ("R" "Already read Articles and Books" ((org-ql-block '(and (todo "DONE") (level 1) (tags "article" "inproceedings" "techreport" "inbook")) ((org-ql-block-header "Articles"))) (org-ql-block '(and (todo "DONE") (level 1) (tags "book")) ((org-ql-block-header "Books"))) (org-ql-block '(and (todo "DONE") (level 1) (tags "phdthesis")) ((org-ql-block-header "Phd Thesis"))) (org-ql-block '(and (todo "DONE") (level 1) (not (tags "article" "inproceedings" "techreport" "inbook" "book" "phdthesis"))) ((org-ql-block-header "Other Things")))) ((org-agenda-files '("~/Cloud/brain/")))) ("r" "Articles and Books to read" ((org-ql-block '(and (todo "READ") (level 1) (tags "article" "inproceedings" "techreport" "inbook")) ((org-ql-block-header "Article to Read"))) (org-ql-block '(and (todo "READ") (level 1) (tags "book")) ((org-ql-block-header "Books to Read"))) (org-ql-block '(and (todo "READ") (level 1) (tags "phdthesis")) ((org-ql-block-header "Phd Thesis to Read"))) (org-ql-block '(and (todo "READ") (level 1) (not (tags "article" "inproceedings" "techreport" "inbook" "book" "phdthesis"))) ((org-ql-block-header "Other Things to Read")))) ((org-agenda-files '("~/Cloud/brain/"))))) ) ) #+end_src ** Org Structure Template #+begin_src emacs-lisp (after! org (require 'org-tempo) (setq org-structure-template-alist '(("c" . "center") ("C" . "comment") ("mm" . "src matlab") ("mf" . "src matlab :exports none") ("mv" . "src matlab :results value replace :exports results :tangle no") ("l" . "src emacs-lisp") ("q" . "quote") ("s" . "src") ("ba" . "answer") ("bd" . "definition") ("be" . "exampl") ("bx" . "exercice") ("bq" . "question") ("bs" . "summary") ("bS" . "seealso") ("bh" . "hint") ("bn" . "note") ("bi" . "important") ("bc" . "caution") ("bw" . "warning") )) ) #+end_src ** Org Capture Documentation: - Template elements: https://orgmode.org/manual/Template-elements.html#Template-elements - Template expansion: https://orgmode.org/manual/Template-expansion.html#Template-expansion - Capture protocol: https://orgmode.org/manual/capture-protocol.html #+begin_src emacs-lisp (after! org (setq org-capture-templates (quote (("t" ; key "Todo" ; name entry ; type (file+headline "~/Cloud/org/work-tasks.org" "Inbox") ; target "** TODO %?\n%U\n" ; template ) ("M" ; key "Meeting" ; name entry ; type (file+headline "~/Cloud/org/work-tasks.org" "Meetings") ; target "** %?\n%(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n" ; template ) ("m" ; key "Mail" ; name entry ; type (file+headline "~/Cloud/org/work-tasks.org" "Mails") ; target "** TODO [#A] %?\nSCHEDULED: %(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n%a\n" ; template ) ("r" ; key "Reference" ; name entry ; type (file+headline "~/Cloud/org/inbox-ereader.org" "Things to Read") ; target "** TODO [#B] %?\n" ; template ) ("pm" "Org-Protocol Mail" entry (file+headline "~/Cloud/org/work-tasks.org" "Mails") "* TODO [#C] %:description [[message:%:link][link]]\nSCHEDULED: %(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n%i\n" :immediate-finish t ) ("ps" "Org-Protocol Sent Mail" entry (file+headline "~/Cloud/org/work-tasks.org" "Mails") "* WAIT %:description [[message:%:link][link]]\n%(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n- to: %i\n\n\n\n" :immediate-finish t ) ("pu" "Org-Protocol Url" entry (file+headline "~/Cloud/org/work-tasks.org" "Inbox") "* [[%:link][%:description]]\nCaptured On: %U\n\n" :immediate-finish t ) ("pt" "Org-Protocol text" entry (file+headline "~/Cloud/org/work-tasks.org" "Inbox") "* %:description\nSource: %:link\nCaptured On: %U\n\n#+begin_quote\n%i\n#+end_quote\n\n" :immediate-finish t ) ))) ) #+end_src ** Org Export Basic configuration: #+begin_src emacs-lisp (after! org ;; How many levels of headline to export (setq org-export-headline-levels 4) ;; Authorize BIND to set local variables (setq org-export-allow-bind-keywords t) ;; Use doc instead of odt (setq org-odt-preferred-output-format "doc") ;; Search collapse items (setq search-invisible t) ) #+end_src Some defaults: #+begin_src emacs-lisp (after! org (setq org-export-with-author t) (setq org-export-with-creator nil) (setq org-export-with-date t) (setq org-export-with-toc t) (setq org-export-with-drawers nil) (setq org-export-with-sub-superscripts nil) (setq org-export-with-todo-keywords nil) ) #+end_src Do not export headline with the =:ignore:= tag: #+begin_src emacs-lisp ;; Used to not export headings with :ignore: tag (after! org (require 'ox-extra) (ox-extras-activate '(ignore-headlines))) #+end_src ** Org-ql #+begin_src emacs-lisp (use-package! org-ql :after org) #+end_src ** Org Effort #+begin_src emacs-lisp (after! org (setq org-global-properties '(("Effort_ALL". "0 0:10 0:30 1:00 2:00 3:00 4:00"))) ) #+end_src ** Open Files #+begin_src emacs-lisp (after! org (setq org-file-apps '((auto-mode . emacs) ("\\.x?html?\\'" . "firefox %s") ("\\.pdf\\'" . "zathura \"%s\"") ("\\.pdf::\\([0-9]+\\)\\'" . "zathura \"%s\" -p %1"))) ) #+end_src ** HTML Export *** HTML Defaults #+begin_src emacs-lisp (after! org (setq org-html-head "") (setq org-html-head-extra "") (setq org-html-head-include-default-style nil) (setq org-html-head-include-scripts nil) (setq org-html-viewport nil) (setq org-html-html5-fancy t) (setq org-html-doctype "xhtml-strict") (setq org-html-wrap-src-lines nil) ;; Export with css class instead of inline css (setq org-html-htmlize-output-type 'css) ) #+end_src *** Footnotes #+begin_src emacs-lisp (after! org (setq org-html-footnotes-section "
\n

%s

\n
\n%s\n
\n
")) #+end_src *** MathJax #+begin_src emacs-lisp (after! org (setq org-html-mathjax-template " ") (setq org-html-mathjax-options '((path "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" ) (scale "1") (autonumber "ams") (tagindent ".8em") (tagside "right"))) ) #+end_src *** MP4 Video - =video= link #+begin_src emacs-lisp (defun org-video-link-export (path desc backend) (let ((ext (file-name-extension path))) (cond ((eq 'html backend) (format "" ext path)) ;; fall-through case for everything else (t path)))) (after! org (org-link-set-parameters "video" :export 'org-video-link-export) (org-export-string-as "video:xxx.mp4" 'html t) ) #+end_src ** Org Xournalpp #+begin_src emacs-lisp (use-package! org-xournalpp :config (add-hook 'org-mode-hook 'org-xournalpp-mode)) #+end_src ** Org LaTeX *** LaTeX Fragments #+begin_src emacs-lisp (after! org ;; Highligh latex parts in org mode (setq org-highlight-latex-and-related '(latex script entities)) ;; Use F9 to globally generate all the latex fragments (map! :map org-mode-map :n "" (lambda () (interactive) (org-preview-latex-fragment 16))) ;; Put all the preview images in some directory (setq org-preview-latex-image-directory "~/.local/share/ltximg/") ;; Define backends to preview LaTeX fragments (setq org-preview-latex-process-alist '((imagemagick :programs ("pdflatex" "convert") :description "pdf > png" :message "you need to install the programs: pdflatex and imagemagick." :image-input-type "pdf" :image-output-type "png" :image-size-adjust (1.0 . 1.0) :latex-compiler ("pdflatex -interaction nonstopmode -output-directory %o %f") :image-converter ("convert -density 100 -trim -antialias %f -quality 100 %O")) (dvipng :programs ("latex" "dvipng") :description "dvi > png" :message "you need to install the programs: latex and dvipng." :image-input-type "dvi" :image-output-type "png" :image-size-adjust (0.4 . 0.4) :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f") :image-converter ("dvipng -D %D -T tight -o %O %f")) (pdf2svg :programs ("pdflatex" "pdftocairo" "pdfcrop") :description "pdf > png" :message "you need to install the programs: pdflatex, pdftocairo and pdfcrop." :image-input-type "pdf" :image-output-type "svg" :image-size-adjust (1.0 . 1.0) :latex-compiler ("pdflatex -interaction nonstopmode -output-directory %o %f") :image-converter ("pdfcrop %f %f && pdf2svg %f %O")) (pdf2dvi :programs ("pdflatex" "dvipng") :description "pdf > png" :message "you need to install the programs: pdflatex, pdftocairo and pdfcrop." :image-input-type "dvi" :image-output-type "png" :image-size-adjust (0.4 . 0.4) :latex-compiler ("pdflatex -output-format dvi -interaction nonstopmode -output-directory %o %f") :image-converter ("dvipng -D %D -T tight -o %O %f")) (dvisvgm :programs ("latex" "dvisvgm") :description "xdi > svg" :message "you need to install the programs: xetex and dvisvgm." :image-input-type "dvi" :image-output-type "svg" :image-size-adjust (0.6 . 0.6) :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f") :image-converter ("dvisvgm %f --no-fonts --exact-bbox --scale=%S --output=%O")) )) ;; Use imagemagick/dvisvgm to generate png from pdf (setq org-preview-latex-default-process 'dvisvgm) ;; Don't change the font size for subscripts and superscripts in latex fragments. ;; This cause the orgmode tables not to be well aligned. (setq font-latex-fontify-script nil) ;; Colors of latex fragments (plist-put org-format-latex-options :foreground nil) (plist-put org-format-latex-options :background nil) ;; (setq org-format-latex-options (plist-put org-format-latex-options :foreground 'default)) ;; (setq org-format-latex-options (plist-put org-format-latex-options :background 'default)) ) #+end_src From https://karthinks.com/software/scaling-latex-previews-in-emacs/, scale the LaTeX fragments with the text: #+begin_src emacs-lisp (after! org (defun my/text-scale-adjust-latex-previews () "Adjust the size of latex preview fragments when changing the buffer's text scale." (pcase major-mode ('latex-mode (dolist (ov (overlays-in (point-min) (point-max))) (if (eq (overlay-get ov 'category) 'preview-overlay) (my/text-scale--resize-fragment ov)))) ('org-mode (dolist (ov (overlays-in (point-min) (point-max))) (if (eq (overlay-get ov 'org-overlay-type) 'org-latex-overlay) (my/text-scale--resize-fragment ov)))))) (defun my/text-scale--resize-fragment (ov) (overlay-put ov 'display (cons 'image (plist-put (cdr (overlay-get ov 'display)) :scale (+ 1.0 (* 0.25 text-scale-mode-amount)))))) (add-hook 'text-scale-mode-hook #'my/text-scale-adjust-latex-previews) ) #+end_src *** LaTeX Classes #+begin_src emacs-lisp (after! org ;; Custom classes to use when exporting to latex (add-to-list 'org-latex-classes '("beamer" ,(concat "\\documentclass[presentation]{beamer}\n" "[DEFAULT-PACKAGES]" "[PACKAGES]" "[EXTRA]\n") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))) (add-to-list 'org-latex-classes '("clean-cheatsheet" "\\documentclass{clean-cheatsheet}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ) (add-to-list 'org-latex-classes '("clean-beamer" "\\documentclass{clean-beamer}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ) (add-to-list 'org-latex-classes '("cleanreport" "\\documentclass{cleanreport}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ) (add-to-list 'org-latex-classes '("scrartcl" "\\documentclass{scrartcl}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ) (add-to-list 'org-latex-classes '("scrreprt" "\\documentclass[a4paper, 10pt, DIV=12, parskip=full]{scrreprt}" ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ) (add-to-list 'org-latex-classes '("biblioreport" "\\documentclass{biblioreport}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ) (add-to-list 'org-latex-classes '("moderncv" "\\documentclass{moderncv}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) ) ) #+end_src *** Ox Latex Subfigure package #+begin_src emacs-lisp (use-package! ox-latex-subfigure :load-path "~/.config/doom/packages/ox-latex-subfigure/" :config (require 'ox-latex-subfigure)) #+end_src *** Clear page before heading https://emacs.stackexchange.com/questions/30575/adding-latex-newpage-before-a-heading/30892 #+begin_src emacs-lisp (after! org (defun tdh-get-headline-string-element (headline backend info) (let ((prop-point (next-property-change 0 headline))) (if prop-point (plist-get (text-properties-at prop-point headline) :parent)))) (defun tdh-ensure-latex-clearpage (headline backend info) (when (org-export-derived-backend-p backend 'latex) (let ((elmnt (tdh-get-headline-string-element headline backend info))) (when (and elmnt (org-element-property :CLEARPAGE elmnt)) (concat "\\clearpage\n" headline))))) (add-to-list 'org-export-filter-headline-functions 'tdh-ensure-latex-clearpage) ) #+end_src *** TODO Default added packages #+begin_src emacs-lisp (after! org (setq org-latex-default-packages-alist '(("AUTO" "inputenc" t ("pdflatex")) ;; for basic font and character selection ("T1" "fontenc" t ("pdflatex")) ;; for basic font and character selection ("" "graphicx" t) ;; for including images ("" "grffile" t) ;; allow periods and spaces in graphics file names ("" "longtable" nil) ;; For multipage tables ("" "wrapfig" nil) ;; for figure placement ("" "rotating" nil) ;; for sideways figures and tables ("normalem" "ulem" t) ;; for underline and strike-through ("" "amsmath" t) ;; for subscript and superscript and math environments ("" "textcomp" t) ;; for various symbols ("" "amssymb" t) ;; for various symbols ("" "capt-of" nil) ;; for captions outside of floats ("" "hyperref" nil)) ;; for cross references ) ) #+end_src #+begin_src emacs-lisp (after! org (add-to-list 'org-latex-packages-alist '("" "siunitx" t)) (add-to-list 'org-latex-packages-alist '("" "array" t)) (add-to-list 'org-latex-packages-alist '("" "tabularx" t)) (add-to-list 'org-latex-packages-alist '("" "booktabs" t)) (add-to-list 'org-latex-packages-alist '("" "bm" t)) (add-to-list 'org-latex-packages-alist '("most" "tcolorbox" t)) ) #+end_src *** Some configurations #+begin_src emacs-lisp (after! org ;; Setup default option for image size when exporting to LaTeX (setq org-latex-image-default-scale "") (setq org-latex-image-default-width "") (setq org-latex-image-default-height "") (setq org-latex-image-default-option "scale=1") ;; Use define labels instead of automatic generated ones (setq org-latex-prefer-user-labels t) ;; Captions above the table (setq org-latex-caption-above '(table)) ;; Settings to export code with `minted' instead of `verbatim'. (setq org-latex-listings 'minted) ;; Set the following as images (setq org-latex-inline-image-rules '(("file" . "\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\|tikz\\|pgf\\|svg\\|gif\\)\\'"))) ;; Command used when exporting to pdf (setq org-latex-pdf-process '("latexmk -cd -pdflatex=\"pdflatex -synctex=1 -shell-escape -interaction nonstopmode -output-directory %o\" -pdf -f %f")) ;; ;; Better display of timestamps ;; (setq org-latex-diary-timestamp-format "\\footnotesize{\\textit{%s}}" ;; org-latex-inactive-timestamp-format "\\footnotesize{\\textit{%s}}" ;; org-latex-active-timestamp-format "\\footnotesize{\\textit{%s}}") (defun org-export-filter-timestamp-remove-brackets (timestamp backend info) "removes relevant brackets from a timestamp" (cond ((org-export-derived-backend-p backend 'latex) (replace-regexp-in-string "[<>]\\|[][]" "" timestamp)) ((org-export-derived-backend-p backend 'html) (replace-regexp-in-string "&[lg]t;\\|[][]" "" timestamp)))) (eval-after-load 'ox '(add-to-list 'org-export-filter-timestamp-functions 'org-export-filter-timestamp-remove-brackets)) ) #+end_src *** Beamer Bold Text #+begin_src emacs-lisp (after! org (defun tdh-my-beamer-bold (contents backend info) (when (eq backend 'beamer) (replace-regexp-in-string (concat "\\`\\\\" "[A-Za-z0-9]+") ;; If not, orgmode is crazy... "\\\\textbf" contents))) (add-to-list 'org-export-filter-bold-functions 'tdh-my-beamer-bold) ) #+end_src Special Environments - [ ] Make some comment those special environments #+begin_src emacs-lisp (after! org-beamer (add-to-list 'org-beamer-environments-extra '("cbox" ;; Name of environment "m" ;; Selection key "\\onslide%a{\\begin{cbox}[%h]%O" "\\end{cbox}}\\vspace{0.5em}")) (add-to-list 'org-beamer-environments-extra '("csubbox" ;; Name of environment "M" ;; Selection key "\\onslide%a{\\tcbsubtitle{%h}" "}")) ) #+end_src *** Number Equations https://kitchingroup.cheme.cmu.edu/blog/2016/11/07/Better-equation-numbering-in-LaTeX-fragments-in-org-mode/ #+begin_src emacs-lisp (after! org (defun tdh-org-renumber-environment (orig-func &rest args) "A function to inject numbers in LaTeX fragment previews." (let ((results '()) (counter -1) (numberp)) (setq results (loop for (begin . env) in (org-element-map (org-element-parse-buffer) 'latex-environment (lambda (env) (cons (org-element-property :begin env) (org-element-property :value env)))) collect (cond ((and (string-match "\\\\begin{equation}" env) (not (string-match "\\\\tag{" env))) (incf counter) (cons begin counter)) ((string-match "\\\\begin{align}" env) (prog2 (incf counter) (cons begin counter) (with-temp-buffer (insert env) (goto-char (point-min)) ;; \\ is used for a new line. Each one leads to a number (incf counter (count-matches "\\\\$")) ;; unless there are nonumbers. (goto-char (point-min)) (decf counter (count-matches "\\nonumber"))))) (t (cons begin nil))))) (when (setq numberp (cdr (assoc (point) results))) (setf (car args) (concat (format "\\setcounter{equation}{%s}\n" numberp) (car args))))) (apply orig-func args)) (advice-add 'org-create-formula-image :around #'tdh-org-renumber-environment) ) #+end_src ** LaTeX macro both for LaTeX and HTML export https://www.reddit.com/r/orgmode/comments/7u2n0h/tip_for_defining_latex_macros_for_use_in_both/ #+begin_src emacs-lisp (after! org (add-to-list 'org-src-lang-modes '("latex-macros" . latex)) (defvar org-babel-default-header-args:latex-macros '((:results . "raw") (:exports . "results"))) (defun prefix-all-lines (pre body) (with-temp-buffer (insert body) (string-insert-rectangle (point-min) (point-max) pre) (buffer-string))) (defun org-babel-execute:latex-macros (body _params) (concat "\n#+begin_export html\n
\\(\n" body "\n\\)
\n#+end_export\n")) ) #+end_src ** Automatically run =startblock= when opening org-mode files #+begin_src emacs-lisp (after! org (defun tdh-eval-startblock () (if (member "startblock" (org-babel-src-block-names)) (save-excursion (org-babel-goto-named-src-block "startblock") (org-babel-execute-src-block)) nil ) ) (add-hook 'org-mode-hook 'tdh-eval-startblock) ) #+end_src ** Org mode and Yasnippet =TAB= used not to work well with Yasnippet ([[https://github.com/doomemacs/doomemacs/issues/7733#issuecomment-2586904927][github issue]]), with the following, it works well: #+begin_src emacs-lisp (map! :map org-mode-map :after yasnippet ;; Retain org-mode's native TAB functionality but allow yas-expand when a snippet is available :nvi [tab] yas-maybe-expand ;; Optionally, bind other keys for snippet navigation :nvi "C-c n" #'yas-next-field :nvi "C-c p" #'yas-prev-field) #+end_src ** Some function #+begin_src emacs-lisp (defun org-syntax-convert-case-to-lower () "Convert all #+KEYWORDS to #+keywords." (interactive) (save-excursion (goto-char (point-min)) (let ((count 0) (case-fold-search nil)) (while (re-search-forward "#\\+[A-Z_]+" nil t) (replace-match (downcase (match-string 0)) t) (setq count (1+ count))) (message "Replaced %d occurances" count)))) #+end_src ** Render Tables https://www.reddit.com/r/emacs/comments/d3a8or/pretty_org_tables_in_the_buffer_chapter_2_it/ #+begin_src emacs-lisp :tangle no (after! org (defun tdh-render-org-table-at-point () (interactive) (save-excursion (beginning-of-line) ;; removes the overlay is already there (if (overlays-at (point)) (delete-overlay (car (overlays-at (point)))) (let* ((element-type (org-element-type (org-element-at-point)))) (if (and (not (eq element-type 'table)) (not (eq element-type 'table-row))) (error "not at an org table") (while (not (eq 'table (org-element-type (org-element-at-point)))) (forward-line -1)) (tdh-render-org-table (org-element-at-point)) ))))) (defun tdh-render-org-table (table) (interactive) (let* ((begin (org-element-property :begin table)) (end (let ((pos (org-element-property :end table))) (goto-char pos) (beginning-of-line) ;; skip possible space after table (while (not (looking-at " *[|#]")) (setq pos (point)) (forward-line -1)) pos)) (tabletxt (buffer-substring-no-properties begin end)) (img (with-temp-buffer (insert tabletxt) (mark-whole-buffer) (org-latex-convert-region-to-latex) (org-latex-preview) (goto-char (point-min)) (overlay-get (car (overlays-at (point))) 'display))) (overlay (make-overlay begin end))) (overlay-put overlay 'display img) (forward-line -1)) ) (defun tdh-render-org-tables-in-buffer () (save-excursion (org-element-map (org-element-parse-buffer) 'table 'tdh-render-org-table))) ;; Use F9 to globally generate tables (map! :map org-mode-map :n "" (lambda () (interactive) (tdh-render-org-table-at-point))) ) #+end_src ** Disable LaTeX fragments in table #+begin_src emacs-lisp (after! org ;; Toggle (defvar td/org-disable-latex-in-tables t "If non-nil, disable LaTeX preview inside Org tables.") (defun td/toggle-latex-in-tables () (interactive) (setq td/org-disable-latex-in-tables (not td/org-disable-latex-in-tables)) (message "Disable LaTeX preview in tables: %s" td/org-disable-latex-in-tables)) (defun td/point-in-table-p (pos) "Check if position POS is inside an Org table." (save-excursion (goto-char pos) (org-at-table-p))) (defadvice! td/org-format-latex-ignore-tables (orig-fn &rest args) "Disable LaTeX preview inside Org tables." :around #'org-format-latex (let ((beg (nth 0 args)) (end (nth 1 args))) ;; If toggle is OFF → run normally (if (not td/org-disable-latex-in-tables) (apply orig-fn args) ;; If this is NOT a user-initiated call (no buffer positions) ;; we need to check if we're currently inside a table (if (not (and (number-or-marker-p beg) (number-or-marker-p end))) ;; Internal call: check if point is in a table (if (td/point-in-table-p (point)) nil ; Skip if in table (apply orig-fn args)) ; Process if not in table ;; User-initiated preview with buffer region ;; Temporarily narrow to exclude table lines, then process (save-restriction (narrow-to-region beg end) (goto-char (point-min)) ;; Process each non-table section separately (let ((start (point-min))) (while (not (eobp)) (if (org-at-table-p) ;; Skip the entire table (progn ;; Process region before table (when (< start (point)) (apply orig-fn (list start (point)) (cddr args))) ;; Move past table (org-table-end) (setq start (point))) ;; Move to next line (forward-line 1))) ;; Process any remaining region after last table (when (< start (point-max)) (apply orig-fn (list start (point-max)) (cddr args)))))))))) ;; Optional keybinding (map! :leader :desc "Toggle LaTeX preview inside Org tables" "t t" #'td/toggle-latex-in-tables) #+end_src ** Org CalDAV #+begin_src emacs-lisp (use-package! org-caldav :config (setq org-caldav-url "https://radicale.tdehaeze.xyz/tdehaeze" org-caldav-calendar-id "627e2bee-7d6a-49dc-128e-fc7a8aed1e8b" org-caldav-inbox "~/Cloud/org/inbox-calendar.org" org-caldav-files '("~/Cloud/org/inbox.org" "~/Cloud/org/home-tasks.org") org-icalendar-use-scheduled '(event-if-todo-not-done) org-icalendar-use-deadline '(event-if-todo-not-done) org-caldav-days-in-past 7 org-icalendar-timezone "Europe/Paris" )) #+end_src ** Org Inline Task #+begin_src emacs-lisp (after! org (require 'org-inlinetask) ) #+end_src ** Org Links *** =yt:= Youtube Links #+begin_src emacs-lisp (after! org (setq yt-iframe-format ;; You may want to change your width and height. (concat "
")) (org-add-link-type "yt" (lambda (handle) (browse-url (concat "https://www.youtube.com/embed/" handle))) (lambda (path desc backend) (cl-case backend (html (format yt-iframe-format path (or desc ""))) (md (format "{{< youtube %s >}}" path)) (latex (format "\\href{%s}{%s}" (concat "https://www.youtube.com/embed/" path) (or desc "video")))))) ) #+end_src *** =message:= link to mutt #+begin_src emacs-lisp ;; Customizable variables (defcustom tdh/org-mutt-terminal "kitty" "The terminal emulator to use for opening Mutt/Neomutt." :group 'org-link :type 'string) (defcustom tdh/org-mutt-executable "neomutt" "The Mutt/Neomutt executable name." :group 'org-link :type 'string) (defcustom tdh/org-mutt-mu-utility "mu" "The 'mu' mail indexer executable name." :group 'org-link :type 'string) (defun tdh/org-open-mutt-message (message-id) "Open the email with the given Message-ID in Mutt/Neomutt using 'mu'. This function is intended to be called by Org mode for 'message://' links. It uses `mu find` to locate the email file, determines the Maildir folder, and launches Mutt/Neomutt in a terminal specified by `tdh/org-mutt-terminal`, instructing it to limit view to the specific message. The Message-ID should be passed without the 'message://' prefix and without surrounding '<>' characters." (interactive "sMessage-ID: ") ; For testing interactively (let* ( ;; 1. Sanitize Message-ID (remove potential whitespace or <>) (msg-id (replace-regexp-in-string "[<>[:space:]\n]" "" message-id)) ;; 2. Construct the 'mu find' command safely (mu-find-command (format "%s find --nocolor -f l i:%s | head -n 1" (shell-quote-argument tdh/org-mutt-mu-utility) (shell-quote-argument msg-id))) ; Quote msg-id for shell ;; 3. Execute 'mu find' and get the mail file path (mail-file-raw (shell-command-to-string mu-find-command)) ;; Trim leading/trailing whitespace and newlines from the result (mail-file (replace-regexp-in-string "\\`[[:space:]]*\\|[[:space:]]*\\'" "" mail-file-raw))) ;; 4. Check if 'mu find' returned a valid path (if (or (string-empty-p mail-file) (not (file-exists-p mail-file))) (error "Could not find mail file for Message-ID '%s'. Command: %s. Result: '%s'" msg-id mu-find-command mail-file-raw) ;; 5. Derive the Maildir *folder* from the file path (let* ( ;; This regex assumes standard Maildir structure like /path/to/Maildir/cur/filename ;; It removes the "/cur/filename", "/new/filename", or "/tmp/filename" part. ;; Adjust if your Maildir structure or mu's output format differs. (mail-dir (replace-regexp-in-string "/\\(cur\\|new\\|tmp\\)/[^/]*$" "/" mail-file)) ;; Alternative (simpler, maybe less robust): just get parent dir of the file ;; (mail-dir (directory-file-name (file-name-directory mail-file))) ;; 6. Define the keystrokes to send to Mutt/Neomutt ;; L: Limit command ;; ~i : Search Message-ID header ;; \n: Execute limit ;; \n: Press Enter again (should open the first/only message in the limited view) (mutt-keystrokes (format "L~i %s\n\n" msg-id)) ; Limit, Enter, Enter to open ;; 7. Prepare arguments for the terminal and Mutt/Neomutt (mutt-base-args (list "-R" ; Start read-only (safer, remove if you want write access) "-f" mail-dir "-e" (format "push '%s'" mutt-keystrokes))) ;; Command list for the terminal emulator (process-args (append (list "-e" tdh/org-mutt-executable) mutt-base-args)) (process-name (concat tdh/org-mutt-executable "-" msg-id))) ; Unique process name for Emacs (message "Launching %s for message %s (Maildir: %s)" tdh/org-mutt-executable msg-id mail-dir) ;; 8. Launch the process asynchronously using start-process (doesn't block Emacs) (apply 'start-process process-name nil tdh/org-mutt-terminal process-args) ;; --- Alternative: Using call-process + setsid (might block Emacs briefly) --- ;; This combines the arguments differently because setsid takes the command first ;; (let ((full-command (append (list tdh/org-mutt-executable) mutt-base-args))) ;; (apply 'call-process "setsid" nil nil "-f" tdh/org-mutt-terminal "-e" full-command)) )))) ;; Register the link type handler with Org mode (org-add-link-type "message" 'tdh/org-open-mutt-message t) ; Added 't' to force update if already defined #+end_src ** Org Wild Notifier #+begin_src emacs-lisp (use-package! org-wild-notifier :after org :init (setq alert-default-style 'libnotify) :config (setq org-wild-notifier-alert-time '(10 5)) (setq org-wild-notifier-notification-title "Org Agenda") (org-wild-notifier-mode) ) #+end_src ** Custom Keybindings - =,= leader key and =C-c= | | | |---------+-------------------| | =C-c a= | Org Agenda | | =C-c n= | Narrow to Subtree | | =C-c l= | Org Link | #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:desc "Org Agenda" :ni "C-c a" 'org-agenda) (:desc "Archive" :n "C-c A" 'org-archive-subtree) (:desc "Org Capture" :ni "C-c c" 'org-capture) (:desc "Store Link" :ni "C-c l" 'org-store-link) (:desc "Narrow Subtree" :ni "C-c n" 'org-toggle-narrow-to-subtree) (:desc "Org Noter" :ni "C-c N" 'org-noter) (:desc "Align Block" :ni "C-c =" 'tdh-align-src-block) (:desc "Insert Reference" :ni "C-c r" 'org-ref-insert-ref-link) (:desc "Insert Image" :ni "C-c i" 'tdh-insert-image-org-link) (:desc "Insert Image SXIV" :ni "C-c I" 'tdh-insert-image-org-link-sxiv) (:desc "Link to next Figure" :ni "C-c f" 'tdh-insert-link-to-next-figure) (:desc "Link to previous Figure" :ni "C-c F" 'tdh-insert-link-to-previous-figure) (:desc "Link to next Table" :ni "C-c t" 'tdh-insert-link-to-next-table) (:desc "Link to previous Table" :ni "C-c T" 'tdh-insert-link-to-previous-table) (:desc "Insert Screenshot" :ni "C-c s" 'tdh-insert-screenshot-org-link) (:desc "Insert Screenshot" :ni "C-c R" 'org-roam-node-find) (:desc "Helm Bibtex" :ni "C-c ]" 'org-ref-cite-insert-helm) )) #+end_src *** Insert Elements =,i= Insert Link to paper #+begin_src emacs-lisp (defun tdh-insert-paper-org-link (paper) "Insert an org link to some paper, choosing the file with completion" (interactive (list (read-file-name "Paper: " "~/Cloud/pdfs/" nil t))) (insert (format "[[papers:%s]]" (file-name-base paper)))) #+end_src Insert Link to notes #+begin_src emacs-lisp (defun tdh-insert-note-org-link (note) "Insert an org link to some note, choosing the file with completion" (interactive (list (read-file-name "Note: " "~/Cloud/pdfs/" nil t))) (insert (format "[[notes:%s]]" (file-name-base note)))) #+end_src Insert Image that is in the figs folder #+begin_src emacs-lisp (defun tdh-insert-image-org-link (img) "Insert an org image link, choosing the file with completion and starting from `my-default-image-directory'." (interactive (list (file-relative-name (read-file-name "Image: " (concat default-directory "figs/")) default-directory))) (insert (format "[[file:%s]]" img))) #+end_src Insert Image that is in the =figs= folder using SXIV #+begin_src emacs-lisp (defun tdh-insert-image-org-link-sxiv () "Insert an org image link, choosing the file with completion and starting from `my-default-image-directory'." (interactive) (setq img (shell-command-to-string "ls figs/*.{jpg,jpeg,bmp,png,gif} 2> /dev/null | nsxiv -i -t -o | tail -1 | tr -d '\n'")) (unless (equal "" img) (insert (format "[[file:%s]]" img))) ) #+end_src Copy picture from phone folder using SXIV and insert it #+begin_src emacs-lisp (defun tdh-insert-phone-picture () (interactive) (setq img (shell-command-to-string "~/.config/doom/bin/copy-phone-picture.sh")) (unless (equal "" img) (insert (format "[[file:%s]]" img))) ) #+end_src Bash script for copying pictures taken by phone. #+begin_src bash :comments both :mkdirp yes :shebang "#!/usr/bin/env bash" :tangle ~/.config/doom/bin/copy-phone-picture.sh if [ -z "$1" ]; then oldpath=$(ls -t ~/Cloud/photos/phone/*.jpg | nsxiv -i -t -o | tail -1); else oldpath=$(ls -t $1 | nsxiv -i -t -o | tail -1); fi if [ -n "$oldpath" ]; then newfilename=$(basename $oldpath .jpg | rofi -i -dmenu -p "Filename") if [ -n "$newfilename" ]; then cp $oldpath "figs/$newfilename.jpg" printf "figs/$newfilename.jpg" fi fi #+end_src Take Screenshot and insert a link: - Ask for a name =screenshot_name= - use =maim -s figs/screenshot_name.png= to take a screenshot with selection - Then insert the following to the buffer #+begin_src emacs-lisp (defun tdh-insert-screenshot-org-link () "Capture screenshot and insert the resulting file. The screenshot tool is determined by `org-download-screenshot-method'." (interactive) (if (string-match "_" (file-name-base buffer-file-name)) (setq filename (read-string "Enter file name:" (car (split-string (file-name-base buffer-file-name) "_")))) (setq filename (read-string "Enter file name:"))) (setq filepath (concat "./figs/" filename ".png")) (shell-command (concat "maim -u -s " filepath)) (insert (format "#+name: fig:%s\n#+caption:\n[[file:%s]]" filename filepath)) (search-backward "caption") (end-of-line) ) #+end_src Insert link to next figure: #+begin_src emacs-lisp (defun tdh-insert-link-to-next-figure () (interactive) (save-excursion (re-search-forward "^#\\+name:\s*\\(fig:.*\\)" nil t 1)) (insert (concat "ref:" (match-string 1))) ) #+end_src Insert link to previous figure: #+begin_src emacs-lisp (defun tdh-insert-link-to-previous-figure () (interactive) (save-excursion (re-search-backward "^#\\+name:\s*\\(fig:.*\\)" nil t 1)) (insert (concat "ref:" (match-string 1))) ) #+end_src Insert link to next table: #+begin_src emacs-lisp (defun tdh-insert-link-to-next-table () (interactive) (save-excursion (re-search-forward "^#\\+name:\s*\\(tab:.*\\)" nil t 1)) (insert (concat "ref:" (match-string 1))) ) #+end_src Insert link to previous table: #+begin_src emacs-lisp (defun tdh-insert-link-to-previous-table () (interactive) (save-excursion (re-search-backward "^#\\+name:\s*\\(tab:.*\\)" nil t 1)) (insert (concat "ref:" (match-string 1))) ) #+end_src Map Keys #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:prefix (",i" . "Insert") :n "p" 'tdh-insert-paper-org-link :n "n" 'tdh-insert-note-org-link :n "f" 'tdh-insert-image-org-link :n "F" 'tdh-insert-image-org-link-sxiv :n "i" 'tdh-insert-phone-picture :n "l" 'tdh-insert-link-to-next-figure :n "L" 'tdh-insert-link-to-previous-figure :n "s" 'tdh-insert-screenshot-org-link))) #+end_src *** LaTeX =,l= #+begin_src emacs-lisp (defun tdh-latex-watch () "Watch LaTeX file using latexmk" (interactive) (start-process-shell-command "latexmk-watch" "*latexmk-watch-output*" "latexmk -bibtex -pvc")) #+end_src #+begin_src emacs-lisp (defun tdh-latex-watch-kill () "Kill the currently running TeX job." (interactive) (delete-process "latexmk-watch") ) #+end_src #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:prefix (",l" . "LaTeX") :n "w" 'tdh-latex-watch :n "k" 'tdh-latex-watch-kill :n "l" 'org-latex-export-to-latex))) #+end_src *** Org LaTeX Automatic fragment #+begin_src emacs-lisp (use-package! org-fragtog :after org :config (add-hook 'org-mode-hook 'org-fragtog-mode) ) #+end_src #+begin_src emacs-lisp (defun tdh-automatic-latex-fragment-activate () (interactive) (add-hook 'org-mode-hook 'org-fragtog-mode)) (defun tdh-automatic-latex-fragment-deactivate () (interactive) (remove-hook 'org-mode-hook 'org-fragtog-mode)) #+end_src #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:prefix (",l" . "LaTeX") :n "f" 'tdh-automatic-latex-fragment-activate :n "F" 'tdh-automatic-latex-fragment-deactivate))) #+end_src *** Org-Appear #+begin_src emacs-lisp (use-package! org-appear :after org :hook (org-mode . org-appear-mode) :config (setq org-appear-autolinks t org-appear-autoentities t org-appear-autosubmarkers t )) #+end_src *** Bibtex =,r= #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:prefix (",r" . "References") :n "b" 'helm-bibtex :n "B" 'helm-bibtex-with-local-bibliography :n "f" 'tdh-helm-bibtex-favorites :n "r" 'helm-resume))) #+end_src *** Open yazi in current directory =,o= #+begin_src emacs-lisp (defun tdh-open-yazi-in-workdir () (interactive) (call-process-shell-command (concat "kitty -e yazi " default-directory) nil 0)) #+end_src #+begin_src emacs-lisp (after! org (map! :map org-mode-map :n ",o" 'tdh-open-yazi-in-workdir)) #+end_src *** View in External programs =,v= Open PDF output with =zathura= #+begin_src emacs-lisp (defun tdh-open-org-pdf-externally () (interactive) (call-process "zathura" nil 0 nil (concat (file-name-sans-extension (buffer-file-name)) ".pdf")) ) #+end_src Open HTML output externally #+begin_src emacs-lisp (defun tdh-open-org-html-externally () (interactive) (call-process "xdg-open" nil 0 nil (concat (file-name-sans-extension (buffer-file-name)) ".html")) ) #+end_src #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:prefix (",v" . "View") :n "p" 'tdh-open-org-pdf-externally :n "h" 'tdh-open-org-html-externally))) #+end_src * Org Babel ** Main configuration Don't ask for confirmation when evaluating following blocs #+begin_src emacs-lisp (defun tdh-org-confirm-babel-evaluate (lang body) (not (member lang '("emacs-lisp" "latex" "matlab" "sh" "latex-macros" "python" "ipython" "jupyter-python" "dot")))) (after! org (setq org-confirm-babel-evaluate 'tdh-org-confirm-babel-evaluate)) #+end_src Default header arguments. #+begin_src emacs-lisp (after! org (setq org-babel-default-header-args '((:eval . "no-export")))) #+end_src Use the current window for C-c ' source editing #+begin_src emacs-lisp (after! org (setq org-src-window-setup 'current-window)) #+end_src ** Appearance of source blocks #+begin_src emacs-lisp (defun tdh-org-prettify-symbols () (mapc (apply-partially 'add-to-list 'prettify-symbols-alist) (cl-reduce 'append (mapcar (lambda (x) (list x (cons (upcase (car x)) (cdr x)))) `(("#+begin_src" . ?✎) ("#+end_src" . ?□) ("#+begin_quote" . ?«) ("#+end_quote" . ?»))))) (turn-on-prettify-symbols-mode)) (add-hook 'org-mode-hook #'tdh-org-prettify-symbols) #+end_src ** Indentation #+begin_src emacs-lisp (after! org ;; Don't change indentation when toggling (setq org-src-preserve-indentation t) ) #+end_src ** Library of Babel Add all named source blocks to =org-babel-library-of-babel= ([[file:emacs-library-babel.org][link]]). #+begin_src emacs-lisp (after! org (org-babel-lob-ingest "~/.config/literate-dotfiles/emacs-library-babel.org")) #+end_src ** Org-Babel Matlab #+begin_src emacs-lisp (after! org (setq org-babel-matlab-shell-command "~/.local/bin/matlab -softwareopengl -nodesktop -nosplash") ) #+end_src Default options for Matlab code #+begin_src emacs-lisp (after! org (setq org-babel-default-header-args:matlab '((:results . "none") (:session . "*MATLAB*") (:comments . "org") (:exports . "both") (:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "yes") (:mkdir . "yes") (:eval . "no-export"))) ) #+end_src Better format the output results for Matlab ([[https://www.reddit.com/r/emacs/comments/fy98bs/orgbabels_matlab_session_output_is_malformed/?utm_source=share&utm_medium=web2x][link]]). #+begin_src emacs-lisp (after! org (setq org-babel-octave-wrapper-method "%s if ischar(ans), fid = fopen('%s', 'w'); fprintf(fid, '%%s\\n', ans); fclose(fid); else, save -ascii %s ans end ") (defun org-babel-octave-evaluate-session (session body result-type &optional matlabp) "Evaluate BODY in SESSION." (let* ((tmp-file (org-babel-temp-file (if matlabp "matlab-" "octave-"))) (wait-file (org-babel-temp-file "matlab-emacs-link-wait-signal-")) (full-body (pcase result-type (`output (mapconcat #'org-babel-chomp (list (if matlabp (multi-replace-regexp-in-string '(("%.*$" . "") ;Remove comments (";\\s-*\n+" . "; ") ;Concatenate lines ("\\(\\.\\)\\{3\\}\\s-*\n+" . " ") ;Handle continuations (",*\\s-*\n+" . ", ")) ;Concatenate lines body) body) org-babel-octave-eoe-indicator) "\n")) (`value (if (and matlabp org-babel-matlab-with-emacs-link) (concat (format org-babel-matlab-emacs-link-wrapper-method body (org-babel-process-file-name tmp-file 'noquote) (org-babel-process-file-name tmp-file 'noquote) wait-file) "\n") (mapconcat #'org-babel-chomp (list (format org-babel-octave-wrapper-method body (org-babel-process-file-name tmp-file 'noquote) (org-babel-process-file-name tmp-file 'noquote)) org-babel-octave-eoe-indicator) "\n"))))) (raw (if (and matlabp org-babel-matlab-with-emacs-link) (save-window-excursion (with-temp-buffer (insert full-body) (write-region "" 'ignored wait-file nil nil nil 'excl) (matlab-shell-run-region (point-min) (point-max)) (message "Waiting for Matlab Emacs Link") (while (file-exists-p wait-file) (sit-for 0.01)) "")) ;; matlab-shell-run-region doesn't seem to ;; make *matlab* buffer contents easily ;; available, so :results output currently ;; won't work (org-babel-comint-with-output (session (if matlabp org-babel-octave-eoe-indicator org-babel-octave-eoe-output) t full-body) (insert full-body) (comint-send-input nil t)))) results) (pcase result-type (`value (org-babel-octave-import-elisp-from-file tmp-file)) (`output (setq results (if matlabp (cdr (reverse (delete "" (mapcar #'org-strip-quotes (mapcar #'org-trim (remove-car-upto-newline raw)))))) (cdr (member org-babel-octave-eoe-output (reverse (mapcar #'org-strip-quotes (mapcar #'org-trim raw))))))) (mapconcat #'identity (reverse results) "\n"))))) (defun remove-car-upto-newline (raw) "Truncate each string in a list of strings up to the first newline" (cons (mapconcat #'identity (cdr (split-string-and-unquote (car raw) "\n")) "\n") (cdr raw))) (defun multi-replace-regexp-in-string (replacements-list string &optional rest) (interactive) "Replace multiple regexps in a string. Order matters." (if (null replacements-list) string (let ((regex (caar replacements-list)) (replacement (cdar replacements-list))) (multi-replace-regexp-in-string (cdr replacements-list) (replace-regexp-in-string regex replacement string rest))))) ) #+end_src ** Some functions for using Matlab with Org Babel =,m= =whos= matlab function #+begin_src emacs-lisp (defun tdh-matlab-whos (&optional start end) "Get what is in the Matlab workspace" (interactive) (if (use-region-p) (let ((regionp (buffer-substring (region-beginning) (region-end)))) (process-send-string "*MATLAB*" (concat "whosEmacs " regionp "\n"))) (process-send-string "*MATLAB*" (concat "whosEmacs" "\n")))) #+end_src =help= matlab function #+begin_src emacs-lisp (defun tdh-matlab-help (&optional start end) "Get help on the selected function" (interactive) (if (use-region-p) (let ((regionp (buffer-substring (region-beginning) (region-end)))) (process-send-string "*MATLAB*" (concat "help " regionp "\n"))) (process-send-string "*MATLAB*" (concat "help " (read-string "Matlab help:") "\n"))) ) #+end_src Specify a Matlab command to run #+begin_src emacs-lisp (defun tdh-matlab-run-command () "Prompt user to enter a matlab command" (interactive) (process-send-string "*MATLAB*" (concat (read-string "Matlab Command: ") "\n"))) #+end_src Specify a Matlab command to run and show output in mini-buffer #+begin_src emacs-lisp (defun tdh-matlab-run-command-show-output () "Prompt user to enter a matlab command" (interactive) (process-send-string "*MATLAB*" (concat "evalEmacs('" (read-string "Matlab Command: ") "')\n"))) #+end_src Org-Babel Tangle File and Execute with Matlab #+begin_src emacs-lisp (defun tdh-matlab-tangle-and-execute () "Jump to tangle file for the source block at point." (interactive) (let (file org-babel-pre-tangle-hook org-babel-post-tangle-hook) (cl-letf (((symbol-function 'write-region) (lambda (start end filename &rest _ignore) (setq file filename))) ((symbol-function 'delete-file) #'ignore)) (org-babel-tangle '(4))) (when file (setq file (expand-file-name file)) (if (file-readable-p file) (process-send-string "*MATLAB*" (concat "run " file "\n")) (error "Cannot open tangle file %S" file))))) #+end_src Map Functions #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:prefix (",m" . "Matlab") :n "e" 'tdh-matlab-run-command :n "E" 'tdh-matlab-run-command-show-output :n "T" 'tdh-matlab-tangle-and-execute :nv "h" 'tdh-matlab-help :nv "w" 'tdh-matlab-whos))) #+end_src ** Remap =ctrl-ret= used to execute the src block and go to the next one https://emacs.stackexchange.com/questions/13869/how-to-toggle-org-mode-source-code-block-eval-no-status Remap =ctrl-ret= to execute the source block and go to the next source block when inside a source block. Otherwise, keep the normal behavior for =ctrl-ret=. #+begin_src emacs-lisp (defun tdh-ctrl-ret () (interactive) (defun tdh-in-src-block-p () "Returns t when the point is inside a source code block" (string= "src" (org-in-block-p '("src")))) (if (tdh-in-src-block-p) (progn (org-babel-execute-src-block) (org-babel-next-src-block)) (+org--insert-item 'below))) #+end_src #+begin_src emacs-lisp (map! :after evil-org :map evil-org-mode-map :n "" #'tdh-ctrl-ret) #+end_src ** Remap =ctrl-shift-ret= used to execute the (matlab) src block in the background and go to the next one *** =tdh-org-babel-execute-matlab-background= #+begin_src emacs-lisp (defun tdh-org-babel-execute-matlab-background (&optional arg info params) (interactive) (let* ((org-babel-current-src-block-location (or org-babel-current-src-block-location (nth 5 info) (org-babel-where-is-src-block-head))) (info (if info (copy-tree info) (org-babel-get-src-block-info)))) ;; Merge PARAMS with INFO before considering source block ;; evaluation since both could disagree. (cl-callf org-babel-merge-params (nth 2 info) params) (when (org-babel-check-evaluate info) (cl-callf org-babel-process-params (nth 2 info)) (let* ((params (nth 2 info)) (cache (let ((c (cdr (assq :cache params)))) (and (not arg) c (string= "yes" c)))) (new-hash (and cache (org-babel-sha1-hash info :eval))) (old-hash (and cache (org-babel-current-result-hash))) (current-cache (and new-hash (equal new-hash old-hash)))) (cond (current-cache (save-excursion ;Return cached result. (goto-char (org-babel-where-is-src-block-result nil info)) (forward-line) (skip-chars-forward " \t") (let ((result (org-babel-read-result))) (message (replace-regexp-in-string "%" "%%" (format "%S" result))) result))) ((org-babel-confirm-evaluate info) (let* ((lang (nth 0 info)) (result-params (cdr (assq :result-params params))) ;; Expand noweb references in BODY and remove any ;; coderef. (body (let ((coderef (nth 6 info)) (expand (if (org-babel-noweb-p params :eval) (org-babel-expand-noweb-references info) (nth 1 info)))) (if (not coderef) expand (replace-regexp-in-string (org-src-coderef-regexp coderef) "" expand nil nil 1)))) (dir (cdr (assq :dir params))) (mkdirp (cdr (assq :mkdirp params))) (default-directory (cond ((not dir) default-directory) ((member mkdirp '("no" "nil" nil)) (file-name-as-directory (expand-file-name dir))) (t (let ((d (file-name-as-directory (expand-file-name dir)))) (make-directory d 'parents) d)))) (cmd (intern (concat "org-babel-execute:" lang))) result) (process-send-string "*MATLAB*" (concat body "\n")) result)) ))) ) ) #+end_src *** =tdh-matlab-execute-selected= #+begin_src emacs-lisp (defun tdh-matlab-execute-selected (start end) "Execute selected text in the *MATLAB* buffer" (interactive "r") (let ((regionp (buffer-substring start end))) (process-send-string "*MATLAB*" (concat regionp "\n")))) #+end_src *** Remap =ctrl-shift-ref= This function: - first check if inside a source block, if not does nothing - when check if the language is =matlab= - if it is not, it just runs the code and go to the next source block - if it is in a =matlab= block, it first check if a region if selected, if so it just runs the selected region. if no region is selected, it runs all the code blocks and goes to the next block #+begin_src emacs-lisp (defun tdh-ctrl-shift-ret () (interactive) (defun tdh-in-src-block-p () "Returns t when the point is inside a source code block" (string= "src" (org-in-block-p '("src")))) (if (tdh-in-src-block-p) (let ((lang (nth 0 (org-babel-get-src-block-info)))) (if (string= lang "matlab") (if (region-active-p) (tdh-matlab-execute-selected (region-beginning) (region-end)) (progn (tdh-org-babel-execute-matlab-background))) (org-babel-next-src-block)) (if (string= lang "jupyter-python") (org-babel-execute-maybe) (org-babel-next-src-block)) ) (org-babel-next-src-block) ) ) #+end_src #+begin_src emacs-lisp (map! :after evil-org :map evil-org-mode-map :n "" #'tdh-ctrl-shift-ret) #+end_src ** Align Source Blocks #+begin_src emacs-lisp (defun tdh-align-src-block () (interactive) (defun tdh-in-src-block-p () "Returns t when the point is inside a source code block" (string= "src" (org-in-block-p '("src")))) (if (tdh-in-src-block-p) (progn (org-edit-special) (indent-region (point-min) (point-max)) (org-edit-src-exit)) (org-table-eval-formula))) #+end_src ** Helping Functions - Tangling =,b= Org-Babel Tangle Sub-tree #+begin_src emacs-lisp (defun tdh-org-babel-tangle-subtree () "Tangle the current subtree" (interactive) (progn (org-narrow-to-subtree) (org-babel-tangle) (widen)) ) #+end_src Org-Tangle and Org-Babel Jump to Tangle File #+begin_src emacs-lisp (defun tdh-org-babel-jump-to-tangle-file () "Jump to tangle file for the source block at point." (interactive) (let (file org-babel-pre-tangle-hook org-babel-post-tangle-hook) (cl-letf (((symbol-function 'write-region) (lambda (start end filename &rest _ignore) (setq file filename))) ((symbol-function 'delete-file) #'ignore)) (org-babel-tangle '(4))) (when file (setq file (expand-file-name file)) (if (file-readable-p file) (find-file file) (error "Cannot open tangle file %S" file))))) #+end_src #+begin_src emacs-lisp (defun tdh-org-babel-tangle-block () (interactive) (let ((current-prefix-arg '(4))) (call-interactively 'org-babel-tangle) )) #+end_src Map Functions #+begin_src emacs-lisp (after! org (map! :map org-mode-map (:prefix (",b" . "Tangle") :n "F" 'tdh-org-babel-jump-to-tangle-file :n "b" 'tdh-org-babel-tangle-block :n "T" 'tdh-org-babel-tangle-subtree))) #+end_src * Bibliography Management My bibliography management is mainly based on the following packages: - =org-ref= for nice citations - =org-noter= to annotate documents - =org-roam= to manage and links all my notes - =helm-bibtex= as an interface to easily find references - =org-roam-bibtex= that connects all the above packages ** Org Ref ([[https://github.com/jkitchin/org-ref][link]]) Nice Functions: - =org-ref-insert-ref-link= - =org-ref-helm-insert-cite-link= - =org-ref-list-of-figures= - =org-ref-find-bad-citations= - =org-ref-clean-bibtex-entry= #+begin_src emacs-lisp (use-package! org-ref :after org :config ;; Ox-Hugo configuration: https://ox-hugo.scripter.co/doc/org-ref-citations/ (setq org-hugo-link-desc-insert-type t) ;; Folder where the notes files are located (or file if just one Note file) (setq bibtex-completion-notes-path "~/Cloud/brain/") ;; Bibliography File (setq bibtex-completion-bibliography '("~/Cloud/brain/biblio/references.bib")) ;; Folder where all the pdf are located (setq bibtex-completion-library-path '("~/Cloud/pdfs/")) (setq org-ref-bibliography-entry-format '(("article" . "%a, %t, %j, v(%n), %p (%y).") ("book" . "%a, %t, %u (%y).") ("techreport" . "%a, %t, %i, %u (%y).") ("phdthesis" . "%a, %t (%y).") ("proceedings" . "%e, %t in %S, %u (%y).") ("inproceedings" . "%a, %t, %p, in %b, edited by %e, %u (%y)"))) ;; Tell org-ref to let helm-bibtex find notes for it (setq org-ref-notes-function (lambda (thekey) (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) (bibtex-completion-edit-notes (list (car (org-ref-get-bibtex-key-and-file thekey))))))) ;; Problem with speed: don't display broken links (setq org-ref-show-broken-links t) ;; Display information on the citation (setq org-ref-show-citation-on-enter t) ;; Remove hook that tries do get PDF each time... (remove-hook 'org-ref-clean-bibtex-entry-hook 'orcb-download-pdf) ;; (add-to-list 'org-ref-helm-user-candidates ;; '("Open pdf in Zathura" . (lambda () (call-process "zathura" nil 0 nil (concat ;; (file-name-as-directory org-ref-pdf-directory) ;; (car (org-ref-get-bibtex-key-and-file)) ;; ".pdf")))) ;; t) ;; (add-to-list 'org-ref-helm-user-candidates ;; '("Drag and Drop" . (lambda () (call-process "/bin/bash" nil 0 nil "-c" (concat ;; "dragon " ;; (file-name-as-directory org-ref-pdf-directory) ;; (car (org-ref-get-bibtex-key-and-file)) ;; ".pdf")))) ;; t) ;; Let Mathjax deals with equation reference ;; TODO - Will use an advice instead ;; (defun org-ref-eqref-export (keyword desc format) ;; (cond ;; ((eq format 'latex) (format "\\eqref{%s}" keyword)) ;; ((eq format 'html) (format "\\eqref{%s}" keyword)) ;; ((eq format 'md) (format "\\eqref{%s}" keyword)))) ;; Convert eqref:label to \eqref{label} (defun my/replace-eqref-with-ref (backend) "Replace eqref:label with \\ref{label} for HTML and Hugo export." (when (memq backend '(html html5 hugo)) (goto-char (point-min)) (while (re-search-forward "eqref:\\([a-zA-Z0-9:-_]+\\)" nil t) (replace-match "\\\\ref{\\1}")))) (add-hook 'org-export-before-processing-hook 'my/replace-eqref-with-ref) ;; Derived from org-ref-extract-bibtex-to-file to force the bibfile to have the same name than to org file, and take references from bibtex-completion-bibliography ;; this function can be added in the org-export-before-parsing-hook for instance (defun tdh-org-ref-extract-bibtex-to-file (&optional arg) "Extract all bibtex entries for citations buffer to BIBFILE. If BIBFILE exists, append, unless you use a prefix arg (C-u), which will CLOBBER the file." (interactive) (let* ((bibtex-files bibtex-completion-bibliography) (bibfile (file-name-nondirectory (concat (file-name-sans-extension (buffer-file-name)) ".bib"))) (keys (reverse (org-ref-get-bibtex-keys))) (bibtex-entry-kill-ring-max (length keys)) (bibtex-entry-kill-ring '()) (kill-cb (not (find-buffer-visiting bibfile))) (cb (find-file-noselect bibfile)) (current-bib-entries (with-current-buffer cb (prog1 (buffer-string) (when kill-cb (kill-buffer cb)))))) (save-window-excursion (cl-loop for key in keys do (bibtex-search-entry key t) (bibtex-kill-entry t))) (with-temp-file bibfile (insert (mapconcat 'identity bibtex-entry-kill-ring "\n\n"))))) ) #+end_src #+begin_src emacs-lisp (after! org (require 'org-ref)) #+end_src #+begin_src emacs-lisp (defun tdh-org-ref-open-pdf-at-point () "Open the pdf in external program for bibtex key under point if it exists." (interactive) (let* ((results (org-ref-get-bibtex-key-and-file)) (key (car results)) (pdf-file (funcall org-ref-get-pdf-filename-function key))) (if (file-exists-p pdf-file) (call-process "zathura" nil 0 nil pdf-file) (message "no pdf found for %s" key)))) ;; Open with Zathura by default (setq org-ref-open-pdf-function 'tdh-org-ref-open-pdf-at-point) #+end_src #+begin_src emacs-lisp (after! org (defun tdh-org-ref-import-pdf (doi file) (doi-utils-add-bibtex-entry-from-doi doi "~/Cloud/brain/biblio/references.bib") (save-excursion (find-file "~/Cloud/brain/biblio/references.bib") (goto-char (point-max)) (bibtex-beginning-of-entry) (let* ((bibtex-expand-strings t) (entry (bibtex-parse-entry t)) (key (cdr (assoc "=key=" entry))) pdf) (if (bibtex-completion-find-pdf-in-library key) (message (format "A file named %s already exists" (bibtex-completion-find-pdf-in-library key))) (setq pdf (expand-file-name (concat key ".pdf") (cond ((stringp bibtex-completion-library-path) bibtex-completion-library-path) ((and (listp bibtex-completion-library-path) (= 1 (length bibtex-completion-library-path))) (car bibtex-completion-library-path)) (t (completing-read "Dir: " bibtex-completion-library-path))))) (rename-file file pdf) (message (format "Created file %s" pdf)))))) ) #+end_src ** Org Noter ([[https://github.com/weirdNox/org-noter][link]]) #+begin_src emacs-lisp (use-package! org-noter :defer t :after (:any org pdf-view) :config (setq org-noter-always-create-frame nil) (setq org-noter-kill-frame-at-session-end nil) ;; Fraction of the frame that the document window will occupy when split (setq org-noter-doc-split-fraction '(0.6 . 0.6)) ;; Save the last visited location automatically; when starting a new session, go to that location (setq org-noter-auto-save-last-location nil) ;; Add an empty line between each note's heading and content (setq org-noter-separate-notes-from-heading t) ;; List of paths to check (non recursively) when searching for a notes file (setq org-noter-notes-search-path "~/Cloud/brain") (defun org-noter-init-pdf-view () (pdf-view-fit-page-to-window) (pdf-view-auto-slice-minor-mode) (run-at-time "0.5 sec" nil #'org-noter)) (add-hook 'pdf-view-mode-hook 'org-noter-init-pdf-view) (map! :map pdf-view-mode-map (:desc "Insert Note" :n "i" #'org-noter-insert-note)) ) #+end_src ** Capture Templates *** Bibliography #+begin_src org :tangle ~/.config/doom/capture-templates/ref.org :mkdirp yes - Tags :: %? - Reference :: ${ref} - Author(s) :: %^{author} - Year :: %^{year} ,* %^{author-abbrev} (%^{year}): %^{title} :%^{entry-type}:ignore: :PROPERTIES: :NOTER_DOCUMENT: ../pdfs/%^{citekey}.pdf :END: ,* Bibliography bibliography:./biblio/references.bib #+end_src *** Default #+begin_src org :tangle ~/.config/doom/capture-templates/default.org - Tags :: %? ,* Bibliography bibliography:./biblio/references.bib #+end_src ** Org Roam ([[https://github.com/jethrokuan/org-roam/][link]]) #+begin_src emacs-lisp (use-package! org-roam :custom-face (org-roam-link ((t (:inherit org-link :foreground "#cc241d")))) :config (setq org-roam-directory (file-truename "~/Cloud/brain/")) (make-directory org-roam-directory 'parents) (setq org-roam-completion-system 'helm) (setq org-roam-tag-sources '(prop last-directory)) (setq org-roam-capture-templates `(("d" "default" plain (file "~/.config/doom/capture-templates/default.org") :if-new (file+head "${slug}.org" "#+title: ${title}\n#+setupfile: ./setup/org-setup-file.org\n#+hugo_section: zettels\n\n") :unnarrowed t) ("r" "bibliography reference" plain (file "~/.config/doom/capture-templates/ref.org") :if-new (file+head "${citekey}.org" "#+title: ${title}\n#+setupfile: ./setup/org-setup-file.org\n#+hugo_section: ${entry-type}\n\n") :unnarrowed t))) ) #+end_src Automatic export of backlinks #+begin_src emacs-lisp (after! (org org-roam org-ref) ;; (defun tdh-org-roam--backlinks-list (file) ;; (when (org-roam--org-roam-file-p file) ;; (mapcar #'car (org-roam-db-query [:select :distinct [from] ;; :from links ;; :where (= to $s1) ;; :and from :not :like $s2] file "%private%")))) ;; (defun tdh-org-export-preprocessor (_backend) ;; (when-let ((links (tdh-org-roam--backlinks-list (buffer-file-name)))) ;; (insert "\nBacklinks:\n") ;; (dolist (link links) ;; (insert (format "- [[file:%s][%s]]\n" ;; (file-relative-name link org-roam-directory) ;; (org-roam--get-title-or-slug link)))))) ;; (add-hook 'org-export-before-processing-hook #'tdh-org-export-preprocessor) ) #+end_src Correctly export references for Hugo blog. #+begin_src emacs-lisp (after! (org org-roam org-ref) ;; Citation processing for org-ref (defun tdh-org-export-org-ref-preprocessor--html (backend) "Preprocess `org-ref' citations to HTML format." (when (org-export-derived-backend-p backend 'html) (org-ref-process-buffer 'html))) (add-hook 'org-export-before-processing-hook #'tdh-org-export-org-ref-preprocessor--html) ) #+end_src Re-Export all roam files. #+begin_src emacs-lisp (defun tdh-org-roam-export-all () "Re-exports all Org-roam files to Hugo markdown." (interactive) (dolist (f (org-roam--list-files "~/Cloud/brain/")) (with-current-buffer (find-file f) (when (s-contains? "SETUPFILE" (buffer-string)) (org-hugo-export-wim-to-md))))) #+end_src ** Helm-Bibtex ([[https://github.com/tmalsburg/helm-bibtex][link]]) #+begin_src emacs-lisp (use-package! helm-bibtex :after-call helm-bibtex :init :config ;; Bibliography file (setq bibtex-completion-bibliography '("~/Cloud/brain/biblio/references.bib")) ;; Directory with all the pdfs (setq bibtex-completion-library-path '("~/Cloud/pdfs/")) ;; Directory with notes files (setq bibtex-completion-notes-path "~/Cloud/brain/") (setq bibtex-completion-notes-extension ".org") (setq bibtex-completion-pdf-extension '(".pdf" ".djvu")) (setq bibtex-completion-additional-search-fields '(keywords)) ;; Use "keywords" field when looking for bib entries (setq helm-bibtex-additional-search-fields '(keywords)) (setq helm-bibtex-full-frame nil) ;; Display of bibtex entries with helm (setq bibtex-completion-display-formats '((t . "${author:36} ${title:*} ${year:4} ${=type=:7} ${=has-note=:1}"))) ;; Special symbols for notes and pdf (setq bibtex-completion-pdf-symbol "⌘") (setq bibtex-completion-notes-symbol "✎") ;; custom function for helm-bibtex (defun tdh-bibtex-completion-format-citation-cite (keys) "Format cite references for keys in KEYS." (s-join ", " (--map (format "cite:%s" it) keys))) (setq bibtex-completion-format-citation-functions '((org-mode . tdh-bibtex-completion-format-citation-cite) (latex . bibtex-completion-format-citation-cite) (default . bibtex-completion-format-citation-default))) ;; Template used when creating new Note file (setq bibtex-completion-notes-template-multiple-files (concat "#+title: ${title}\n" "#+setupfile: ./setup/org-setup-file.org\n" "#+hugo_section: ${=type=}\n" "#+roam_key: ${=key=}\n" "#+hugo_draft: true\n" "\n" "- Tags ::\n" "- Reference :: cite:${=key=}\n" "- Author(s) :: ${author}\n" "- Year :: ${year}\n" "\n" "* ${author-abbrev} (${year}): ${title} :${=type=}:ignore:\n" ":PROPERTIES:\n" ":NOTER_DOCUMENT: ../pdfs/${=key=}.pdf\n" ":END:\n" "\n" "* Bibliography :ignore:\n" "bibliography:./biblio/references.bib" )) ;; Make "Edit notes" the default action (helm-delete-action-from-source "Edit notes" helm-source-bibtex) (helm-add-action-to-source "Edit notes" 'helm-bibtex-edit-notes helm-source-bibtex 0) (helm-delete-action-from-source "Open PDF Externally" helm-source-bibtex) (helm-add-action-to-source "Open PDF Externally" 'tdh-open-pdf-externally helm-source-bibtex 1) (helm-add-action-to-source "Insert Link to Note" 'tdh-insert-link-to-note helm-source-bibtex 2) (helm-add-action-to-source "Insert E-Reader Link" 'tdh-insert-link-to-pdf-entry helm-source-bibtex 3) ) #+end_src #+begin_src emacs-lisp (defun tdh-insert-link-to-pdf-entry (key) "Insert a link to a pdf associated with the bibtex entry." (let* ((entry (bibtex-completion-get-entry key)) (title (bibtex-completion-get-value "title" entry))) (insert (concat "[[file:Download/" key ".pdf][" title "]] (cite:" key ")")) ) ) #+end_src #+begin_src emacs-lisp (defun tdh-insert-link-to-note (key) "Insert a link to a note associated with the bibtex entry." (if (and bibtex-completion-notes-path (f-directory? bibtex-completion-notes-path)) (let* ((path (f-join bibtex-completion-notes-path (s-concat key bibtex-completion-notes-extension)))) (if (file-exists-p path) (insert (concat "[[file:" (file-relative-name path) "][Notes]]")) (message "No note file associated")) ))) #+end_src Open pdf externally #+begin_src emacs-lisp (defun tdh-open-pdf-externally (key) (call-process "zathura" nil 0 nil (nth 0 (-cons-to-list (bibtex-completion-find-pdf key))))) #+end_src Special Commands #+begin_src emacs-lisp (defun tdh-helm-bibtex-favorites (&optional arg) "Search Favorite BibTeX entries" (interactive "P") (helm-bibtex arg nil "favorite ")) #+end_src List all element of the bibliography without pdf associated #+begin_src emacs-lisp (defun tdh-list-bib-without-pdf-associated () (interactive) (bibtex-completion-init) (setq candidates (bibtex-completion-candidates)) (defun canditate-is-pdf-present (candidate) (bibtex-completion-find-pdf-in-library (cdr (assoc "=key=" candidate))) ) (setq candidates-without-pdf (remove-if #'canditate-is-pdf-present candidates)) (setq candidate-without-pdf-names (mapcar (lambda (x) (cdr (assoc "title" x))) candidates-without-pdf)) (with-output-to-temp-buffer "*bib-without-pdf*" (princ (string-join candidate-without-pdf-names "\n"))) (switch-to-buffer-other-window "*bib-without-pdf*") ) #+end_src ** Org-Roam-Bibtex ([[https://github.com/org-roam/org-roam-bibtex][link]]) Provides nice functions such as: - =orb-find-non-ref-file= - =orb-insert-non-ref= - =orb-note-action= #+begin_src emacs-lisp (use-package! org-roam-bibtex :after org-roam :config (setq orb-preformat-keywords '("citekey" "title" "author" "year" "author-abbrev" "entry-type")) (setq orb-note-actions-user '(("Open with Zathura" . tdh-open-bib-with-zathura))) ) #+end_src #+begin_src emacs-lisp (defun tdh-open-bib-with-zathura (key) "Open the pdf corresponding to the reference KEY with Zathura" (if (listp key) (setq key (car key))) (call-process "zathura" nil 0 nil (org-ref-get-pdf-filename key))) #+end_src ** Bibtex-Mode #+begin_src emacs-lisp (after! bibtex (map! :map bibtex-mode-map :n "C-c c" 'org-ref-clean-bibtex-entry) (setq bibtex-files bibtex-completion-bibliography)) #+end_src ** Citar #+begin_src emacs-lisp ;; (use-package! citar ;; :custom ;; (org-cite-global-bibliography '("~/Cloud/brain/biblio/references.bib")) ;; (setq citar-library-paths '("~/Cloud/pdfs/")) ;; (setq citar-open-note-function 'orb-citar-edit-note) ;; (org-cite-insert-processor 'citar) ;; (org-cite-follow-processor 'citar) ;; (org-cite-activate-processor 'citar)) #+end_src * LaTeX - https://tex.stackexchange.com/questions/52179/what-is-your-favorite-emacs-and-or-auctex-command-trick - https://tex.stackexchange.com/questions/20843/useful-shortcuts-or-key-bindings-or-predefined-commands-for-emacsauctex ** Basic Config #+begin_src emacs-lisp (after! auctex (setq +latex-viewers '(zathura pdf-tools))) #+end_src ** Bibtex #+begin_src emacs-lisp (use-package! bibtex :config (bibtex-set-dialect 'BibTeX)) #+end_src * Matlab - https://sourceforge.net/projects/matlab-emacs/ ** Setup Matlab Mode #+begin_src emacs-lisp (setq matlab-shell-command "~/.local/bin/matlab") (setq matlab-shell-command-switches (list "-softwareopengl -nodesktop -nosplash")) (setq matlab-indent-function t) (setq mlint-programs '("mlint" "~/.local/bin/mlint")) #+end_src ** Setup Flycheck to work with =mlint= #+begin_src emacs-lisp (defvar mlint-executable "~/.local/bin/mlint") (flycheck-define-command-checker 'matlab-mlint "A Matlab checker based on mlint." :command `(,mlint-executable source) :error-patterns '((warning line-start "L " line " (C " (1+ digit) "): " (message) line-end)) :modes '(matlab-mode)) (add-to-list 'flycheck-checkers 'matlab-mlint) ;; Automatic startup of flycheck for matlab (add-hook 'matlab-mode-hook 'flycheck-mode) #+end_src ** Completion in the Matlab Shell #+begin_src emacs-lisp ;; (map! :map matlab-shell-mode-map ;; :i "" 'matlab-shell-c-tab) (map! :map matlab-shell-mode-map :i "" #'matlab-shell-tab) #+end_src #+begin_src emacs-lisp (defadvice! inhibit-real-only-a (oldfun &rest r) "Temporary remove read-only lines in shell buffer" :around#'matlab-shell-collect-command-output (let ((inhibit-read-only t)) (apply oldfun r))) #+end_src ** Beautify code #+begin_src emacs-lisp (defun tdh-matlab-beautify-buffer () "Beautify Current Matlab Buffer" (interactive) ;; First verifies is the current file is a Matlab file (if (string= (file-name-extension (buffer-file-name)) "m") (progn (save-buffer) (matlab-shell-run-command (concat "MBeautify.formatFileNoEditor(\"" (buffer-file-name) "\", \"" (buffer-file-name) "\")")) (revert-buffer :ignore-auto :noconfirm)) (message "Current buffer is not a matlab file") ) ) #+end_src ** Key Bindings #+begin_src emacs-lisp (defun tdh-matlab-add-breakpoint () (interactive) (matlab-shell-run-command (concat "dbstop in " (buffer-name) " at " (number-to-string (line-number-at-pos nil))))) (defun tdh-matlab-remove-breakpoint () (interactive) (matlab-shell-run-command (concat "dbclear in " (buffer-name) " at " (number-to-string (line-number-at-pos nil))))) (defun tdh-matlab-list-breakpoints () (interactive) (matlab-shell-run-command (concat "dbstatus " (buffer-name)))) (defun tdh-matlab-clear-breakpoints () (interactive) (matlab-shell-run-command (concat "dbclear in " (buffer-name)))) (defun tdh-matlab-no-debug-on-error () (interactive) (matlab-shell-run-command (concat "dbclear if error"))) (defun tdh-matlab-debug-on-error () (interactive) (matlab-shell-run-command (concat "dbstop if error"))) (defun tdh-matlab-go-to-file-directory () (interactive) (matlab-shell-run-command (concat "cd " (file-name-directory buffer-file-name)))) #+end_src #+begin_src emacs-lisp (map! :map matlab-mode-map (:prefix ("," . "prefix") :n "g" 'tdh-matlab-go-to-file-directory (:prefix ("d" . "Debug") :n "de" 'tdh-matlab-debug-on-error :n "dE" 'tdh-matlab-no-debug-on-error :n "da" 'tdh-matlab-add-breakpoint :n "dr" 'tdh-matlab-remove-breakpoint :n "dL" 'tdh-matlab-list-breakpoints :n "dc" 'tdh-matlab-clear-breakpoints :n "dl" 'gud-cont :n "ds" 'gud-step :n "dn" 'gud-next :n "dq" 'gud-finish))) #+end_src ** Useful General Functions #+begin_src emacs-lisp (defun tdh-matlab-work () "Setup Matlab Work Windows" (interactive) (delete-other-windows) (evil-window-vsplit) (evil-window-right 1) (switch-to-buffer "*MATLAB*") (evil-normal-state) (evil-goto-line) (evil-window-left 1) ) #+end_src * Doom =init.el= #+begin_src emacs-lisp :tangle ~/.config/doom/init.el (doom! :completion company ; the ultimate code completion backend (corfu +orderless) ; complete with cap(f), cape and a flying feather! helm ; the *other* search engine for love and life ;;ido ; the other *other* search engine... ;;ivy ; a search engine for love and life vertico ; the search engine of the future :ui doom ; what makes DOOM look the way it does (emoji +unicode) ; 🙂 hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW indent-guides ; highlighted indent columns modeline ; snazzy, Atom-inspired modeline, plus API ophints ; highlight the region an operation acts on (popup +defaults) ; tame sudden yet inevitable temporary windows ;;smooth-scroll ; So smooth you won't believe it's not butter unicode ; extended unicode support for various languages (vc-gutter +pretty) ; vcs diff in the fringe vi-tilde-fringe ; fringe tildes to mark beyond EOB workspaces ; tab emulation, persistence & separate workspaces :editor (evil +everywhere); come to the dark side, we have cookies file-templates ; auto-snippets for empty files fold ; (nigh) universal code folding ;;(format +onsave) ; automated prettiness ;;god ; run Emacs commands without modifier keys ;;lispy ; vim for lisp, for people who don't like vim ;;multiple-cursors ; editing in many places at once ;;objed ; text object editing for the innocent ;;parinfer ; turn lisp into python, sort of ;;rotate-text ; cycle region at point between text candidates snippets ; my elves. They type so I don't have to word-wrap ; soft wrapping with language-aware indent :emacs dired ; making dired pretty [functional] electric ; smarter, keyword-based electric-indent ibuffer ; interactive buffer management undo ; persistent, smarter undo for your inevitable mistakes vc ; version-control and Emacs, sitting in a tree :term eshell ; the elisp shell that works everywhere ;;shell ; simple shell REPL for Emacs ;;term ; basic terminal emulator for Emacs vterm ; the best terminal emulation in Emacs :checkers syntax ; tasing you for every semicolon you forget (spell +aspell +everywhere) ; tasing you for misspelling mispelling :tools ;;ansible biblio ; Writes a PhD for you (citation needed) ;;collab ; buffers with friends debugger ; FIXME stepping through code, to help you add bugs ;;direnv ;;docker ;;editorconfig ; let someone else argue about tabs vs spaces ;;ein ; tame Jupyter notebooks with emacs (eval +overlay) ; run code, run (also, repls) (lookup +dictionary) ; navigate your code and its documentation ;;lsp ; M-x vscode magit ; a git porcelain for Emacs ;;make ; run make tasks from Emacs ;;pass ; password manager for nerds pdf ; pdf enhancements ;;terraform ; infrastructure as code ;;tmux ; an API for interacting with tmux ;;tree-sitter ; syntax and parsing, sitting in a tree... ;;upload ; map local to remote projects via ssh/ftp :os ;;(:if (featurep :system 'macos) macos) ; improve compatibility with macOS ;;tty ; improve the terminal Emacs experience :lang ;;agda ; types of types of types of types... ;;beancount ; mind the GAAP ;;(cc +lsp) ; C > C++ == 1 ;;clojure ; java with a lisp ;;common-lisp ; if you've seen one lisp, you've seen them all ;;coq ; proofs-as-programs ;;crystal ; ruby at the speed of c ;;csharp ; unity, .NET, and mono shenanigans data ; config/data formats ;;(dart +flutter) ; paint ui and not much else ;;dhall ;;elixir ; erlang done right ;;elm ; care for a cup of TEA? emacs-lisp ; drown in parentheses ;;erlang ; an elegant language for a more civilized age ;;ess ; emacs speaks statistics ;;factor ;;faust ; dsp, but you get to keep your soul ;;fortran ; in FORTRAN, GOD is REAL (unless declared INTEGER) ;;fsharp ; ML stands for Microsoft's Language ;;fstar ; (dependent) types and (monadic) effects and Z3 ;;gdscript ; the language you waited for ;;(go +lsp) ; the hipster dialect ;;(graphql +lsp) ; Give queries a REST ;;(haskell +lsp) ; a language that's lazier than I am ;;hy ; readability of scheme w/ speed of python ;;idris ; a language you can depend on ;;json ; At least it ain't XML ;;(java +lsp) ; the poster child for carpal tunnel syndrome ;;javascript ; all(hope(abandon(ye(who(enter(here)))))) ;;julia ; a better, faster MATLAB ;;kotlin ; a better, slicker Java(Script) latex ; writing papers in Emacs has never been so fun ;;lean ; for folks with too much to prove ;;ledger ; be audit you can be ;;lua ; one-based indices? one-based indices markdown ; writing docs for people to ignore ;;nim ; python + lisp at the speed of c ;;nix ; I hereby declare "nix geht mehr!" ;;ocaml ; an objective camel (org +pretty +roam2 +hugo +noter) ; organize your plain life in plain text ;;php ; perl's insecure younger brother ;;plantuml ; diagrams for confusing people more ;;graphviz ; diagrams for confusing yourself even more ;;purescript ; javascript, but functional python ; beautiful is better than ugly ;;qt ; the 'cutest' gui framework ever ;;racket ; a DSL for DSLs ;;raku ; the artist formerly known as perl6 ;;rest ; Emacs as a REST client ;;rst ; ReST in peace ;;(ruby +rails) ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} ;;(rust +lsp) ; Fe2O3.unwrap().unwrap().unwrap().unwrap() ;;scala ; java, but good ;;(scheme +guile) ; a fully conniving family of lisps sh ; she sells {ba,z,fi}sh shells on the C xor ;;sml ;;solidity ; do you need a blockchain? No. ;;swift ; who asked for emoji variables? ;;terra ; Earth and Moon in alignment for performance. ;;web ; the tubes ;;yaml ; JSON, but readable ;;zig ; C, but simpler :email ;;(mu4e +org +gmail) ;;notmuch ;;(wanderlust +gmail) :app ;;calendar ;;emms ;;everywhere ; *leave* Emacs!? You must be joking ;;irc ; how neckbeards socialize ;;(rss +org) ; emacs as an RSS reader :config literate (default +bindings +smartparens)) #+end_src * Doom =packages.el= :PROPERTIES: :header-args:emacs-lisp: :tangle ~/.config/doom/packages.el :END: ** Org Mode Related https://github.com/doomemacs/doomemacs/issues/6478 #+begin_src emacs-lisp ;; Automatic toggling of LaTeX fragments (package! org-fragtog) #+end_src #+begin_src emacs-lisp ;; Toggle visibility of hidden Org mode element parts upon entering and leaving an element (package! org-appear) #+end_src #+begin_src emacs-lisp ;; Connector between Org-roam, BibTeX-completion, and Org-ref (package! org-roam-bibtex :recipe (:host github :repo "org-roam/org-roam-bibtex")) (unpin! org-roam company-org-roam) #+end_src #+begin_src emacs-lisp ;; Org-mode modules for citations, cross-references, bibliographies (package! org-ref) #+end_src #+begin_src emacs-lisp ;; Org-mode calendar sync (package! org-caldav) #+end_src #+begin_src emacs-lisp ;; Alert notifications for org-agenda (package! org-wild-notifier) #+end_src #+begin_src emacs-lisp ;; Turn table into subfigure (package! ox-latex-subfigure :recipe (:host github :repo "tdehaeze/ox-latex-subfigure")) #+end_src #+begin_src emacs-lisp ;; Org-mode query language (package! org-ql :recipe (:host github :repo "alphapapa/org-ql" :files ("*.el") )) ;; (package! helm-org-ql) #+end_src ** Other #+begin_src emacs-lisp ;; Nice theme (package! poet-theme) #+end_src #+begin_src emacs-lisp :tangle no ;; Major Mode for Matlab (package! matlab-mode :recipe (:host github :repo "matlab-mode/mirror") :pin "f1a709e") #+end_src #+begin_src emacs-lisp ;; Major Mode for Matlab (package! matlab-mode :recipe (:host github :repo "mathworks/Emacs-MATLAB-Mode")) #+end_src #+begin_src emacs-lisp (package! org-xournalpp :recipe (:host gitlab :repo "vherrmann/org-xournalpp" :files ("resources" "*.el"))) #+end_src ** Not used anymore :noexport: :PROPERTIES: :header-args:emacs-lisp: :tangle no :END: #+begin_src emacs-lisp ;; Web Server (package! web-server) #+end_src #+begin_src emacs-lisp (package! mpv) #+end_src #+begin_src emacs-lisp (package! pretty-hydra) #+end_src #+begin_src emacs-lisp ;; custom blocks and links for org-mode (package! org-special-block-extras) #+end_src #+begin_src emacs-lisp ;; Import file to Org-mode (package! org-pandoc-import :recipe (:host github :repo "tecosaur/org-pandoc-import" :files ("*.el" "filters" "preprocessors"))) #+end_src #+begin_src emacs-lisp (package! org-media-note :recipe (:host github :repo "yuchen-lea/org-media-note")) #+end_src #+begin_src emacs-lisp (package! igo-org :recipe (:host github :repo "misohena/el-igo" :branch "master" :files ("*.el"))) #+end_src #+begin_src emacs-lisp (package! org-transclusion :recipe (:host github :repo "nobiot/org-transclusion" :branch "main" :files ("*.el"))) #+end_src Why this was pinned? #+begin_src emacs-lisp ;; (package! org-mode :pin "971eb6885ec996c923e955730df3bafbdc244e54") #+end_src #+begin_src emacs-lisp ;; Nice theme (package! languagetool) #+end_src #+begin_src emacs-lisp ;; Don't use this default package in Doom (package! evil-escape :disable t) #+end_src #+begin_src emacs-lisp ;; Nice gantt charts (package! ob-mermaid) #+end_src #+begin_src emacs-lisp ;; Vimrc (package! vimrc-mode) (package! transient :pin "c2bdf7e12c530eb85476d3aef317eb2941ab9440") (package! with-editor :pin "391e76a256aeec6b9e4cbd733088f30c677d965b") #+end_src #+begin_src emacs-lisp (package! org-ai) #+end_src