Browse Source

Emacs: Split up config into separate modules

master
Riyyi 2 years ago
parent
commit
0288dbf58f
  1. 1258
      .config/emacs/config.org
  2. 406
      .config/emacs/config/development.org
  3. 105
      .config/emacs/config/evil.org
  4. 157
      .config/emacs/config/mail.org
  5. 328
      .config/emacs/config/org-mode.org
  6. 46
      .config/emacs/config/selection.org
  7. 261
      .config/emacs/config/ui.org

1258
.config/emacs/config.org

File diff suppressed because it is too large Load Diff

406
.config/emacs/config/development.org

@ -0,0 +1,406 @@
#+TITLE: Development
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#company][Company]]
- [[#git][Git]]
- [[#projectile][Projectile]]
- [[#languages][Languages]]
- [[#language-server-support][Language Server Support]]
- [[#debug-adapter-support][Debug Adapter Support]]
- [[#cc][C/C++]]
- [[#cmake][CMake]]
- [[#glsl][GLSL]]
- [[#html][HTML]]
- [[#kotlin][Kotlin]]
- [[#lua][Lua]]
- [[#php][PHP]]
- [[#python][Python]]
- [[#yaml][YAML]]
- [[#quality-of-life][Quality of Life]]
- [[#flycheck][Flycheck]]
- [[#flyspell][Flyspell]]
- [[#rainbow-delimiters][Rainbow Delimiters]]
- [[#rainbow-mode][Rainbow Mode]]
- [[#yasnippet][YASnippet]]
** Company
#+BEGIN_SRC emacs-lisp
(use-package company
:hook
((c-mode-common
emacs-lisp-mode
latex-mode
org-mode
php-mode
shell-mode
shell-script-mode)
. company-mode)
:config
(setq company-idle-delay 0.2)
(setq company-minimum-prefix-length 2)
(setq company-show-numbers t)
(setq company-tooltip-align-annotations 't))
#+END_SRC
Sort Company completions.
#+BEGIN_SRC emacs-lisp
(use-package company-prescient
:after (company prescient)
:config (company-prescient-mode))
#+END_SRC
Auto-completion for C/C++ headers.
#+BEGIN_SRC emacs-lisp
(use-package company-c-headers
:after company
:config (add-to-list 'company-backends 'company-c-headers))
#+END_SRC
GLSL integration with company requires the package: ~glslang~.
#+BEGIN_SRC emacs-lisp
(when (executable-find "glslangValidator")
(use-package company-glsl
:after company
:config (add-to-list 'company-backends 'company-glsl)))
#+END_SRC
** Git
#+BEGIN_SRC emacs-lisp
(use-package diff-hl
:demand
:hook (prog-mode . turn-on-diff-hl-mode)
:hook (prog-mode . dot/diff-hl-enable-flydiff-and-fringe)
:config
(defun dot/diff-hl-enable-flydiff-and-fringe ()
"Enable on the fly diff checking if file is under version control."
(let ((buffer buffer-file-name))
(when (and buffer (vc-registered buffer))
(diff-hl-flydiff-mode)
(dot/toggle-fringe 1)))))
(use-package transient
:defer t
:config (setq transient-history-file (concat dot-cache-dir "/transient/history.el")))
(use-package magit
:after (diff-hl transient)
:hook (git-commit-setup . git-commit-turn-on-auto-fill)
:hook (git-commit-setup . git-commit-turn-on-flyspell)
:hook (magit-pre-refresh . diff-hl-magit-pre-refresh)
:hook (magit-post-refresh . diff-hl-magit-post-refresh)
:config
(setq git-commit-fill-column 72)
(setq git-commit-summary-max-length 70)
(setq magit-completing-read-function #'selectrum-completing-read)
(setq magit-diff-paint-whitespace-lines 'both)
(setq magit-repository-directories '(("~/dotfiles" . 0)
("~/code" . 3)))
(put 'magit-log-select-pick :advertised-binding [?\M-c])
(put 'magit-log-select-quit :advertised-binding [?\M-k]))
#+END_SRC
** Projectile
Project manager.
#+BEGIN_SRC emacs-lisp
(use-package projectile
:defer t
:config
(setq projectile-cache-file (concat dot-cache-dir "/projectile.cache"))
(setq projectile-completion-system 'default)
(setq projectile-enable-caching t)
(setq projectile-indexing-method 'hybrid)
(setq projectile-known-projects-file (concat dot-cache-dir "/projectile-bookmarks.eld"))
(setq projectile-project-search-path '("~"))
(setq projectile-sort-order 'recentf)
(defun dot/find-project-root ()
"Return root of the project, determined by `.git/' and `.projectile',
`default-directory' otherwise."
(let ((search-directory (projectile-project-root)))
(if search-directory
search-directory
default-directory)))
(defun dot/find-file-in-project-root ()
"Find file in project root."
(interactive)
(let ((default-directory (dot/find-project-root)))
(call-interactively 'find-file)))
(projectile-mode))
#+END_SRC
** Languages
*** Language Server Support
Language Server Protocol.
#+BEGIN_SRC emacs-lisp
(use-package lsp-mode
:commands lsp
:after which-key
:hook
((c-mode ; clangd
c++-mode ; clangd
lua-mode ; lua-language-server
php-mode ; nodejs-intelephense
latex-mode ; texlab
kotlin-mode ; kotlin-language-server
web-mode)
. lsp-deferred)
:config
(setq lsp-auto-guess-root t)
(setq lsp-clients-clangd-args '("-j=2"
"--background-index"
"--clang-tidy"
"--compile-commands-dir=build"
"--log=error"
"--pch-storage=memory"))
(setq lsp-clients-lua-language-server-install-dir "/usr/share/lua-language-server/")
(setq lsp-clients-lua-language-server-bin "/usr/bin/lua-language-server")
(setq lsp-enable-xref t)
(setq lsp-headerline-breadcrumb-enable nil)
(setq lsp-intelephense-storage-path (concat dot-cache-dir "/lsp-cache"))
(setq lsp-keep-workspace-alive nil)
(setq lsp-prefer-flymake nil)
(setq lsp-session-file (concat dot-cache-dir "/lsp-session-v1"))
;; Mark clangd args variable as safe to modify via .dir-locals.el
(put 'lsp-clients-clangd-args 'safe-local-variable #'listp)
;; Enable which-key descriptions
(dolist (leader-key (list dot/leader-key dot/leader-alt-key))
(let ((lsp-keymap-prefix (concat leader-key " l")))
(lsp-enable-which-key-integration)))
(defun lsp-format-buffer-or-region ()
"Format the selection (or buffer) with LSP."
(interactive)
(unless (bound-and-true-p lsp-mode)
(message "Not in an LSP buffer"))
(call-interactively
(if (use-region-p)
#'lsp-format-region
#'lsp-format-buffer))))
;; TODO: add lsp-signature keybinds
(use-package lsp-ui
:commands lsp-ui-mode
:after (flycheck lsp-mode)
:config
(setq lsp-ui-doc-border (face-foreground 'default))
(setq lsp-ui-doc-delay 0.5)
(setq lsp-ui-doc-enable t)
(setq lsp-ui-doc-header t)
(setq lsp-ui-doc-include-signature t)
(setq lsp-ui-doc-position 'top)
(setq lsp-ui-doc-use-childframe t)
(setq lsp-ui-flycheck-list-position 'right)
(setq lsp-ui-imenu-enable nil)
(setq lsp-ui-peek-enable nil)
(setq lsp-ui-sideline-enable nil))
#+END_SRC
*** Debug Adapter Support
Debug Adapter Protocol.
#+BEGIN_SRC emacs-lisp
(use-package treemacs
:after all-the-icons
:hook (treemacs-mode . dot/hook-disable-line-numbers)
:config (setq treemacs-persist-file (concat dot-cache-dir "/treemacs/persist")))
(use-package dap-mode
:after (treemacs lsp-mode)
:hook (lsp-after-initialize . dot/dap-install-debug-adapters)
:config
(setq dap-auto-configure-features '(sessions locals expressions controls tooltip))
(setq dap-breakpoints-file (concat dot-cache-dir "/dap/breakpoints"))
(setq dap-utils-extension-path (concat dot-cache-dir "/dap"))
;; Create dap extension directory
(unless (file-directory-p dap-utils-extension-path)
(make-directory dap-utils-extension-path t))
(defun dot/dap-install-debug-adapters ()
"Install and Load debug adapters."
(interactive)
(unless (bound-and-true-p lsp-mode)
(user-error "Not in an LSP buffer"))
(when (string-equal major-mode "c++-mode")
(require 'dap-cpptools)
(dap-cpptools-setup))))
#+END_SRC
*** C/C++
#+BEGIN_SRC emacs-lisp
(use-package c-mode
:ensure nil
:defer t
;; C++ // line comment style in c-mode
:hook (c-mode . (lambda ()
(c-toggle-comment-style -1))))
#+END_SRC
*** CMake
#+BEGIN_SRC emacs-lisp
(use-package cmake-mode
:config (setq cmake-tab-width 4)
:defer t)
#+END_SRC
*** GLSL
#+BEGIN_SRC emacs-lisp
(use-package glsl-mode
:defer t)
#+END_SRC
*** HTML
#+BEGIN_SRC emacs-lisp
(use-package web-mode
:defer t)
#+END_SRC
*** Kotlin
#+BEGIN_SRC emacs-lisp
(use-package kotlin-mode
:defer t)
#+END_SRC
*** Lua
#+BEGIN_SRC emacs-lisp
(use-package lua-mode
:defer t
:config (setq lua-indent-level 4))
#+END_SRC
*** PHP
#+BEGIN_SRC emacs-lisp
(use-package php-mode
:defer t
:hook
(php-mode . (lambda ()
(setq indent-tabs-mode t))))
(use-package restclient
:defer t)
#+END_SRC
*** Python
#+BEGIN_SRC emacs-lisp
(use-package python-mode
:ensure nil
:defer t
:hook (python-mode . (lambda ()
(setq indent-tabs-mode t)
(setq python-indent-offset 4)
(setq tab-width 4))))
#+END_SRC
*** YAML
#+BEGIN_SRC emacs-lisp
(use-package yaml-mode
:defer t)
#+END_SRC
** Quality of Life
**** Flycheck
On the fly syntax checking.
#+BEGIN_SRC emacs-lisp
(use-package flycheck
:hook
((c-mode-common
emacs-lisp-mode
latex-mode
org-mode
php-mode
sh-mode
shell-mode
shell-script-mode)
. flycheck-mode)
:config
(setq flycheck-clang-language-standard "c++17")
(setq flycheck-gcc-language-standard "c++17"))
;; For .el files which are intended to be packages
(use-package flycheck-package
:after flycheck
:config
(add-to-list 'flycheck-checkers 'flycheck-emacs-lisp-package)
(flycheck-package-setup))
(use-package flycheck-clang-tidy
:after flycheck
:hook (flycheck-mode . flycheck-clang-tidy-setup)
:config (setq flycheck-clang-tidy-extra-options "--format-style=file"))
#+END_SRC
**** Flyspell
Give Flyspell a selection menu.
#+BEGIN_SRC emacs-lisp
(use-package flyspell-correct
:after flyspell
:demand
:hook (org-mode . flyspell-mode)
:config
(setq flyspell-issue-message-flag nil)
(setq flyspell-issue-welcome-flag nil))
#+END_SRC
**** Rainbow Delimiters
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
#+END_SRC
**** Rainbow Mode
#+BEGIN_SRC emacs-lisp
(use-package rainbow-mode
:hook (css-mode . rainbow-mode))
#+END_SRC
**** YASnippet
#+BEGIN_SRC emacs-lisp
(use-package yasnippet
:defer t
:init
(setq yas-snippet-dirs (list (concat dot-emacs-dir "/snippets")))
(setq yas-prompt-functions '(yas-completing-prompt))
:config
(yas-global-mode))
(use-package yasnippet-snippets
:after yasnippet)
#+END_SRC
https://stackoverflow.com/questions/22735895/configuring-a-yasnippet-for-two-scenarios-1-region-is-active-2-region-is

105
.config/emacs/config/evil.org

@ -0,0 +1,105 @@
#+TITLE: Evil
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#evil][Evil]]
** Evil
Evil mode and related packages.
#+BEGIN_SRC emacs-lisp
(use-package undo-tree
:config (global-undo-tree-mode))
(use-package goto-chg)
(use-package evil
:after (undo-tree goto-chg)
:init
(setq evil-ex-complete-emacs-commands nil)
(setq evil-kill-on-visual-paste nil)
(setq evil-operator-state-cursor 'box) ; Do not set half cursor
(setq evil-search-module 'evil-search)
(setq evil-split-window-below t)
(setq evil-undo-system 'undo-tree)
(setq evil-vsplit-window-right t)
(setq evil-want-C-u-scroll t)
(setq evil-want-Y-yank-to-eol t)
(setq evil-want-keybinding nil) ; Needed by evil-collection
:config
(defun dot/evil-normal-sort-paragraph ()
"Sort paragraph cursor is under.
Vim equivalence: vip:sort<CR>"
(interactive)
(let ((p (point)))
(evil-visual-char)
(call-interactively 'evil-inner-paragraph)
(evil-ex-sort (region-beginning) (region-end))
(goto-char p)))
(defun dot/evil-insert-shift-left ()
"Shift line left, retains cursor position.
Vim equivalence: <C-D>"
(interactive)
(evil-shift-left-line 1))
(defun dot/evil-insert-shift-right ()
"Shift line right, retains cursor position.
Vim equivalence: <Tab>"
(interactive)
(insert "\t"))
(defun dot/evil-visual-shift-left ()
"Shift visual selection left, retains the selection.
Vim equivalence: <gv"
(interactive)
(evil-shift-left (region-beginning) (region-end))
(funcall (evil-visual-restore)))
(defun dot/evil-visual-shift-right ()
"Shift visual selection left, retains the selection.
Vim equivalence: >gv"
(interactive)
(evil-shift-right (region-beginning) (region-end))
(funcall (evil-visual-restore)))
(evil-mode))
#+END_SRC
Evil command aliases.
#+BEGIN_SRC emacs-lisp
(use-package evil-ex
:ensure nil ; evil-ex.el is part of evil
:after evil
:config
(evil-ex-define-cmd "W" "w")
(evil-ex-define-cmd "Q" "q")
(evil-ex-define-cmd "WQ" "wq")
(evil-ex-define-cmd "Wq" "wq"))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package evil-collection
:after evil
:init
(setq evil-collection-company-use-tng nil)
(setq evil-collection-key-blacklist (list dot/leader-key dot/localleader-key
dot/leader-alt-key dot/localleader-alt-key
"M-h" "M-j" "M-k" "M-l"))
(setq evil-collection-setup-minibuffer t)
:config
(evil-collection-init))
(use-package evil-nerd-commenter
:defer t
:after evil)
#+END_SRC

157
.config/emacs/config/mail.org

@ -0,0 +1,157 @@
#+TITLE: Mail Configuration
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#mail-functions][Mail Functions]]
- [[#mail-in-emacs-with-mu4e][Mail in Emacs with mu4e]]
- [[#sources][Sources]]
** Mail Functions
#+BEGIN_SRC emacs-lisp
(with-eval-after-load 'auth-source
(defun dot/mail-auth-get-field (host prop)
"Find PROP in `auth-sources' for HOST entry."
(when-let ((source (auth-source-search :max 1 :host host)))
(if (eq prop :secret)
(funcall (plist-get (car source) prop))
(plist-get (flatten-list source) prop)))))
#+END_SRC
** Mail in Emacs with mu4e
Useful mu4e manual pages:
- [[https://www.djcbsoftware.nl/code/mu/mu4e/MSGV-Keybindings.html#MSGV-Keybindings][Key bindings]]
#+BEGIN_SRC emacs-lisp
(use-package mu4e
:ensure nil
:load-path "/usr/share/emacs/site-lisp/mu4e"
:defer 20
:commands mu4e
:config
(setq auth-sources `(,(concat dot-etc-dir "/authinfo.gpg")))
(setq user-full-name (dot/mail-auth-get-field "fullname" :user))
(setq user-mail-address (dot/mail-auth-get-field "info" :user))
(setq mail-user-agent 'mu4e-user-agent)
;; Headers
(setq mu4e-headers-date-format "%d-%m-%Y")
(setq mu4e-headers-time-format "%I:%M %p")
(setq mu4e-headers-long-date-format "%d-%m-%Y %I:%M:%S %p")
;; Syncing
(setq mu4e-get-mail-command (concat "mbsync -a -c " (getenv "XDG_CONFIG_HOME") "/isync/mbsyncrc"))
(setq mu4e-update-interval (* 15 60)) ; 15 minutes
(setq mu4e-maildir "~/mail")
(setq mu4e-attachment-dir "~/downloads")
;; Avoid mail syncing issues when using mbsync
(setq mu4e-change-filenames-when-moving t)
;; Misc
(setq mu4e-completing-read-function 'completing-read)
(setq mu4e-confirm-quit nil)
(setq mu4e-display-update-status-in-modeline t)
(setq mu4e-hide-index-messages t)
(setq mu4e-sent-messages-behavior 'sent)
(setq mu4e-view-show-addresses t)
(setq mu4e-view-show-images nil)
;; Compose
(setq mu4e-compose-context-policy 'ask)
(setq mu4e-compose-dont-reply-to-self t)
(setq mu4e-compose-signature (concat (dot/mail-auth-get-field "fullname" :user) "\nriyyi.com\n"))
(setq mu4e-compose-signature-auto-include t)
;; Contexts
(setq mu4e-context-policy 'pick-first)
(setq mu4e-contexts
`(,(make-mu4e-context
:name "info"
:match-func (lambda (msg)
(when msg
(string= (mu4e-message-field msg :maildir) "/info")))
:vars `((user-mail-address . ,(dot/mail-auth-get-field "info" :user))
(mu4e-drafts-folder . "/info/Drafts")
(mu4e-refile-folder . "/info/Archive")
(mu4e-sent-folder . "/info/Sent")
(mu4e-trash-folder . "/info/Trash")))
,(make-mu4e-context
:name "private"
:match-func (lambda (msg)
(when msg
(string= (mu4e-message-field msg :maildir) "/private")))
:vars `((user-mail-address . ,(dot/mail-auth-get-field "private" :user))
(mu4e-drafts-folder . "/private/Drafts")
(mu4e-refile-folder . "/private/Archive")
(mu4e-sent-folder . "/private/Sent")
(mu4e-trash-folder . "/private/Trash")))
))
;; Do not mark messages as IMAP-deleted, just move them to the Trash directory!
;; https://github.com/djcb/mu/issues/1136#issuecomment-486177435
(setf (alist-get 'trash mu4e-marks)
(list :char '("d" . "▼")
:prompt "dtrash"
:dyn-target (lambda (target msg)
(mu4e-get-trash-folder msg))
:action (lambda (docid msg target)
(mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))))
;; Start mu4e in the background for mail syncing
(mu4e t))
#+END_SRC
Use [[https://github.com/iqbalansari/mu4e-alert][mu4e-alert]] to show new e-mail notifications.
#+BEGIN_SRC emacs-lisp
(use-package mu4e-alert
:after mu4e
:config
(setq mu4e-alert-interesting-mail-query "(maildir:/info/Inbox OR maildir:/private/Inbox) AND flag:unread AND NOT flag:trashed")
(setq mu4e-alert-notify-repeated-mails nil)
(mu4e-alert-set-default-style 'libnotify)
(mu4e-alert-enable-notifications))
#+END_SRC
Sending mail.
#+BEGIN_SRC emacs-lisp
(use-package smtpmail
:ensure nil ; built-in
:after mu4e
:init (setq smtpmail-default-smtp-server "mail.riyyi.com")
:config
(setq smtpmail-smtp-server "mail.riyyi.com")
(setq smtpmail-local-domain "riyyi.com")
(setq smtpmail-smtp-service 587)
(setq smtpmail-stream-type 'starttls)
(setq smtpmail-queue-mail nil))
(use-package sendmail
:ensure nil ; built-in
:after mu4e
:config (setq send-mail-function 'smtpmail-send-it))
(use-package message
:ensure nil ; built-in
:after mu4e
:config
(setq message-kill-buffer-on-exit t)
(setq message-send-mail-function 'smtpmail-send-it))
#+END_SRC
** Sources
- https://rakhim.org/fastmail-setup-with-emacs-mu4e-and-mbsync-on-macos/
- https://wiki.archlinux.org/title/Isync
- https://man.archlinux.org/man/community/isync/mbsync.1.en
- https://gitlab.com/protesilaos/dotfiles/-/blob/master/mbsync/.mbsyncrc
- https://gitlab.com/protesilaos/dotfiles/-/blob/master/emacs/.emacs.d/prot-lisp/prot-mail.el
- https://gitlab.com/protesilaos/dotfiles/-/blob/master/emacs/.emacs.d/prot-lisp/prot-mu4e-deprecated-conf.el
- https://github.com/daviwil/dotfiles/blob/master/Mail.org

328
.config/emacs/config/org-mode.org

@ -0,0 +1,328 @@
#+TITLE: Org Mode
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#latex-configuration][LaTeX Configuration]]
- [[#org-configuration][Org Configuration]]
- [[#org-functions][Org Functions]]
- [[#org-bullets][Org Bullets]]
- [[#org-export-packages][Org Export Packages]]
- [[#org-roam][Org Roam]]
- [[#org-table-of-contents][Org "Table of Contents"]]
** LaTeX Configuration
#+BEGIN_SRC emacs-lisp
(use-package tex-mode
:ensure nil ; built-in
:defer t
:hook (latex-mode . (lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)))
:config
(with-eval-after-load 'projectile
(defun compile-latex ()
"Compile LaTeX project."
(interactive)
(let ((default-directory (dot/find-project-root)))
(projectile-save-project-buffers)
(shell-command "make")))))
#+END_SRC
** Org Configuration
Base Org.
#+BEGIN_SRC emacs-lisp
(use-package org
:config
(setq org-adapt-indentation nil)
(setq org-default-notes-file (expand-file-name "notes.org" org-directory))
(setq org-directory (concat (getenv "HOME") "/documents/org"))
(setq org-ellipsis "⤵")
(setq org-image-actual-width nil)
;; Enable structured template completion
(add-to-list 'org-modules 'org-tempo t)
(add-to-list 'org-structure-template-alist
'("el" . "src emacs-lisp")))
#+END_SRC
Org agenda.
#+BEGIN_SRC emacs-lisp
(use-package org-agenda
:ensure nil ; built-in
:defer t
:config
(setq org-agenda-files `(,org-directory ,user-emacs-directory))
(setq org-agenda-span 14)
(setq org-agenda-window-setup 'current-window)
(evil-set-initial-state 'org-agenda-mode 'motion))
#+END_SRC
Org capture.
#+BEGIN_SRC emacs-lisp
(use-package org-capture
:ensure nil ; built-in
;; Org-capture in new tab, rather than split window
:hook (org-capture-mode . delete-other-windows))
#+END_SRC
Org keys.
#+BEGIN_SRC emacs-lisp
(use-package org-keys
:ensure nil ; built-in
:config
(setq org-return-follows-link t))
#+END_SRC
Org links.
#+BEGIN_SRC emacs-lisp
(use-package ol
:ensure nil ; built-in
:config
;; Do not open links to .org files in a split window
(add-to-list 'org-link-frame-setup '(file . find-file)))
#+END_SRC
Org source code blocks.
#+BEGIN_SRC emacs-lisp
(use-package org-src
:ensure nil ; built-in
:config
(setq org-edit-src-content-indentation 0)
(setq org-src-fontify-natively t)
(setq org-src-preserve-indentation t)
(setq org-src-tab-acts-natively t)
(setq org-src-window-setup 'current-window))
#+END_SRC
Org exporter.
#+BEGIN_SRC emacs-lisp
(use-package ox
:ensure nil ; built-in
:defer t
:config
(setq org-export-coding-system 'utf-8-unix))
#+END_SRC
Org latex exporter.
#+BEGIN_SRC emacs-lisp
(use-package ox-latex
:ensure nil ; built-in
:defer t
:config
;; Define how minted (highlighted src code) is added to src code blocks
(setq org-latex-listings 'minted)
(setq org-latex-minted-options '(("frame" "lines") ("linenos=true")))
;; Set 'Table of Contents' layout
(setq org-latex-toc-command "\\newpage \\tableofcontents \\newpage")
;; Add minted package to every LaTeX header
(add-to-list 'org-latex-packages-alist '("" "minted"))
;; Append -shell-escape so pdflatex exports minted correctly
(add-to-list 'org-latex-pdf-process (replace-regexp-in-string
"%latex "
"%latex -shell-escape "
(car org-latex-pdf-process))))
#+END_SRC
** Org Functions
#+BEGIN_SRC emacs-lisp
(with-eval-after-load 'evil-commands
(defun dot/org-ret-at-point ()
"Org return key at point.
If point is on:
checkbox -- toggle it
link -- follow it
otherwise -- run the default (evil-ret) expression"
(interactive)
(let ((type (org-element-type (org-element-context))))
(pcase type
('link (if org-return-follows-link (org-open-at-point) (evil-ret)))
((guard (org-at-item-checkbox-p)) (org-toggle-checkbox))
(_ (evil-ret))
))))
#+END_SRC
** Org Bullets
#+BEGIN_SRC emacs-lisp
(use-package org-bullets
:hook (org-mode . org-bullets-mode))
#+END_SRC
** Org Export Packages
HTML exporter.
#+BEGIN_SRC emacs-lisp
(use-package htmlize
:defer t
:config (setq org-export-html-postamble nil))
;;org-export-html-postamble-format ; TODO
#+END_SRC
GitHub flavored Markdown exporter.
#+BEGIN_SRC emacs-lisp
(use-package ox-gfm
:defer t)
#+END_SRC
** Org Roam
Setup =org-roam=.
#+BEGIN_SRC emacs-lisp
(use-package org-roam
:defer 1
:init
(setq org-roam-v2-ack t)
:config
(setq org-roam-db-location (expand-file-name "org-roam.db" dot-cache-dir))
(setq org-roam-directory org-directory)
;; Exclude Syncthing backup directory
(setq org-roam-file-exclude-regexp "\\.stversions")
(setq org-roam-verbose nil)
(setq org-roam-capture-templates
'(("d" "default" plain
"%?"
:target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n#+FILETAGS: %^{File tags}\n")
:unnarrowed t)))
(defun dot/org-roam-node-insert-immediate (arg &rest args)
(interactive "P")
(let ((args (push arg args))
(org-roam-capture-templates (list (append (car org-roam-capture-templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args)))
(cl-defmethod org-roam-node-slug ((node org-roam-node))
"Return the slug of NODE, strip out common words."
(let* ((title (org-roam-node-title node))
(words (split-string title " "))
(common-words '("a" "an" "and" "as" "at" "by" "is" "it" "of" "the" "to"))
(title (string-join (seq-remove (lambda (element) (member element common-words)) words) "_"))
(pairs '(("c\\+\\+" . "cpp") ;; convert c++ -> cpp
("c#" . "cs") ;; convert c# -> cs
("[^[:alnum:][:digit:]]" . "_") ;; convert anything not alphanumeric
("__*" . "_") ;; remove sequential underscores
("^_" . "") ;; remove starting underscore
("_$" . "")))) ;; remove ending underscore
(cl-flet ((cl-replace (title pair)
(replace-regexp-in-string (car pair) (cdr pair) title)))
(downcase (-reduce-from #'cl-replace title pairs)))))
;; Right-align org-roam-node-tags in the completion menu without a length limit
;; Source: https://github.com/org-roam/org-roam/issues/1775#issue-971157225
(setq org-roam-node-display-template "${title} ${tags:0}")
(setq org-roam-node-annotation-function #'dot/org-roam-annotate-tag)
(defun dot/org-roam-annotate-tag (node)
(let ((tags (mapconcat 'identity (org-roam-node-tags node) " #")))
(unless (string-empty-p tags)
(concat
(propertize " " 'display `(space :align-to (- right ,(+ 2 (length tags)))))
(propertize (concat "#" tags) 'face 'bold)))))
(org-roam-setup))
#+END_SRC
Enable [[https://www.orgroam.com/manual.html#Roam-Protocol][Roam Protocol]], needed to process =org-protocol://= links
#+BEGIN_SRC emacs-lisp
(use-package org-roam-protocol
:ensure nil ; org-roam-protocol.el is part of org-roam
:after org-roam
:config
;; Templates used when creating a new file from a bookmark
(setq org-roam-capture-ref-templates
'(("r" "ref" plain
"%?"
:target (file+head "${slug}.org" "#+TITLE: ${title}\n \n${body}")
:unnarrowed t))))
#+END_SRC
The roam-ref protocol bookmarks to add:
#+BEGIN_SRC javascript
javascript:location.href =
'org-protocol://roam-ref?template=r'
+ '&ref=' + encodeURIComponent(location.href)
+ '&title=' + encodeURIComponent(document.title)
+ '&body=' + encodeURIComponent(window.getSelection())
#+END_SRC
Setup =org-roam-ui=, runs at http://127.0.0.1:35901.
#+BEGIN_SRC emacs-lisp
(use-package org-roam-ui
:after org-roam
:config
(setq org-roam-ui-follow t)
(setq org-roam-ui-open-on-start t)
(setq org-roam-ui-sync-theme nil) ;; FIXME: Make this work (org-roam-ui-get-theme)
(setq org-roam-ui-update-on-save t))
#+END_SRC
Easily searchable .org files via Deft.
#+BEGIN_SRC emacs-lisp
(use-package deft
:after org
:hook (deft-mode . dot/hook-disable-line-numbers)
:config
(setq deft-auto-save-interval 0)
(setq deft-default-extension "org")
(setq deft-directory org-directory)
(setq deft-file-naming-rules '((noslash . "-")
(nospace . "-")
(case-fn . downcase)))
(setq deft-new-file-format "%Y%m%d%H%M%S-deft")
(setq deft-recursive t)
;; Exclude Syncthing backup directory
(setq deft-recursive-ignore-dir-regexp (concat "\\.stversions\\|" deft-recursive-ignore-dir-regexp))
;; Remove file variable -*- .. -*- and Org Mode :PROPERTIES: lines
(setq deft-strip-summary-regexp (concat "\\(^.*-\\*-.+-\\*-$\\|^:[[:alpha:]_]+:.*$\\)\\|" deft-strip-summary-regexp))
(setq deft-use-filename-as-title nil)
(setq deft-use-filter-string-for-filename t)
(add-to-list 'deft-extensions "tex")
;; Start filtering immediately
(evil-set-initial-state 'deft-mode 'insert)
(defun deft-parse-title (file contents)
"Parse the given FILE and CONTENTS and determine the title."
(org-element-property
:value
(car
(org-element-map
(with-temp-buffer
(insert contents)
(org-element-parse-buffer 'greater-element))
'keyword
(lambda (e) (when (string-match "TITLE" (org-element-property :key e)) e)))))))
#+END_SRC
** Org "Table of Contents"
Generate table of contents without exporting.
#+BEGIN_SRC emacs-lisp
(use-package toc-org
:hook (org-mode . toc-org-mode))
#+END_SRC

46
.config/emacs/config/selection.org

@ -0,0 +1,46 @@
#+TITLE: Selection
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#selection][Selection]]
** Selection
#+BEGIN_SRC emacs-lisp
(use-package selectrum
:hook (emacs-startup . selectrum-mode)
:config
(defun dot/selectrum-backspace ()
"In Selectrum file completion, backward kill sexp, delete char otherwise."
(interactive)
(if (and selectrum-is-active
minibuffer-completing-file-name)
(evil-with-state 'insert
(move-end-of-line 1) (backward-kill-sexp 1))
(evil-delete-backward-char-and-join 1))))
(use-package prescient
:after selectrum
:config
(setq prescient-filter-method '(literal regexp fuzzy))
(setq prescient-save-file (concat dot-cache-dir "/prescient-save.el"))
(prescient-persist-mode))
(use-package selectrum-prescient
:after (selectrum prescient)
:config
(selectrum-prescient-mode))
(use-package marginalia
:after selectrum
:config
(setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light))
(marginalia-mode))
(use-package consult
:after selectrum
:config
(setq consult-project-root-function #'dot/find-project-root))
#+END_SRC

261
.config/emacs/config/ui.org

@ -0,0 +1,261 @@
#+TITLE: UI
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#all-the-icons][All the icons]]
- [[#centaur-tabs][Centaur Tabs]]
- [[#dashboard][Dashboard]]
- [[#helpful][Helpful]]
- [[#neotree][NeoTree]]
- [[#telephone-line][Telephone Line]]
- [[#theme][Theme]]
- [[#which-key][Which-key]]
** All the icons
#+BEGIN_SRC emacs-lisp
(use-package all-the-icons
:defer t
:config
;; Install all-the-icons if font files are not found
(unless (find-font (font-spec :name "all-the-icons"))
(all-the-icons-install-fonts t)))
(use-package all-the-icons-dired
:after all-the-icons
:hook (dired-mode . all-the-icons-dired-mode)
:config (setq all-the-icons-dired-monochrome nil))
#+END_SRC
** Centaur Tabs
Places buffers as tabs in a bar at the top of the frame.
#+BEGIN_SRC emacs-lisp
(use-package centaur-tabs
:after all-the-icons
:demand
:hook
((eshell-mode
help-mode
helpful-mode
mu4e-view-mode
neotree-mode
shell-mode)
. centaur-tabs-local-mode)
:config
(setq centaur-tabs-enable-ido-completion nil)
(setq centaur-tabs-height (if dot/hidpi 28 18))
(setq centaur-tabs-modified-marker "•")
(setq centaur-tabs-set-icons t)
(setq centaur-tabs-set-modified-marker t)
(setq centaur-tabs-style "slant")
(defun centaur-tabs-buffer-groups ()
"Organize tabs into groups by buffer."
(list
(cond
((string-equal "*" (substring (buffer-name) 0 1)) "Emacs")
((memq major-mode '(org-mode
emacs-lisp-mode)) "Org Mode")
((derived-mode-p 'dired-mode) "Dired")
((derived-mode-p 'prog-mode
'text-mode) "Editing")
(t "User"))))
(defun centaur-tabs-hide-tab (buffer)
"Hide from the tab bar by BUFFER name."
(let ((name (format "%s" buffer)))
(or
;; Current window is dedicated window
(window-dedicated-p (selected-window))
;; Buffer name does match below blacklist
(string-match-p (concat "\\(CAPTURE-\\)?" (format-time-string "%Y%m%d%H%M%S") "-.*\\.org") name)
(string-match-p
(concat "^ ?\\*\\("
"Agenda Commands\\|"
"e?shell\\|"
"Compile-Log\\|"
"Completions\\|"
;; "clangd\\|" ; lsp c/c++
"dap-mouse\\|"
"dap-ui-\\|"
"Debug\\|"
"Faces\\|"
"Flycheck\\|"
"Help\\|"
"helpful\\|"
"httpd\\|"
"iph\\|" ; lsp php
"org-roam\\|"
"Org tags\\|"
"Org todo"
"\\).*")
name))))
(defun dot/centaur-tabs-is-buffer-unimportant (buffer)
"Return t if BUFFER is unimportant and can be killed without caution."
(let ((name (format "%s" buffer)))
(cond
((centaur-tabs-hide-tab name) t)
((string-match-p "^magit\\(-[a-z]+\\)*: .*" name) t)
(t nil))))
(defun dot/centaur-tabs-buffer-cleanup ()
"Clean up all the hidden buffers."
(interactive)
(dolist (buffer (buffer-list))
(when (dot/centaur-tabs-is-buffer-unimportant buffer)
(kill-buffer buffer)))
(princ "Cleaned buffers"))
(defun dot/centaur-tabs-kill-buffer-or-window ()
"Delete window of the current buffer, also kill if the buffer is hidden."
(interactive)
(if (dot/centaur-tabs-is-buffer-unimportant (buffer-name))
(kill-buffer-and-window)
(delete-window)))
(centaur-tabs-headline-match)
(centaur-tabs-mode))
#+END_SRC
** Dashboard
#+BEGIN_SRC emacs-lisp
(use-package page-break-lines)
(use-package dashboard
:demand
:hook (dashboard-mode . dot/hook-disable-line-numbers)
:config
(setq initial-buffer-choice (lambda () (get-buffer "*dashboard*")))
(setq dashboard-banner-logo-title "GNU Emacs master race!")
(setq dashboard-center-content t)
(setq dashboard-page-separator "\n\f\n")
(setq dashboard-set-file-icons t)
(setq dashboard-set-footer nil)
(setq dashboard-set-heading-icons t)
(setq dashboard-show-shortcuts t)
(setq dashboard-startup-banner 'logo)
(setq dashboard-items '((projects . 10)
(bookmarks . 5)
(recents . 5)))
(defun dot/dashboard-goto ()
"Go to the *dashboard* buffer, create if non-existing."
(interactive)
(let ((buffer "*dashboard*"))
(unless (get-buffer buffer)
(generate-new-buffer buffer)
(dashboard-refresh-buffer))
(switch-to-buffer buffer)))
;; Fix keybinds..
(defun dot/dashboard-goto-bookmarks ()
"Move point to bookmarks."
(interactive)
(funcall (local-key-binding "m")))
(defun dot/dashboard-goto-projects ()
"Move point to projects."
(interactive)
(funcall (local-key-binding "p")))
(defun dot/dashboard-goto-recent-files ()
"Move point to recent files."
(interactive)
(funcall (local-key-binding "r")))
(dashboard-setup-startup-hook))
#+END_SRC
** Helpful
A better *help* buffer.
#+BEGIN_SRC emacs-lisp
(use-package helpful
:hook (helpful-mode . dot/hook-disable-line-numbers))
#+END_SRC
** NeoTree
Provides Emacs with a file tree.
#+BEGIN_SRC emacs-lisp
(use-package neotree
:after all-the-icons
:hook (neotree-mode . dot/hook-disable-line-numbers)
:hook (neotree-mode . hl-line-mode)
:init
;; This needs to be in init to actually start loading the package
(with-eval-after-load 'projectile
(defun neotree-toggle-in-project-root ()
"Toggle Neotree in project root."
(interactive)
(let ((default-directory (dot/find-project-root)))
(call-interactively #'neotree-toggle))))
:config
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
(setq neo-autorefresh nil)
(setq neo-mode-line-type 'none)
(setq neo-show-hidden-files t)
(setq neo-vc-integration '(face)))
#+END_SRC
** Telephone Line
Emacs mode line replacement.
#+BEGIN_SRC emacs-lisp
(use-package telephone-line
:config
(setq telephone-line-height (if dot/hidpi 20 15))
(setq telephone-line-lhs
'((evil . (telephone-line-evil-tag-segment))
(accent . (telephone-line-erc-modified-channels-segment
telephone-line-process-segment
telephone-line-buffer-segment))
(nil . (telephone-line-projectile-segment))))
(telephone-line-mode))
#+END_SRC
** Theme
#+BEGIN_SRC emacs-lisp
(use-package hybrid-reverse-theme
:ensure nil
:load-path "~/code/elisp/emacs-hybrid-reverse"
:config (load-theme 'hybrid-reverse t))
#+END_SRC
** Which-key
Popup that displays available key bindings.
#+BEGIN_SRC emacs-lisp
(use-package which-key
:hook (emacs-startup . which-key-mode)
:config
(setq which-key-add-column-padding 1)
(setq which-key-max-display-columns nil)
(setq which-key-min-display-lines 6)
(setq which-key-sort-order #'dot/which-key-prefix-then-key-order-alpha)
(setq which-key-sort-uppercase-first nil)
(defun dot/which-key-prefix-then-key-order-alpha (acons bcons)
"Order by prefix, then lexicographical."
(let ((apref? (which-key--group-p (cdr acons)))
(bpref? (which-key--group-p (cdr bcons))))
(if (not (eq apref? bpref?))
(and (not apref?) bpref?)
(which-key-key-order-alpha acons bcons)))))
#+END_SRC
Loading…
Cancel
Save