From 89607db9054ae83118f53af6c5e7c7c5a1aa7f63 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sun, 1 Jan 2023 22:46:55 +0100 Subject: [PATCH] Emacs: Complete restructure of the config Changed - Org-mode babel config to separate .el modules - Built-in package manager package.el to Elpaca - Configuration macro use-package to setup.el - Completion framework selectrum to vertico --- .config/emacs/config.org | 1297 ----------------- .config/emacs/config/development.org | 471 ------ .config/emacs/config/evil.org | 108 -- .config/emacs/config/mail.org | 157 -- .config/emacs/config/org-mode.org | 331 ----- .config/emacs/config/selection.org | 52 - .config/emacs/config/ui.org | 253 ---- .config/emacs/early-init.el | 15 +- .config/emacs/init.el | 36 +- .../emacs/site-lisp/core/dot-core-advice.el | 25 + .../emacs/site-lisp/core/dot-core-config.el | 244 ++++ .../site-lisp/core/dot-core-customize.el | 19 + .../emacs/site-lisp/core/dot-core-fonts.el | 17 + .../site-lisp/core/dot-core-functions.el | 195 +++ .../emacs/site-lisp/core/dot-core-hooks.el | 32 + .../emacs/site-lisp/core/dot-core-packages.el | 90 ++ .../site-lisp/core/dot-core-variables.el | 48 + .config/emacs/site-lisp/dot-core.el | 24 + .config/emacs/site-lisp/dot-development.el | 472 ++++++ .config/emacs/site-lisp/dot-elpaca.el | 48 + .config/emacs/site-lisp/dot-evil.el | 104 ++ .config/emacs/site-lisp/dot-keybinds.el | 665 +++++++++ .config/emacs/site-lisp/dot-mail.el | 148 ++ .config/emacs/site-lisp/dot-org-mode.el | 268 ++++ .config/emacs/site-lisp/dot-rss.el | 29 + .config/emacs/site-lisp/dot-selection.el | 79 + .config/emacs/site-lisp/dot-setup-el.el | 107 ++ .config/emacs/site-lisp/dot-ui.el | 249 ++++ .config/emacs/snippets/c++-mode/namespace | 2 +- 29 files changed, 2880 insertions(+), 2705 deletions(-) delete mode 100644 .config/emacs/config.org delete mode 100644 .config/emacs/config/development.org delete mode 100644 .config/emacs/config/evil.org delete mode 100644 .config/emacs/config/mail.org delete mode 100644 .config/emacs/config/org-mode.org delete mode 100644 .config/emacs/config/selection.org delete mode 100644 .config/emacs/config/ui.org create mode 100644 .config/emacs/site-lisp/core/dot-core-advice.el create mode 100644 .config/emacs/site-lisp/core/dot-core-config.el create mode 100644 .config/emacs/site-lisp/core/dot-core-customize.el create mode 100644 .config/emacs/site-lisp/core/dot-core-fonts.el create mode 100644 .config/emacs/site-lisp/core/dot-core-functions.el create mode 100644 .config/emacs/site-lisp/core/dot-core-hooks.el create mode 100644 .config/emacs/site-lisp/core/dot-core-packages.el create mode 100644 .config/emacs/site-lisp/core/dot-core-variables.el create mode 100644 .config/emacs/site-lisp/dot-core.el create mode 100644 .config/emacs/site-lisp/dot-development.el create mode 100644 .config/emacs/site-lisp/dot-elpaca.el create mode 100644 .config/emacs/site-lisp/dot-evil.el create mode 100644 .config/emacs/site-lisp/dot-keybinds.el create mode 100644 .config/emacs/site-lisp/dot-mail.el create mode 100644 .config/emacs/site-lisp/dot-org-mode.el create mode 100644 .config/emacs/site-lisp/dot-rss.el create mode 100644 .config/emacs/site-lisp/dot-selection.el create mode 100644 .config/emacs/site-lisp/dot-setup-el.el create mode 100644 .config/emacs/site-lisp/dot-ui.el diff --git a/.config/emacs/config.org b/.config/emacs/config.org deleted file mode 100644 index 6f39f30..0000000 --- a/.config/emacs/config.org +++ /dev/null @@ -1,1297 +0,0 @@ -#+STARTUP: overview -#+TITLE: Ricemacs, an Emacs Configuration -#+AUTHOR: Riyyi -#+LANGUAGE: en -#+OPTIONS: toc:nil -#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n" -#+SETUPFILE: https://fniessen.github.io/org-html-themes/org/theme-readtheorg.setup -#+LATEX_HEADER: \usepackage[top=100pt,bottom=100pt,left=75pt,right=75pt]{geometry} -#+LATEX_HEADER: \usepackage{color} -#+LATEX_HEADER: \definecolor{blue}{rgb}{0,0.5,1} -#+LATEX_HEADER: \hypersetup{colorlinks=true, linkcolor=blue, urlcolor=blue, citecolor=blue} - -* Table of Contents :toc_4: -- [[#global-variables][Global Variables]] -- [[#customizations][Customizations]] -- [[#package-management][Package Management]] - - [[#ensure][Ensure]] - - [[#auto-update][Auto Update]] - - [[#compile][Compile]] - - [[#packages][Packages]] - - [[#load-modules][Load Modules]] - - [[#general-packages][General Packages]] - - [[#rss][RSS]] -- [[#general][General]] - - [[#buffers][Buffers]] - - [[#dired][Dired]] - - [[#electric][Electric]] - - [[#file-paths][File Paths]] - - [[#file-backups-versioning][File Backups Versioning]] - - [[#formatting][Formatting]] - - [[#hide-elements][Hide Elements]] - - [[#native-compilation][Native Compilation]] - - [[#recentf][Recentf]] - - [[#tabs][Tabs]] - - [[#utf-8][UTF-8]] - - [[#window][Window]] -- [[#functions][Functions]] - - [[#general-functions][General Functions]] -- [[#advice-and-aliases][Advice and Aliases]] - - [[#advice][Advice]] - - [[#aliases][Aliases]] -- [[#hooks][Hooks]] -- [[#key-bindings][Key Bindings]] - - [[#disable-native][Disable Native]] - - [[#disable-package][Disable Package]] - - [[#set-native][Set Native]] - - [[#set-native-global-keybinds][Set Native Global Keybinds]] - - [[#set-native-mode-keybinds][Set Native Mode Keybinds]] - - [[#set-package][Set Package]] - - [[#leader][Leader]] - - [[#global-leader][Global Leader]] - - [[#local-leader][Local Leader]] -- [[#notes][Notes]] - -* Global Variables - -Variables for directories, leader keys, etc. - -#+BEGIN_SRC emacs-lisp -(defvar dot-emacs-dir (directory-file-name (file-truename user-emacs-directory)) - "Directory base.") ; ~/.config/emacs - -(defvar dot-etc-dir (concat dot-emacs-dir "/etc") - "Directory for non-volatile storage.") ; ~/.config/emacs/etc - -(defvar dot-cache-dir (concat (getenv "XDG_CACHE_HOME") "/emacs") - "Directory for cache data.") ; ~/.cache/emacs - -(defvar dot/leader-key "SPC" - "Leader prefix key.") - -(defvar dot/leader-alt-key "M-SPC" - "Alternative leader prefix key, used for Insert and Emacs states.") - -(defvar dot/localleader-key "SPC m" - "Local leader prefix key, for 'major-mode' specific commands.") - -(defvar dot/localleader-alt-key "M-SPC m" - "Alternative local leader prefix key, used for Insert and Emacs states.") - -(defvar dot/shell "/bin/zsh" - "Command interpreter binary path.") - -(defvar dot/hidpi (getenv "HIDPI") - "Whether the primary screen is HiDPI.") - -;; Create cache directory -(unless (file-directory-p dot-cache-dir) - (make-directory dot-cache-dir t)) -#+END_SRC - -* Customizations - -Store customize file separately, don't freak out when it's not found. - -#+BEGIN_SRC emacs-lisp -(setq custom-file (concat dot-etc-dir "/custom.el")) -(load custom-file 'noerror) -#+END_SRC - -Set font. - -#+BEGIN_SRC emacs-lisp -(set-face-attribute 'default nil :height 90 :family "DejaVu Sans Mono") -(set-face-attribute 'fixed-pitch-serif nil :height 100) -#+END_SRC - -* Package Management -** Ensure - -Ensures packages are installed by default. - -#+BEGIN_SRC emacs-lisp -(require 'use-package-ensure) -(setq use-package-always-ensure t) -#+END_SRC - -** Auto Update - -Update pending updates of installed packages at startup. -https://github.com/rranelli/auto-package-update.el - -#+BEGIN_SRC emacs-lisp -(use-package auto-package-update - :config - (setq auto-package-update-delete-old-versions t) - (setq auto-package-update-hide-results t) - (setq auto-package-update-last-update-day-path (concat dot-cache-dir "/last-package-update-day")) - - (defun dot/update-packages () - "Update all packages." - (interactive) - (package-refresh-contents) - (auto-package-update-now) - (package-quickstart-refresh)) - - (auto-package-update-maybe)) -#+END_SRC - -** Compile - -Automatically compile all packages. -https://github.com/emacscollective/auto-compile - -#+BEGIN_SRC emacs-lisp -(use-package auto-compile - :config - (auto-compile-on-load-mode) - (auto-compile-on-save-mode)) -#+END_SRC - -** Packages - -Install and configure packages. - -*** Load Modules - -#+BEGIN_SRC emacs-lisp -(defun dot/load-org (file) - "Tangle then load org FILE." - (if (file-readable-p file) - (org-babel-load-file file) - (user-error (format "Init: could not load module '%s'" (file-name-base file))))) - -(dot/load-org (concat dot-emacs-dir "/config/ui.org")) -(dot/load-org (concat dot-emacs-dir "/config/evil.org")) -(dot/load-org (concat dot-emacs-dir "/config/development.org")) -(dot/load-org (concat dot-emacs-dir "/config/selection.org")) -(dot/load-org (concat dot-emacs-dir "/config/org-mode.org")) -(dot/load-org (concat dot-emacs-dir "/config/mail.org")) -#+END_SRC - -*** General Packages - -#+BEGIN_SRC emacs-lisp -(use-package general - :after evil - :config - ;; Fix for issue: general #493 - (defun dot/general-fix-leader-key () - "Fix leader key in *Messages* buffer." - (when-let ((messages-buffer (get-buffer "*Messages*"))) - (with-current-buffer messages-buffer - (evil-normalize-keymaps)))) - (add-hook 'emacs-startup-hook #'dot/general-fix-leader-key)) - -(use-package avy - :defer t) - -(use-package hungry-delete - :config (global-hungry-delete-mode)) - -(use-package smart-tabs-mode - :config - (smart-tabs-add-language-support latex latex-mode-hook - ((latex-indent-line . 4) - (latex-indent-region . 4))) - (smart-tabs-insinuate 'c 'c++ 'java 'python 'latex)) - -(use-package super-save - :config - (setq super-save-auto-save-when-idle t) - - ;; Fix for issues: super-save #38 and lsp-mode #1322 - (defun dot/super-save-disable-advice (orig-fun &rest args) - "Dont auto-save under these conditions." - (unless (equal (car args) " *LV*") - (apply orig-fun args))) - (advice-add 'super-save-command-advice :around #'dot/super-save-disable-advice) - - (super-save-mode)) - -(use-package desktop - :after centaur-tabs - :config - (setq desktop-dirname (concat dot-cache-dir "/desktop/")) - (setq desktop-path (list (concat dot-cache-dir "/desktop/"))) - - (defun dot/desktop-save-on-exit () - "Save state of open buffers before closing Emacs." - (dot/centaur-tabs-buffer-cleanup) - (desktop-save desktop-dirname t) - (desktop-release-lock desktop-dirname)) - (add-hook 'kill-emacs-hook #'dot/desktop-save-on-exit)) -#+END_SRC - -*** RSS - -#+BEGIN_SRC emacs-lisp -(use-package elfeed - :defer t - :commands elfeed - :hook (elfeed-search-mode . dot/hook-disable-line-numbers) - :hook (elfeed-show-mode . dot/hook-disable-line-numbers) - :config - (setq elfeed-db-directory (concat dot-cache-dir "/elfeed")) - (setq elfeed-enclosure-default-dir "~/downloads/") - (setq elfeed-search-filter "@6-months-ago +unread") - (setq elfeed-search-clipboard-type 'CLIPBOARD) - (setq elfeed-search-title-max-width 100) - (setq elfeed-search-title-min-width 30) - (setq elfeed-search-trailing-width 55) - (setq elfeed-show-unique-buffers t) - (load (concat dot-etc-dir "/elfeed-feeds"))) -#+END_SRC - -* General - -#+BEGIN_SRC emacs-lisp -;; Columns start at 1 -(setq column-number-indicator-zero-based nil) - -;; Dont confirm on quitting Emacs -(setq confirm-kill-processes nil) - -;; Custom thems, do not ask if safe -(setq custom-safe-themes t) - -;; Dired move to trash -(setq delete-by-moving-to-trash t) - -;; Column indicator character -(setq display-fill-column-indicator-character ?\N{U+2503}) - -;; Scrolling -(setq scroll-conservatively 1) -(setq mouse-wheel-scroll-amount '(5)) -(setq mouse-wheel-progressive-speed nil) - -;; Parenthesis, set behavior -(setq show-paren-delay 0) -(setq show-paren-style 'mixed) - -;; Tramp default protocol -(setq tramp-default-method "ssh") - -;; Set undo limit, measured in bytes -(setq-default undo-limit 400000) -(setq-default undo-strong-limit 3000000) -(setq-default undo-outer-limit 12000000) - -;; Enable line numbers -(global-display-line-numbers-mode) - -;; C++ syntax highlighting for .h files -(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode)) - -;; Set the frame title -(setq frame-title-format - `("%b" - (:eval - (if (buffer-file-name) - (concat - (if (buffer-modified-p) " •" nil) - " (" - (abbreviate-file-name - (directory-file-name - (file-name-directory (buffer-file-name)))) - ")") - nil)) - ,(format " - GNU Emacs %s" emacs-version) - )) -(setq icon-title-format frame-title-format) -#+END_SRC - -** Buffers - -#+BEGIN_SRC emacs-lisp -(setq confirm-nonexistent-file-or-buffer nil) -(setq ibuffer-expert t) -#+END_SRC - -** Dired - -#+BEGIN_SRC emacs-lisp -(setq wdired-allow-to-change-permissions t) -#+END_SRC - -** Electric - -#+BEGIN_SRC emacs-lisp -;; Make return key also do indent of previous line -(electric-indent-mode 1) -(setq electric-pair-pairs '( - (?\( . ?\)) - (?\[ . ?\]) - )) -(electric-pair-mode 1) -#+END_SRC - -** File Paths - -Set file paths for built-in features like: auto-saves, backups, etc. - -#+BEGIN_SRC emacs-lisp -;; Set Directory locations -(setq auto-save-list-file-prefix (concat dot-cache-dir "/auto-save/")) -(setq auto-save-file-name-transforms `((".*" ,auto-save-list-file-prefix t))) -(setq backup-directory-alist `((".*" . ,(concat dot-cache-dir "/backup/")))) -(setq eshell-directory-name (concat dot-cache-dir "/eshell/")) -(setq org-id-locations-file (concat dot-cache-dir "/org-id-locations")) -(setq tramp-auto-save-directory (concat dot-cache-dir "/tramp-auto-save/")) -(setq tramp-backup-directory-alist backup-directory-alist) -(setq url-configuration-directory (concat dot-cache-dir "/url/")) - -;; Set file locations -(setq bookmark-default-file (concat dot-etc-dir "/bookmarks")) -(setq nsm-settings-file (concat dot-cache-dir "/network-security.data")) -(setq tramp-persistency-file-name (concat dot-cache-dir "/tramp")) -#+END_SRC - -** File Backups Versioning - -Setup file backups versioning. - -#+BEGIN_SRC emacs-lisp -(setq backup-by-copying t) ; Don't cobbler symlinks -(setq create-lockfiles nil) ; Disable lockfiles (.#) -(setq delete-old-versions t) ; Cleanup backups -(setq kept-new-versions 5) ; Newest backups to keep -(setq kept-old-versions 2) ; Oldest backups to keep -(setq version-control t) ; Use version numbers on backups -#+END_SRC - -** Formatting - -#+BEGIN_SRC emacs-lisp -;; Columnn after line-wrapping happens -(setq-default fill-column 80) - -;; Automatically add newline on save at the end of the file -(setq require-final-newline t) - -;; End sentences with a single space -(setq sentence-end-double-space nil) - -;; `tabify' and `untabify' should only affect indentation -(setq tabify-regexp "^\t* [ \t]+") - -;; Do not wrap lines -(setq-default truncate-lines t) - -;; Wrap lines in the middle of words, gives a \ indicator -(setq-default word-wrap nil) -#+END_SRC - -** Hide Elements - -#+BEGIN_SRC emacs-lisp -(menu-bar-mode 0) -(scroll-bar-mode 0) -(tool-bar-mode 0) -(tooltip-mode 0) -(fringe-mode 0) -(blink-cursor-mode 0) - -(setq inhibit-startup-message t) -(setq initial-scratch-message nil) -(setq ring-bell-function 'ignore) -#+END_SRC - -** Native Compilation - -#+BEGIN_SRC emacs-lisp -(setq native-comp-async-report-warnings-errors nil) -#+END_SRC - -** Recentf - -#+BEGIN_SRC emacs-lisp -(use-package recentf - :ensure nil ; built-in - :config - (setq recentf-auto-cleanup 'never) - (setq recentf-exclude '("~$" "/ssh:" "/sudo:")) - (setq recentf-filename-handlers '(abbreviate-file-name)) - (setq recentf-max-menu-items 0) - (setq recentf-max-saved-items 200) - (setq recentf-save-file (concat dot-cache-dir "/recentf")) - (recentf-mode)) -#+END_SRC - -** Tabs - -#+BEGIN_SRC emacs-lisp -;; Tabs -(setq-default tab-width 4 - indent-tabs-mode t) - -;; C/C++-like languages formatting style -;; https://www.emacswiki.org/emacs/IndentingC -(setq-default c-basic-offset 4 - sgml-basic-offset 4 - sh-basic-offset 4 - c-default-style "linux") -#+END_SRC - -** UTF-8 - -Set UTF-8 encoding as default. - -#+BEGIN_SRC emacs-lisp -(prefer-coding-system 'utf-8-unix) -(setq locale-coding-system 'utf-8-unix) -;; Default also sets file-name, keyboard and terminal coding system -(set-default-coding-systems 'utf-8-unix) -(set-buffer-file-coding-system 'utf-8-unix) -(set-selection-coding-system 'utf-8-unix) -#+END_SRC - -** Window - -#+BEGIN_SRC emacs-lisp -;; Set `switch-to-buffer' to respect the window rules -(setq switch-to-buffer-obey-display-actions t) - -;; Window rules -(setq display-buffer-alist - '( - ;; ^\*(e?shell|(ansi-|v)?term).* - ("^\\*\\(e?shell\\|\\(ansi-\\|v\\)?term\\).*" - (display-buffer-in-side-window) - (window-height . 0.25) - (side . bottom) - (slot . -1)) - ("\\*Faces\\*" - (display-buffer-in-side-window) - (window-height . 0.25) - (side . bottom) - (slot . 1)) - ("\\*Help.*" - (display-buffer-in-side-window) - (window-height . 0.25) - (side . bottom) - (slot . 0)) - )) -#+END_SRC - -Allow 'undo' and 'redo' changes in Window Configuration. - -#+BEGIN_SRC emacs-lisp -(winner-mode) -#+END_SRC - -* Functions -** General Functions - -Functions that only use built-in Emacs functionality. - -#+BEGIN_SRC emacs-lisp -(defun display-startup-echo-area-message () - "Hide default startup message." - (message nil)) - -(defun dot/config-visit () - "Edit config file." - (interactive) - (find-file (concat dot-emacs-dir "/config.org"))) - -(defun dot/config-reload () - "Reload config file." - (interactive) - (org-babel-load-file (concat dot-emacs-dir "/config.org"))) - -(defun dot/copy-cpp-function-implementation () - (interactive) - (save-excursion - (let ((func (save-excursion - (re-search-backward "\\b") - (re-search-forward "\\([^;]+\\);") - (match-string 1))) - (type (progn - (re-search-backward "\\b") - (push-mark) - (back-to-indentation) - (buffer-substring (mark) (point)))) - (class (progn - (backward-up-list) - (backward-sexp) - (back-to-indentation) - (forward-to-word 1) - (current-word)))) - (kill-new (concat type class "::" func "\n{\n}")))) - (message "Copied function implementation")) - -;; Reference: http://turingmachine.org/bl/2013-05-29-recursively-listing-directories-in-elisp.html -(defun dot/directory-files-recursively-depth (dir regexp include-directories maxdepth) - "Depth limited variant of the built-in `directory-files-recursively'." - (let ((result '()) - (current-directory-list (directory-files dir t))) - (dolist (path current-directory-list) - (cond - ((and (file-regular-p path) - (file-readable-p path) - (string-match regexp path)) - (setq result (cons path result))) - ((and (file-directory-p path) - (file-readable-p path) - (not (string-equal "/.." (substring path -3))) - (not (string-equal "/." (substring path -2)))) - (when (and include-directories - (string-match regexp path)) - (setq result (cons path result))) - (when (> maxdepth 1) - (setq result (append (nreverse (dot/directory-files-recursively-depth - path regexp include-directories (- maxdepth 1))) - result)))) - (t))) - (reverse result))) - -(defun dot/dired-find-file () - "In Dired, visit the file or directory named on this line." - (interactive) - (if (file-directory-p (dired-file-name-at-point)) - (dired-find-alternate-file) - (dired-find-file))) - -(defun dot/dired-up-directory () - "Run Dired on parent directory of current directory." - (interactive) - (find-alternate-file "..")) - -(defun dot/find-file-emacsd () - "Find file under `dot-emacs-dir', recursively." - (interactive) - (let ((files (mapcar 'abbreviate-file-name - (directory-files-recursively dot-emacs-dir "")))) - (find-file (completing-read "Find file (emacs): " files nil t)))) - -(defun dot/indent-buffer () - "Indent each nonblank line in the buffer." - (interactive) - (save-excursion - (indent-region (point-min) (point-max) nil))) - -(defun dot/insert-spaces-until-column (until-column) - "Insert spaces from point to UNTIL-COLUMN." - (interactive "nInsert spaces until column: ") - (let ((current-column (current-column))) - ;; Increment column if the index is 1 based - (when (not column-number-indicator-zero-based) - (setq current-column (+ current-column 1))) - ;; Insert spaces - (let ((diff (- until-column current-column))) - (if (> diff 0) - (save-excursion (insert (make-string diff ?\ ))) - (user-error "Column should be higher than point"))))) - -(defun dot/reload-theme () - "Reload custom theme." - (interactive) - (mapc 'load (file-expand-wildcards - (concat (car custom-theme-load-path) "*.el"))) - (load-theme (car custom-enabled-themes) t)) - -(defun dot/sudo-find-file (filename) - "Edit file FILENAME as root." - (interactive "FOpen file (as root): ") - (find-file (concat "/sudo:root@localhost:" filename))) - -(defun dot/sudo-this-file () - "Edit the current file as root." - (interactive) - (if buffer-file-name - (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)) - (princ "Current buffer isn't a file"))) - -(defun dot/toggle-fringe (&optional arg) - "Toggle left-only fringe, or set state with ARG." - (interactive) - (if (or (and (eq fringe-mode 0) (eq arg nil)) - (eq arg 1)) - (set-fringe-mode '(nil . 0)) - (set-fringe-mode 0))) - -(defun dot/M-x (command) - "Prompt and execute COMMAND." - (interactive "CCommand: ") - (command-execute command)) - -(defun split-follow-horizontally () - "Split and follow window." - (interactive) - (split-window-below) - (other-window 1)) -(defun split-follow-vertically () - "Split and follow window." - (interactive) - (split-window-right) - (other-window 1)) - -;; https://emacsredux.com/blog/2013/05/04/rename-file-and-buffer/ -(defun rename-file-and-buffer () - "Rename the current buffer and file it is visiting." - (interactive) - (let ((filename (buffer-file-name))) - (if (not (and filename (file-exists-p filename))) - (message "Buffer is not visiting a file!") - (let ((new-name (read-file-name "New name: " filename))) - (cond - ((vc-backend filename) (vc-rename-file filename new-name)) - (t - (rename-file filename new-name t) - (set-visited-file-name new-name t t))))))) -#+END_SRC - -Functions that are only used for hook calls. - -#+BEGIN_SRC emacs-lisp -(defun dot/hook-disable-line-numbers () - "Disable the line numbers." - (display-line-numbers-mode 0)) - -(defun dot/hook-disable-mode-line () - "Disable the mode line." - (setq-local mode-line-format nil)) -#+END_SRC - -* Advice and Aliases -** Advice - -Define default terminal option. - -#+BEGIN_SRC emacs-lisp -(defun dot/ansi-term (program &optional new-buffer-name) - (interactive (list dot/shell))) -(advice-add 'ansi-term :before #'dot/ansi-term) -#+END_SRC - -** Aliases - -Make confirm easier, by just pressing y/n. - -#+BEGIN_SRC emacs-lisp -(defalias 'yes-or-no-p 'y-or-n-p) -#+END_SRC - -* Hooks - -#+BEGIN_SRC emacs-lisp -;; Delete trailing whitespace -(add-hook 'before-save-hook 'delete-trailing-whitespace) - -;; Display fill column indicator -(add-hook 'prog-mode-hook 'display-fill-column-indicator-mode) -(add-hook 'text-mode-hook 'display-fill-column-indicator-mode) - -;; Highlight parenthesis -(add-hook 'prog-mode-hook 'show-paren-mode) - -;; Disable line numbers -(add-hook 'Custom-mode-hook 'dot/hook-disable-line-numbers) -(add-hook 'dired-mode-hook 'dot/hook-disable-line-numbers) -(add-hook 'Info-mode-hook 'dot/hook-disable-line-numbers) -(add-hook 'term-mode-hook 'dot/hook-disable-line-numbers) - -;; Wrap lines in the middle of words, gives a \ indicator -(add-hook 'visual-line-mode-hook (lambda () (setq word-wrap nil))) -#+END_SRC - -* Key Bindings - -Useful links:\\ -[[https://www.masteringemacs.org/article/mastering-key-bindings-emacs][Mastering Emacs key bindings]] \\ -[[https://github.com/jwiegley/use-package/blob/master/bind-key.el][use-package bind key]] \\ -[[https://www.gnu.org/software/emacs/manual/html_node/elisp/Remapping-Commands.html][GNU remapping commands]] \\ -[[https://www.gnu.org/software/emacs/manual/html_node/efaq/Binding-combinations-of-modifiers-and-function-keys.html][GNU binding combinations of modifiers]] \\ -[[https://github.com/hlissner/doom-emacs/blob/develop/modules/config/default/+evil-bindings.el][Doom Emacs bindings]] - -** Disable Native - -Disable keybinds of native modes that clash with other custom keybinds. - -#+BEGIN_SRC emacs-lisp -(with-eval-after-load 'org - (define-key org-mode-map (kbd "M-h") nil) - (define-key org-mode-map (kbd "C-M-h") nil)) - -(with-eval-after-load 'cc-mode - (define-key c-mode-base-map (kbd "M-j") nil) - (define-key c-mode-base-map (kbd "C-M-h") nil)) - -(with-eval-after-load 'nxml-mode - (define-key nxml-mode-map (kbd "M-h") nil)) -#+END_SRC - -** Disable Package - -Disable keybinds of installed packages that clash with other custom keybinds. - -#+BEGIN_SRC emacs-lisp -(with-eval-after-load 'evil-states - (define-key evil-motion-state-map (kbd dot/leader-key) nil)) - -(with-eval-after-load 'magit - (general-def 'normal magit-mode-map - ;; Do not close magit when pressing escape - "" nil)) - -(with-eval-after-load 'php-mode - (define-key php-mode-map (kbd "M-j") nil) - (define-key php-mode-map (kbd "C-M-h") nil)) -#+END_SRC - -** Set Native - -Set keybinds to native functionality. - -*** Set Native Global Keybinds - -#+BEGIN_SRC emacs-lisp -;; Buffers -(global-set-key (kbd "C-x C-b") 'ibuffer) -(global-set-key (kbd "M-w") 'kill-buffer-and-window) - -;; Config edit/reload -(global-set-key (kbd "C-c r") 'config-reload) -(global-set-key (kbd "C-c v") 'config-visit) - -;; Find file -(global-set-key (kbd "C-x C-f") #'dot/find-file-in-project-root) - -;; Split and follow window -(global-set-key (kbd "C-x 2") 'split-follow-horizontally) -(global-set-key (kbd "C-x 3") 'split-follow-vertically) - -;; Terminal -(global-set-key (kbd "") 'ansi-term) -#+END_SRC - -*** Set Native Mode Keybinds - -#+BEGIN_SRC emacs-lisp -;; Dired -(with-eval-after-load 'dired - (define-key dired-mode-map [remap dired-find-file] #'dot/dired-find-file) - (define-key dired-mode-map [remap dired-up-directory] #'dot/dired-up-directory)) - -;; Org-mode -(with-eval-after-load 'org-capture - (define-key org-capture-mode-map (kbd "M-c") #'org-capture-finalize) - (define-key org-capture-mode-map (kbd "M-w") #'org-capture-refile) - (define-key org-capture-mode-map (kbd "M-k") #'org-capture-kill)) -(define-key org-mode-map (kbd "M-c") #'org-edit-special) -(define-key org-src-mode-map (kbd "M-c") #'org-edit-src-exit) -(define-key org-src-mode-map (kbd "M-k") #'org-edit-src-abort) -#+END_SRC - -** Set Package - -Set keybinds to functionality of installed packages. - -#+BEGIN_SRC emacs-lisp -;; Buffers -(global-set-key (kbd "M-h") #'centaur-tabs-backward-tab) -(global-set-key (kbd "M-j") #'centaur-tabs-forward-group) -(global-set-key (kbd "M-k") #'centaur-tabs-backward-group) -(global-set-key (kbd "M-l") #'centaur-tabs-forward-tab) -(global-set-key (kbd "M-H") #'centaur-tabs-move-current-tab-to-left) -(global-set-key (kbd "M-L") #'centaur-tabs-move-current-tab-to-right) -(global-set-key (kbd "M-\`") #'evil-switch-to-windows-last-buffer) - -(global-set-key (kbd "M-s") #'avy-goto-char-timer) -(global-set-key (kbd "M-x") #'dot/M-x) - -;; Company completion selection -(with-eval-after-load 'company - (define-key company-active-map (kbd "M-n") nil) - (define-key company-active-map (kbd "M-p") nil) - (define-key company-active-map (kbd "M-h") #'company-abort) - (define-key company-active-map (kbd "M-j") #'company-select-next) - (define-key company-active-map (kbd "M-k") #'company-select-previous) - (define-key company-active-map (kbd "M-l") #'company-complete-selection) - (define-key company-active-map (kbd "") #'company-abort)) - -;; Evil command history selection -(with-eval-after-load 'evil-ex - (define-key evil-ex-completion-map (kbd "M-h") #'abort-recursive-edit) - (define-key evil-ex-completion-map (kbd "M-j") #'next-complete-history-element) - (define-key evil-ex-completion-map (kbd "M-k") #'previous-complete-history-element) - (define-key evil-ex-completion-map (kbd "M-l") #'exit-minibuffer)) - -;; flyspell-correct -(with-eval-after-load 'flyspell-correct - (global-set-key [remap ispell-word] #'flyspell-correct-at-point)) ; z= - -;; Helpful overwrite default help functions -(global-set-key [remap describe-command] #'helpful-command) -(global-set-key [remap describe-function] #'helpful-callable) -(global-set-key [remap describe-key] #'helpful-key) -(global-set-key [remap describe-symbol] #'helpful-at-point) -(global-set-key [remap describe-variable] #'helpful-variable) -(which-key-add-key-based-replacements "C-h o" "describe-symbol-at-point") - -;; LSP -(with-eval-after-load 'lsp-mode - (define-key lsp-signature-mode-map (kbd "M-j") #'lsp-signature-next) - (define-key lsp-signature-mode-map (kbd "M-k") #'lsp-signature-previous)) - -;; Magit -(with-eval-after-load 'magit - (define-key magit-log-select-mode-map (kbd "M-c") #'magit-log-select-pick) - (define-key magit-log-select-mode-map (kbd "M-k") #'magit-log-select-quit)) - -;; Org-roam -(with-eval-after-load 'org-roam - (define-key org-roam-mode-map [down-mouse-1] #'org-roam-visit-thing)) - -;; Minibuffer completion selection -(general-def minibuffer-local-map - "M-h" #'abort-recursive-edit - "M-j" #'selectrum-next-candidate - "M-k" #'selectrum-previous-candidate - "M-l" #'selectrum-select-current-candidate - "M-J" #'next-history-element - "M-K" #'previous-history-element - "" #'dot/selectrum-backspace - "" #'evil-delete-backward-char-and-join) - -;; with-editor -(with-eval-after-load 'with-editor - (define-key with-editor-mode-map (kbd "M-c") 'with-editor-finish) - (define-key with-editor-mode-map (kbd "M-k") 'with-editor-cancel)) - -(with-eval-after-load 'evil-states - - ;; Global evil keymap - - (general-def evil-normal-state-map - "C-n" #'neotree-toggle-in-project-root - "C-S-p" #'evil-paste-pop-next - ) - - (general-def evil-insert-state-map - "" #'dot/evil-insert-shift-left ; - "TAB" #'dot/evil-insert-shift-right ; - ) - - (general-def evil-visual-state-map - "<" #'dot/evil-visual-shift-left ; " #'dot/evil-visual-shift-right ; >gv - ) - - ;; Custom (M-x customize) - (general-def 'normal custom-mode-map - [down-mouse-1] #'widget-button-click - ) - - ;; Dashboard - (general-def 'normal dashboard-mode-map - [down-mouse-1] 'widget-button-click - "g" #'dashboard-refresh-buffer - "m" #'dot/dashboard-goto-bookmarks - "p" #'dot/dashboard-goto-projects - "r" #'dot/dashboard-goto-recent-files - ) - - ;; Dap - (general-def 'normal dap-ui-session-mode-map - "D" #'dap-ui-delete-session - ) - - ;; Deft - (general-def 'normal deft-mode-map - [down-mouse-1] #'widget-button-click - "+" #'deft-new-file-named - "-" #'deft-new-file - "a" #'deft-archive-file - "c" #'deft-filter-clear - "d" #'deft-delete-file - "f" #'deft-find-file - "g" #'deft-refresh - "q" #'kill-this-buffer - "R" #'deft-rename-file - "s" #'deft-filter - "ts" #'deft-toggle-incremental-search :which-key "Toggle search" - "tt" #'deft-toggle-sort-method :which-key "Toggle sort" - ) - - ;; Elfeed - (general-def 'normal elfeed-search-mode-map - "b" 'elfeed-search-browse-url - "c" 'elfeed-search-clear-filter - "gr" '(elfeed-search-update--force :which-key "Refresh buffer") - "gR" '(elfeed-search-fetch :which-key "Update feeds") - "q" 'elfeed-search-quit-window - "u" 'elfeed-search-tag-all-unread - "U" nil - "r" 'elfeed-search-untag-all-unread - ) - - (general-def 'normal elfeed-show-mode-map - "b" #'elfeed-show-visit - "g" #'elfeed-show-refresh - "q" #'elfeed-kill-buffer - "u" #'elfeed-show-tag--unread - "y" #'elfeed-show-yank - ) - - ;; Magit - (general-def '(normal visual) magit-mode-map - "{" #'magit-section-backward-sibling - "}" #'magit-section-forward-sibling - ) - - ;; Minibuffer - (general-def 'normal minibuffer-local-map - "TAB" #'selectrum-insert-current-candidate - "j" #'selectrum-next-candidate - "k" #'selectrum-previous-candidate - "" #'selectrum-previous-candidate - "" #'selectrum-next-candidate - ) - (general-def 'insert minibuffer-local-map - "TAB" #'selectrum-insert-current-candidate - ) - - ;; Mu4e - (general-def 'normal mu4e-compose-mode-map - "q" #'mu4e-message-kill-buffer - "M-c" #'message-send-and-exit - "M-k" #'mu4e-message-kill-buffer - ) - - ;; Neotree - (general-def 'normal neotree-mode-map - "RET" 'neotree-enter - "" 'neotree-collapse-all ; - "c" 'neotree-create-node - "r" 'neotree-rename-node - "d" 'neotree-delete-node - "h" 'neotree-select-previous-sibling-node - "g" 'neotree-refresh - "j" 'neotree-next-line - "k" 'neotree-previous-line - "l" 'neotree-enter - "C" 'neotree-change-root - "H" 'neotree-hidden-file-toggle - "q" 'neotree-hide - ) - - ;; Org - (general-def 'normal org-mode-map - "RET" #'dot/org-ret-at-point) - (general-def 'insert org-mode-map - "RET" #'evil-ret) - (general-def 'motion org-agenda-mode-map - "RET" #'org-agenda-switch-to) - - ;; Wdired - (with-eval-after-load 'wdired - (general-def '(normal insert) wdired-mode-map - "M-c" #'wdired-finish-edit - "M-k" #'wdired-abort-changes - )) - ) -#+END_SRC - -** Leader - -General.el ~leader key binds. - -*** Global Leader - -#+BEGIN_SRC emacs-lisp -(general-create-definer space-leader - :prefix dot/leader-key - :non-normal-prefix dot/leader-alt-key - :global-prefix dot/leader-alt-key - :states '(normal visual insert motion emacs) - :keymaps 'override) ; prevent leader keybindings from ever being overridden - -(space-leader - "SPC" '(dot/M-x :which-key "Execute command") - "RET" '(consult-bookmark :which-key "Go to bookmark") - - ;; Apps - "a" '(:ignore t :which-key "apps") - "a d" '(deft :which-key "Deft") - "a e" '(elfeed :which-key "Elfeed") - - ;; Buffer / bookmark - "b" '(:ignore t :which-key "buffer/bookmark") - "b a" '(auto-revert-mode :which-key "Auto revert buffer") - "b b" '(consult-buffer :which-key "Switch buffer") - "b d" '(dot/dashboard-goto :which-key "Dashboard") - "b k" '(kill-current-buffer :which-key "Kill buffer") - "b m" '(bookmark-set :which-key "Make bookmark") - "b n" '(evil-buffer-new :which-key "New empty buffer") - "b r" '(revert-buffer :which-key "Revert buffer") - "b s" '(basic-save-buffer :which-key "Save buffer") - "b B" '(ibuffer :which-key "List buffers") - "b C" '(dot/centaur-tabs-buffer-cleanup :which-key "Cleanup buffers") - "b M" '(bookmark-delete :which-key "Delete bookmark") - "b S" '(evil-write-all :which-key "Save all buffers") - "b " '(previous-buffer :which-key "Previous buffer") - "b " '(next-buffer :which-key "Next buffer") - - ;; Comments - "c" '(:ignore t :which-key "comment/config") - "c c" '(evilnc-comment-or-uncomment-lines :which-key "Toggle comment") - "c p" '(evilnc-comment-or-uncomment-paragraphs :which-key "Toggle comment paragraph") - "c y" '(evilnc-comment-and-kill-ring-save :which-key "Comment and copy") - - ;; Elisp - "e" '(:ignore t :which-key "elisp") - "e ;" '(eval-expression :which-key "Evaluate expression") - "e b" '(eval-buffer :which-key "Evaluate buffer") - "e e" '(eval-last-sexp :which-key "Evaluate last sexp") - "e r" '(eval-region :which-key "Evaluate region") - "e t" '(dot/reload-theme :which-key "Reload theme") - - ;; File - "f" '(:ignore t :which-key "file") - "f d" '(dired :which-key "Find directory") - "f f" '(dot/find-file-in-project-root :which-key "Find file") - "f o" '(ff-find-other-file :which-key "Find header/source file") - "f r" '(consult-recent-file :which-key "Find recent file") - "f R" '(rename-file-and-buffer :which-key "Rename file") - "f s" '(basic-save-buffer :which-key "Save file") - "f S" '(write-file :which-key "Save file as...") - "f u" '(dot/sudo-find-file :which-key "Sudo find file") - "f U" '(dot/sudo-this-file :which-key "Sudo this file") - "f e" '(:ignore t :which-key "emacs") - "f e c" '(dot/config-visit :which-key "Config visit") - "f e f" '(dot/find-file-emacsd :which-key "Find emacs file") - "f e r" '(dot/config-reload :which-key "Config reload") - - ;; Go to - "g" '(:ignore t :which-key "goto") - "g b" '(consult-bookmark :which-key "Go to bookmark") - "g f" '(consult-flycheck :which-key "Go to flycheck error") - "g m" '(consult-mark :which-key "Go to marker") - - ;; Help - "h" '(:keymap help-map :which-key "help") - "h o" '(:ignore t :which-key "describe-symbol-at-point") - - ;; Insert - "i" '(:ignore t :which-key "insert") - "i b" '(dot/indent-buffer :which-key "Indent buffer") - "i f" '(fill-region :which-key "Reflow region") - "i F" '(fill-paragraph :which-key "Reflow paragraph") - "i r" '(indent-region :which-key "Indent region") - "i s" '(dot/evil-normal-sort-paragraph :which-key "Sort paragraph") - "i S" '(dot/insert-spaces-until-column :which-key "Insert spaces") - "i y" '(yas-insert-snippet :which-key "Insert yasnippet") - - ;; Notes - "n" '(:ignore t :which-key "notes") - "n a" '(org-agenda :which-key "Org agenda") - "n r" '(:ignore t :which-key "org-roam") - "n r c" '(org-roam-capture :which-key "Capture") - "n r C" '(org-roam-db-sync :which-key "Build cache") - "n r f" '(org-roam-node-find :which-key "Find node") - "n r g" '(org-roam-graph :which-key "Show graph") - "n r i" '(org-roam-node-insert :which-key "Insert") - "n r I" '(dot/org-roam-node-insert-immediate :which-key "Insert (without capture)") - "n r r" '(org-roam-buffer-toggle :which-key "Toggle buffer") - "n r s" '(org-roam-ui-mode :which-key "Toggle server") - - ;; Project - "p" '(:keymap project-prefix-map :which-key "project") - "p b" '(consult-project-buffer :which-key "project-switch-buffer") - "p f" '(consult-project-extra-find :which-key "project-find-file") - "p g" '(consult-grep :which-key "project-find-regexp") - - ;; Quit - "q" '(:ignore t :which-key "quit") - "q q" '(save-buffers-kill-terminal :which-key "Quit Emacs") - "q Q" '(save-buffers-kill-emacs :which-key "Quit Emacs (and daemon)") - "q f" '(delete-frame :which-key "Close frame") - "q o" '(delete-other-frames :which-key "Close other frames") - - ;; Search - "s" '(:ignore t :which-key "search") - "s a" '(avy-goto-char-timer :which-key "Avy goto char") - "s f" '(consult-find :which-key "Search file") - "s l" '(avy-goto-line :which-key "Avy goto line") - "s p" '(consult-grep :which-key "Search project") - "s q" '(evil-ex-nohighlight :which-key "Stop search") - "s s" '(consult-line :which-key "Search buffer") - - ;; Tabs / toggle - "t" '(:ignore t :which-key "tabs/toggle") - "t f" '(dot/toggle-fringe :which-key "Toggle fringe") - "t g" '(centaur-tabs-switch-group :which-key "Switch tab group") - "t h" '(centaur-tabs-backward-group :which-key "Tab backward group") - "t j" '(centaur-tabs-select-end-tab :which-key "Tab select first") - "t k" '(centaur-tabs-select-beg-tab :which-key "Tab select last") - "t l" '(centaur-tabs-forward-group :which-key "Tab forward group") - "t n" '(neotree-toggle-in-project-root :which-key "Toggle Neotree") - "t s" '(dot/flyspell-toggle :which-key "Toggle spell checker") - "t w" '(visual-line-mode :which-key "Toggle line wrapping") - - ;; Update packages - "U" '(dot/update-packages :which-key "Update packages") - - ;; Version control - "v" '(:ignore t :which-key "git") - "v b" '(magit-branch-checkout :which-key "Magit switch branch") - "v B" '(magit-blame-addition :which-key "Magit blame") - "v C" '(magit-clone :which-key "Magit clone") - "v F" '(magit-fetch :which-key "Magit fetch") - "v L" '(magit-log :which-key "Magit log") - "v s" '(magit-show-commit :which-key "Magit show commit") - "v S" '(magit-stage-file :which-key "Stage file") - "v U" '(magit-unstage-file :which-key "Unstage file") - "v v" '(magit-status :which-key "Magit status") - "v V" '(magit-status-here :which-key "Magit status here") - "v c" '(:ignore t :which-key "create") - "v c c" '(magit-commit-create :which-key "Commit") - "v c b" '(magit-branch-and-checkout :which-key "Branch") - "v c r" '(magit-init :which-key "Initialize repo") - "v f" '(:ignore t :which-key "file") - "v f c" '(magit-find-git-config-file :which-key "Find gitconfig file") - "v f D" '(magit-file-delete :which-key "Delete file") - "v f f" '(magit-find-file :which-key "Find file") - "v f R" '(magit-file-rename :which-key "Rename file") - "v l" '(:ignore t :which-key "list") - "v l r" '(magit-list-repositories :which-key "List repositories") - "v l s" '(magit-list-submodules :which-key "List submodules") - "v r" '(dot/magit-select-repo :which-key "Select repo") - - ;; Window - "w" '(:ignore t :which-key "window") - "w +" '(evil-window-increase-height :which-key "Increase window height") - "w -" '(evil-window-decrease-height :which-key "Decrease window height") - "w <" '(evil-window-decrease-width :which-key "Decrease window width") - "w =" '(balance-windows :which-key "Balance windows") - "w >" '(evil-window-increase-width :which-key "Increase window width") - "w _" '(evil-window-set-height :which-key "Maximize window height") - "w h" '(windmove-left :which-key "Focus window left") - "w j" '(windmove-down :which-key "Focus window down") - "w k" '(windmove-up :which-key "Focus window up") - "w l" '(windmove-right :which-key "Focus window right") - "w o" '(delete-other-windows :which-key "Close other windows") - "w s" '(split-follow-horizontally :which-key "Split horizontal") - "w v" '(split-follow-vertically :which-key "Split vertical") - "w w" '(other-window :which-key "Focus other window") - "w q" '(dot/centaur-tabs-kill-buffer-or-window :which-key "Close window") - "w r" '(winner-redo :which-key "Redo window configuration") - "w u" '(winner-undo :which-key "Undo window configuration") - "w " '(windmove-left :which-key "Focus window left") - "w " '(windmove-right :which-key "Focus window right") - "w " '(windmove-up :which-key "Focus window up") - "w " '(windmove-down :which-key "Focus window down") - ) -#+END_SRC - -Evaluated keybinds. - -#+BEGIN_SRC emacs-lisp -(with-eval-after-load 'lsp-mode - (space-leader lsp-mode-map - "l" lsp-command-map - "l = f" '(dot/lsp-format-buffer-or-region :which-key "format buffer or region") - )) - -(with-eval-after-load 'dap-mode - (space-leader lsp-mode-map - "l d" '(dap-hydra :which-key "DAP hydra") - )) -#+END_SRC - -Source: -https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-evil.el#L712 -https://github.com/suyashbire1/emacs.d/blob/master/init.el - -*** Local Leader - -#+BEGIN_SRC emacs-lisp -(general-create-definer local-leader - :prefix dot/localleader-key - :non-normal-prefix dot/localleader-alt-key - :global-prefix dot/localleader-alt-key - :states '(normal visual insert motion emacs) - :keymaps 'override ; prevent leader keybindings from ever being overridden - "" '(:ignore t :which-key "") - ) - -(local-leader c++-mode-map - "i" '(:ignore t :which-key "insert") - "i i" '(dot/copy-cpp-function-implementation :which-key "Copy function implementation") - ) - -(local-leader org-mode-map - "'" '(org-edit-special :which-key "Org edit") - "e" '(org-export-dispatch :which-key "Org export") - "o" '(org-open-at-point :which-key "Org open at point") - "q" '(org-set-tags-command :which-key "Org tags") - - "g" '(:ignore t :which-key "goto") - "g o" '(consult-outline :which-key "Org go to heading") - - "i" '(:ignore t :which-key "insert") - "i c" '(org-table-insert-column :which-key "Insert table column") - "i h" '(org-table-insert-hline :which-key "Insert table hline") - "i H" '(org-table-hline-and-move :which-key "Insert table hline and move") - "i r" '(org-table-insert-row :which-key "Insert table row") - "i t" '(org-insert-structure-template :which-key "Insert template") - - "l" '(:ignore t :which-key "links") - "l i" '(org-id-store-link :which-key "Store ID link") - "l l" '(org-insert-link :which-key "Insert link") - "l s" '(org-store-link :which-key "Store link") - "l S" '(org-insert-last-stored-link :which-key "Insert stored link") - - "s" '(:ignore t :which-key "tree/subtree") - "s h" '(org-promote-subtree :which-key "Org promote subtree") - "s j" '(org-metadown :which-key "Org move subtree down") - "s k" '(org-metaup :which-key "Org move subtree up") - "s l" '(org-demote-subtree :which-key "Org demote subtree") - "s " '(org-promote-subtree :which-key "Org promote subtree") - "s " '(org-demote-subtree :which-key "Org demote subtree") - "s " '(org-move-subree-up :which-key "Org move subtree up") - "s " '(org-move-subtree-down :which-key "Org move subtree down") - - "t" '(:ignore t :which-key "toggle") - "t t" '(org-todo :which-key "Org todo state") - "t l" '(org-toggle-link-display :which-key "Org link display") - ) - -(local-leader org-src-mode-map - "k" '(org-edit-src-abort :which-key "Org Edit abort")) - -(local-leader elfeed-search-mode-map - "g" '(elfeed-search-update--force :which-key "Elfeed refresh buffer") - "G" '(elfeed-search-fetch :which-key "Elfeed update feeds") - ) - -(local-leader elfeed-show-mode-map - "g" '(elfeed-show-refresh :which-key "Elfeed refresh buffer") - ) - -;; c-fill-paragraph Reflow comment -;; https://youtu.be/hbmV1bnQ-i0?t=1910 -#+END_SRC - -* Notes - -Org mode keybinds: - -| Keystroke | Description | Function | -|----------------+----------------------------+--------------------------------------| -| | Update tags/headline | (org-ctrl-c-ctrl-c) | -| | Insert heading | (org-insert-heading-respect-content) | -| | ? | (org-narrow-to-subtree) | -| | ? | (widen) | -| | Insert heading | (org-meta-return) | -| | Insert todo heading | (org-insert-todo-heading) | -| | Move subtree down | (org-metadown) | -| | Promote heading | (org-metaleft) | -| | Demote heading | (org-metaright) | -| | Move subtree up | (org-metaup) | -| | Cycle to next todo keyword | (org-shiftleft/org-shiftright) | -| | Cycle todo priority | (org-shiftup/org-shiftdown) | diff --git a/.config/emacs/config/development.org b/.config/emacs/config/development.org deleted file mode 100644 index f917b8f..0000000 --- a/.config/emacs/config/development.org +++ /dev/null @@ -1,471 +0,0 @@ -#+TITLE: Development -#+OPTIONS: toc:nil -#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n" - -** Table of Contents :toc_4: - - [[#company][Company]] - - [[#git][Git]] - - [[#project][Project]] - - [[#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")) - (setq transient-values-file (concat dot-cache-dir "/transient/values.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 72) - (setq magit-completing-read-function #'selectrum-completing-read) - (setq magit-diff-paint-whitespace-lines 'both) - (setq magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1) - (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]) - - (defun dot/magit-select-repo () - "Select project repo." - (interactive) - (let ((current-prefix-arg '(t))) - (call-interactively #'magit-status)))) -#+END_SRC - -** Project - -Project manager. - -[[https://michael.stapelberg.ch/posts/2021-04-02-emacs-project-override/][Adding to project.el project directory detection]]. - -#+BEGIN_SRC emacs-lisp -(use-package project - :defer t - :init (setq project-list-file (concat dot-cache-dir "/projects")) - :config - (defun dot/project-find (dir) - (let ((root (locate-dominating-file dir ".project"))) - (and root (cons 'vc root)))) - (add-hook 'project-find-functions #'dot/project-find) - - (defun dot/find-project-root () - "Return root of the project, determined by `.git/' and `.project', -`default-directory' otherwise." - (let ((project (project-current))) - (if project - (project-root project) - 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))) - - (defun dot/project-remember-projects-under (dir maxdepth) - "Index all projects below directory DIR recursively, until MAXDEPTH." - (let ((files (mapcar 'file-name-directory - (dot/directory-files-recursively-depth - dir "\\.git$\\|\\.project$" t maxdepth)))) - (dolist (path files) - (project-remember-projects-under path)))) - - (unless (file-exists-p project-list-file) - (project-remember-projects-under "~/dotfiles") - (dot/project-remember-projects-under "~/code" 4)) - - (defun dot/project-project-name () - "Return project name." - (let ((project (project-current))) - (if project - (file-name-nondirectory (directory-file-name (project-root project))) - "-"))) - - (defun dot/project-save-project-buffers () - "Save all project buffers." - (interactive) - (let ((buffers (cl-remove-if (lambda (buffer) (not (buffer-file-name buffer))) - (project-buffers (project-current))))) - (save-some-buffers t (lambda () (member (current-buffer) buffers)))))) -#+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" - "--enable-config")) - (setq lsp-clients-lua-language-server-bin "/usr/bin/lua-language-server") - (setq lsp-clients-lua-language-server-install-dir "/usr/lib/lua-language-server/") - (setq lsp-clients-lua-language-server-main-location "/usr/lib/lua-language-server/main.lua") - (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 dot/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))) - - ;; This is cached to prevent unneeded I/O - (setq lsp-in-cpp-project-cache nil) - (defun dot/lsp-format-cpp-buffer () - "Format buffer in C++ projects." - (unless lsp-in-cpp-project-cache - (set (make-local-variable 'lsp-in-cpp-project-cache) - (list - (if (and (eq major-mode 'c++-mode) - (bound-and-true-p lsp-mode) - (or - (locate-dominating-file "." ".clang-format") - (locate-dominating-file "." "_clang-format"))) - t - nil)))) - (when (car lsp-in-cpp-project-cache) - (lsp-format-buffer))) - (add-hook 'before-save-hook #'dot/lsp-format-cpp-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++20") - (setq flycheck-gcc-language-standard "c++20")) - -;; 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) - - (defun dot/flyspell-toggle () - "Toggle Flyspell, prompt for language." - (interactive) - (if (symbol-value flyspell-mode) - (flyspell-mode -1) - (call-interactively 'ispell-change-dictionary) - (if (derived-mode-p 'prog-mode) - (flyspell-prog-mode) - (flyspell-mode)) - (flyspell-buffer)))) -#+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 diff --git a/.config/emacs/config/evil.org b/.config/emacs/config/evil.org deleted file mode 100644 index 16f8977..0000000 --- a/.config/emacs/config/evil.org +++ /dev/null @@ -1,108 +0,0 @@ -#+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 - (setq undo-tree-auto-save-history t) - (setq undo-tree-history-directory-alist `(("." . ,(concat dot-cache-dir "/undo-tree")))) - (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" - (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: " - (interactive) - (evil-shift-left-line 1)) - - (defun dot/evil-insert-shift-right () - "Shift line right, retains cursor position. - -Vim equivalence: " - (interactive) - (insert "\t")) - - (defun dot/evil-visual-shift-left () - "Shift visual selection left, retains the selection. - -Vim equivalence: gv" - (interactive) - (call-interactively #'evil-shift-right) - (setq deactivate-mark nil)) - - (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 diff --git a/.config/emacs/config/mail.org b/.config/emacs/config/mail.org deleted file mode 100644 index c9cba49..0000000 --- a/.config/emacs/config/mail.org +++ /dev/null @@ -1,157 +0,0 @@ -#+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 diff --git a/.config/emacs/config/org-mode.org b/.config/emacs/config/org-mode.org deleted file mode 100644 index c1ab6c5..0000000 --- a/.config/emacs/config/org-mode.org +++ /dev/null @@ -1,331 +0,0 @@ -#+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) - (setq tex-indent-basic 4))) - :config - - (with-eval-after-load 'project - (defun compile-latex () - "Compile LaTeX project." - (interactive) - (let ((default-directory (dot/find-project-root))) - (dot/project-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")) - ;; Add -shell-escape so pdflatex exports minted correctly - (setcar org-latex-pdf-process (replace-regexp-in-string - "-%latex -interaction" - "-%latex -shell-escape -interaction" - (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 - table -- go to next row - 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)) - ('table-cell (org-table-next-row)) - (_ (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 diff --git a/.config/emacs/config/selection.org b/.config/emacs/config/selection.org deleted file mode 100644 index 477adab..0000000 --- a/.config/emacs/config/selection.org +++ /dev/null @@ -1,52 +0,0 @@ -#+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-narrow-key (kbd "?"))) - -(use-package consult-flycheck - :after (consult flycheck)) - -(use-package consult-project-extra - :after (consult project) - :config (setq project-switch-commands 'consult-project-extra-find)) -#+END_SRC diff --git a/.config/emacs/config/ui.org b/.config/emacs/config/ui.org deleted file mode 100644 index 12c0257..0000000 --- a/.config/emacs/config/ui.org +++ /dev/null @@ -1,253 +0,0 @@ -#+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 38 18)) - (setq centaur-tabs-modified-marker "•") - (setq centaur-tabs-set-icons t) - (setq centaur-tabs-set-modified-marker t) - (setq centaur-tabs-style "slant") - - (setq centaur-tabs-project-buffer-group-calc nil) - (defun centaur-tabs-buffer-groups () - "Organize tabs into groups by buffer." - (unless centaur-tabs-project-buffer-group-calc - (set (make-local-variable 'centaur-tabs-project-buffer-group-calc) - (list - (cond - ((string-equal "*" (substring (buffer-name) 0 1)) "Emacs") - ((or (memq major-mode '(magit-process-mode - magit-status-mode - magit-diff-mode - magit-log-mode - magit-file-mode - magit-blob-mode - magit-blame-mode)) - (string= (buffer-name) "COMMIT_EDITMSG")) "Magit") - ((project-current) (dot/project-project-name)) - ((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 "Other"))))) - (symbol-value 'centaur-tabs-project-buffer-group-calc)) - - (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 matches below blacklist - (string-match-p "^ ?\\*.*\\*" 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-projects-backend 'project-el) - (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 'project - (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 30 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-project-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 diff --git a/.config/emacs/early-init.el b/.config/emacs/early-init.el index 2bf731b..9a08cd5 100644 --- a/.config/emacs/early-init.el +++ b/.config/emacs/early-init.el @@ -23,19 +23,8 @@ ;; Prefer to `load' the newest elisp file (setq load-prefer-newer t) -;; Set package install location -(setq package-user-dir (concat user-emacs-directory "elpa")) - -;; Set package quickstart location -(setq package-quickstart-file (concat - (getenv "XDG_CACHE_HOME") - "/emacs/package-quickstart.el")) - -;; Precompute activation actions to speed up startup -(setq package-quickstart t) - -;; Native compilation -(setq package-native-compile t) +;; Disable package.el +(setq package-enable-at-startup nil) ;; ------------------------------------- diff --git a/.config/emacs/init.el b/.config/emacs/init.el index 3924364..2c90c7e 100644 --- a/.config/emacs/init.el +++ b/.config/emacs/init.el @@ -2,31 +2,23 @@ ;;; Commentary: -;; Setup package archives and build configuration file. +;; Load modules. ;;; Code: -(require 'package) +;; ----------------------------------------- -;; Add the MELPA repository to the package manager -(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) +(add-to-list 'load-path (locate-user-emacs-file "site-lisp")) -;; Install the `use-package' dependency -(unless (package-installed-p 'use-package) - (package-refresh-contents) - (package-install 'use-package)) +(require 'dot-elpaca) +(require 'dot-setup-el) -(use-package benchmark-init - :ensure t - :config - ;; To disable collection of benchmark data after init is complete - (add-hook 'after-init-hook 'benchmark-init/deactivate)) - -;; ------------------------------------- - -;; Tangle and load configuration file -(require 'org) -(when (file-readable-p (concat user-emacs-directory "config.org")) - (org-babel-load-file (concat user-emacs-directory "config.org"))) - -;;; init.el ends here +(require 'dot-core) +(require 'dot-ui) +(require 'dot-evil) +(require 'dot-development) +(require 'dot-selection) +(require 'dot-org-mode) +(require 'dot-mail) +(require 'dot-rss) +(require 'dot-keybinds) diff --git a/.config/emacs/site-lisp/core/dot-core-advice.el b/.config/emacs/site-lisp/core/dot-core-advice.el new file mode 100644 index 0000000..4eb2dd3 --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-advice.el @@ -0,0 +1,25 @@ +;;; dot-core-advice.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Advice and Aliases. + +;;; Code: + +;; ----------------------------------------- + +;; Advice + +;; Define default terminal option. +(defun dot/ansi-term (program &optional new-buffer-name) + (interactive (list dot/shell))) +(advice-add 'ansi-term :before #'dot/ansi-term) + +;; Aliases + +;; Make confirm easier, by just pressing y/n. +(defalias 'yes-or-no-p 'y-or-n-p) + +(provide 'dot-core-advice) + +;;; dot-core-advice.el ends here diff --git a/.config/emacs/site-lisp/core/dot-core-config.el b/.config/emacs/site-lisp/core/dot-core-config.el new file mode 100644 index 0000000..46e504d --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-config.el @@ -0,0 +1,244 @@ +;;; dot-core-config.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; ?? + +;;; Code: + +;; ----------------------------------------- +;; General + +;; Columns start at 1 +(setq column-number-indicator-zero-based nil) +;; TODO: Make variable below compatible with telephone-line +;; (setq mode-line-position-column-format " C%C") + +;; Dont confirm on quitting Emacs +(setq confirm-kill-processes nil) + +;; Custom thems, do not ask if safe +(setq custom-safe-themes t) + +;; Dired move to trash +(setq delete-by-moving-to-trash t) + +;; Column indicator character +(setq display-fill-column-indicator-character ?\N{U+2503}) + +;; Scrolling +(setq scroll-conservatively 1) +(setq mouse-wheel-scroll-amount '(5)) +(setq mouse-wheel-progressive-speed nil) + +;; Parenthesis, set behavior +(setq show-paren-delay 0) +(setq show-paren-style 'mixed) + +;; Tramp default protocol +(setq tramp-default-method "ssh") + +;; Set undo limit, measured in bytes +(setq-default undo-limit 400000) +(setq-default undo-strong-limit 3000000) +(setq-default undo-outer-limit 12000000) + +;; Enable line numbers +(global-display-line-numbers-mode) + +;; C++ syntax highlighting for .h files +(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode)) + +;; Set the frame title +(setq frame-title-format + `("%b" + (:eval + (if (buffer-file-name) + (concat + (if (buffer-modified-p) " •" nil) + " (" + (abbreviate-file-name + (directory-file-name + (file-name-directory (buffer-file-name)))) + ")") + nil)) + ,(format " - GNU Emacs %s" emacs-version) + )) +(setq icon-title-format frame-title-format) + +;; ----------------------------------------- +;; Buffers + +(setq confirm-nonexistent-file-or-buffer nil) +(setq ibuffer-expert t) + +;; ----------------------------------------- +;; Dired + +(setq wdired-allow-to-change-permissions t) + +;; ----------------------------------------- +;; Electric + +;; Make return key also do indent of previous line +(electric-indent-mode 1) +(setq electric-pair-pairs '( + (?\( . ?\)) + (?\[ . ?\]) + )) +(electric-pair-mode 1) + +;; ----------------------------------------- +;; File Paths + +;; Set file paths for built-in features like: auto-saves, backups, etc. + +;; Set Directory locations +(setq auto-save-list-file-prefix (expand-file-name "auto-save/" dot-cache-dir)) +(setq auto-save-file-name-transforms `((".*" ,auto-save-list-file-prefix t))) +(setq backup-directory-alist `((".*" . ,(expand-file-name "backup/" dot-cache-dir)))) +(setq custom-theme-directory (expand-file-name "themes/" dot-emacs-dir)) +(setq eshell-directory-name (expand-file-name "eshell/" dot-cache-dir)) +(setq tramp-auto-save-directory (expand-file-name "tramp-auto-save/" dot-cache-dir)) +(setq tramp-backup-directory-alist backup-directory-alist) +(setq url-configuration-directory (expand-file-name "url/" dot-cache-dir)) + +;; Set file locations +(setq bookmark-default-file (expand-file-name "bookmarks" dot-etc-dir)) +(setq nsm-settings-file (expand-file-name "network-security.data" dot-cache-dir)) +(setq org-id-locations-file (expand-file-name "org-id-locations" dot-cache-dir)) +(setq tramp-persistency-file-name (expand-file-name "tramp" dot-cache-dir )) + +;; ----------------------------------------- +;; File Backups Versioning + +;; Setup file backups versioning. + +(setq backup-by-copying t) ; Don't cobbler symlinks +(setq create-lockfiles nil) ; Disable lockfiles (.#) +(setq delete-old-versions t) ; Cleanup backups +(setq kept-new-versions 5) ; Newest backups to keep +(setq kept-old-versions 2) ; Oldest backups to keep +(setq version-control t) ; Use version numbers on backups + +;; ----------------------------------------- +;; Formatting + +;; Columnn after line-wrapping happens +(setq-default fill-column 80) + +;; Automatically add newline on save at the end of the file +(setq require-final-newline t) + +;; End sentences with a single space +(setq sentence-end-double-space nil) + +;; `tabify' and `untabify' should only affect indentation +(setq tabify-regexp "^\t* [ \t]+") + +;; Do not wrap lines +(setq-default truncate-lines t) + +;; Wrap lines in the middle of words, gives a \ indicator +(setq-default word-wrap nil) + +;; ----------------------------------------- +;; Hide Elements + +(menu-bar-mode 0) +(scroll-bar-mode 0) +(tool-bar-mode 0) +(tooltip-mode 0) +(fringe-mode 0) +(blink-cursor-mode 0) + +(setq inhibit-startup-message t) +(setq initial-scratch-message nil) +(setq ring-bell-function 'ignore) + +;; ----------------------------------------- +;; Native Compilation + +(setq native-comp-async-report-warnings-errors nil) + +;; ----------------------------------------- +;; Recentf + +(elpaca nil (setup recentf ; built-in + (:require recentf) + (:when-loaded + (setq recentf-auto-cleanup 'never) + (setq recentf-exclude '("~$" "/ssh:" "/sudo:")) + (setq recentf-filename-handlers '(abbreviate-file-name)) + (setq recentf-max-menu-items 0) + (setq recentf-max-saved-items 200) + (setq recentf-save-file (expand-file-name "recentf" dot-cache-dir)) + (recentf-mode)))) + +;; ----------------------------------------- +;; Tabs + +;; Tabs +(setq-default tab-width 4 + indent-tabs-mode t + c-basic-offset 4 + sgml-basic-offset 4 + sh-basic-offset 4) + +;; C/C++-like languages formatting style +;; https://www.emacswiki.org/emacs/IndentingC +;; https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html#Getting-Started +;; https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html#Adding-Styles +;; https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html#Sample-Init-File +(c-add-style "user" `("linux" + (c-basic-offset . ,(default-value 'tab-width)) + (c-offsets-alist + (innamespace . -) + ))) +(setq-default c-default-style "user") + +;; ----------------------------------------- +;; UTF-8 + +;; Set UTF-8 encoding as default. + +(prefer-coding-system 'utf-8-unix) +(setq locale-coding-system 'utf-8-unix) +;; Default also sets file-name, keyboard and terminal coding system +(set-default-coding-systems 'utf-8-unix) +(set-buffer-file-coding-system 'utf-8-unix) +(set-selection-coding-system 'utf-8-unix) + +;; ----------------------------------------- +;; Window + +;; Set `switch-to-buffer' to respect the window rules +(setq switch-to-buffer-obey-display-actions t) + +;; Window rules +(setq display-buffer-alist + '( + ;; ^\*(e?shell|(ansi-|v)?term).* + ("^\\*\\(e?shell\\|\\(ansi-\\|v\\)?term\\).*" + (display-buffer-in-side-window) + (window-height . 0.25) + (side . bottom) + (slot . -1)) + ("\\*Faces\\*" + (display-buffer-in-side-window) + (window-height . 0.25) + (side . bottom) + (slot . 1)) + ("\\*Help.*" + (display-buffer-in-side-window) + (window-height . 0.25) + (side . bottom) + (slot . 0)) + )) + +;; Allow 'undo' and 'redo' changes in Window Configuration. +(winner-mode) + +(provide 'dot-core-config) + +;;; dot-core-config.el ends here diff --git a/.config/emacs/site-lisp/core/dot-core-customize.el b/.config/emacs/site-lisp/core/dot-core-customize.el new file mode 100644 index 0000000..6b69cb2 --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-customize.el @@ -0,0 +1,19 @@ +;;; dot-core-customize.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; ?? + +;;; Code: + +;; ----------------------------------------- +;; Customizations + +;; Store customize file separately, don't freak out when it's not found. + +(setq custom-file (expand-file-name "custom.el" dot-etc-dir)) +(load custom-file 'noerror) + +(provide 'dot-core-customize) + +;;; dot-core-customize.el ends here diff --git a/.config/emacs/site-lisp/core/dot-core-fonts.el b/.config/emacs/site-lisp/core/dot-core-fonts.el new file mode 100644 index 0000000..b648947 --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-fonts.el @@ -0,0 +1,17 @@ +;;; dot-core-fonts.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; ?? + +;;; Code: + +;; ----------------------------------------- +;; Set fonts + +(set-face-attribute 'default nil :height 90 :family "DejaVu Sans Mono") +(set-face-attribute 'fixed-pitch-serif nil :height 100) + +(provide 'dot-core-fonts) + +;;; dot-core-fonts.el ends here diff --git a/.config/emacs/site-lisp/core/dot-core-functions.el b/.config/emacs/site-lisp/core/dot-core-functions.el new file mode 100644 index 0000000..502c01d --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-functions.el @@ -0,0 +1,195 @@ +;;; dot-core-functions.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Custom elisp functions and macros. + +;;; Code: + +;; ----------------------------------------- +;; General Functions + +;; Functions that only use built-in Emacs functionality. + +(defun display-startup-echo-area-message () + "Hide default startup message." + (message nil)) + +(defun dot/config-visit () + "Edit config file." + (interactive) + (find-file (expand-file-name "init.el" dot-emacs-dir))) + +(defun dot/config-reload () + "Reload config file." + (interactive) + (load (expand-file-name "init.el" dot-emacs-dir))) + +(defun dot/copy-cpp-function-implementation () + "Copy C++ function implementation to clipboard." + (interactive) + (save-excursion + (let ((func (save-excursion + (re-search-backward "\\b") + (re-search-forward "\\([^;]+\\);") + (match-string 1))) + (type (progn + (re-search-backward "\\b") + (push-mark) + (back-to-indentation) + (buffer-substring (mark) (point)))) + (class (progn + (backward-up-list) + (backward-sexp) + (back-to-indentation) + (forward-to-word 1) + (current-word)))) + (kill-new (concat type class "::" func "\n{\n}")))) + (message "Copied function implementation")) + +;; Reference: http://turingmachine.org/bl/2013-05-29-recursively-listing-directories-in-elisp.html +(defun dot/directory-files-recursively-depth (dir regexp include-directories maxdepth) + "Depth limited variant of the built-in `directory-files-recursively'." + (let ((result '()) + (current-directory-list (directory-files dir t))) + (dolist (path current-directory-list) + (cond + ((and (file-regular-p path) + (file-readable-p path) + (string-match regexp path)) + (setq result (cons path result))) + ((and (file-directory-p path) + (file-readable-p path) + (not (string-equal "/.." (substring path -3))) + (not (string-equal "/." (substring path -2)))) + (when (and include-directories + (string-match regexp path)) + (setq result (cons path result))) + (when (> maxdepth 1) + (setq result (append (nreverse (dot/directory-files-recursively-depth + path regexp include-directories (- maxdepth 1))) + result)))) + (t))) + (reverse result))) + +(defun dot/dired-find-file () + "In Dired, visit the file or directory named on this line." + (interactive) + (if (file-directory-p (dired-file-name-at-point)) + (dired-find-alternate-file) + (dired-find-file))) + +(defun dot/dired-up-directory () + "Run Dired on parent directory of current directory." + (interactive) + (find-alternate-file "..")) + +(defun dot/find-file-emacsd () + "Find file under `dot-emacs-dir', recursively." + (interactive) + (let ((files (mapcar 'abbreviate-file-name + (directory-files-recursively dot-emacs-dir "")))) + (find-file (completing-read "Find file (emacs): " files nil t)))) + +(defun dot/indent-buffer () + "Indent each nonblank line in the buffer." + (interactive) + (save-excursion + (indent-region (point-min) (point-max) nil))) + +(defun dot/insert-spaces-until-column (until-column) + "Insert spaces from point to UNTIL-COLUMN." + (interactive "nInsert spaces until column: ") + (let ((current-column (current-column))) + ;; Increment column if the index is 1 based + (when (not column-number-indicator-zero-based) + (setq current-column (+ current-column 1))) + ;; Insert spaces + (let ((diff (- until-column current-column))) + (if (> diff 0) + (save-excursion (insert (make-string diff ?\ ))) + (user-error "Column should be higher than point"))))) + +(defun dot/reload-theme () + "Reload custom theme." + (interactive) + (mapc 'load (file-expand-wildcards + (concat (car custom-theme-load-path) "*.el"))) + (load-theme (car custom-enabled-themes) t)) + +(defun dot/sudo-find-file (filename) + "Edit file FILENAME as root." + (interactive "FOpen file (as root): ") + (find-file (concat "/sudo:root@localhost:" filename))) + +(defun dot/sudo-this-file () + "Edit the current file as root." + (interactive) + (if buffer-file-name + (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)) + (princ "Current buffer isn't a file"))) + +(defun dot/toggle-fringe (&optional arg) + "Toggle left-only fringe, or set state with ARG." + (interactive) + (if (or (and (eq fringe-mode 0) (eq arg nil)) + (eq arg 1)) + (set-fringe-mode '(nil . 0)) + (set-fringe-mode 0))) + +(defun dot/M-x (command) + "Prompt and execute COMMAND." + (interactive "CCommand: ") + (command-execute command)) + +(defun split-follow-horizontally () + "Split and follow window." + (interactive) + (split-window-below) + (other-window 1)) +(defun split-follow-vertically () + "Split and follow window." + (interactive) + (split-window-right) + (other-window 1)) + +;; https://emacsredux.com/blog/2013/05/04/rename-file-and-buffer/ +(defun rename-file-and-buffer () + "Rename the current buffer and file it is visiting." + (interactive) + (let ((filename (buffer-file-name))) + (if (not (and filename (file-exists-p filename))) + (message "Buffer is not visiting a file!") + (let ((new-name (read-file-name "New name: " filename))) + (cond + ((vc-backend filename) (vc-rename-file filename new-name)) + (t + (rename-file filename new-name t) + (set-visited-file-name new-name t t))))))) + +;; ----------------------------------------- +;; Hook call functions + +(defun dot/hook-disable-line-numbers () + "Disable the line numbers." + (display-line-numbers-mode 0)) + +(defun dot/hook-disable-mode-line () + "Disable the mode line." + (setq-local mode-line-format nil)) + +(provide 'dot-core-functions) + +;; ----------------------------------------- +;; Macros + +;; Reference: https://github.com/arcticicestudio/nord-emacs/issues/59#issuecomment-414882071 +(defmacro dot/run-after-new-frame (func) + "Run FUNC once or after every frame creation. +This is needed for UI initialization when running with the daemon." + `(if (daemonp) + (add-hook 'after-make-frame-functions + (lambda (frame) (with-selected-frame frame ,func))) + ,func)) + +;;; dot-core-functions.el ends here diff --git a/.config/emacs/site-lisp/core/dot-core-hooks.el b/.config/emacs/site-lisp/core/dot-core-hooks.el new file mode 100644 index 0000000..de1ee24 --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-hooks.el @@ -0,0 +1,32 @@ +;;; dot-hooks.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Add hooks. + +;;; Code: + +;; ----------------------------------------- + +;; Delete trailing whitespace +(add-hook 'before-save-hook #'delete-trailing-whitespace) + +;; Display fill column indicator +(add-hook 'prog-mode-hook #'display-fill-column-indicator-mode) +(add-hook 'text-mode-hook #'display-fill-column-indicator-mode) + +;; Highlight parenthesis +(add-hook 'prog-mode-hook #'show-paren-mode) + +;; Disable line numbers +(add-hook 'Custom-mode-hook #'dot/hook-disable-line-numbers) +(add-hook 'dired-mode-hook #'dot/hook-disable-line-numbers) +(add-hook 'Info-mode-hook #'dot/hook-disable-line-numbers) +(add-hook 'term-mode-hook #'dot/hook-disable-line-numbers) + +;; Wrap lines in the middle of words, gives a \ indicator +(add-hook 'visual-line-mode-hook (lambda () (setq word-wrap nil))) + +(provide 'dot-core-hooks) + +;;; dot-hooks.el ends here diff --git a/.config/emacs/site-lisp/core/dot-core-packages.el b/.config/emacs/site-lisp/core/dot-core-packages.el new file mode 100644 index 0000000..bce8131 --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-packages.el @@ -0,0 +1,90 @@ +;;; dot-core-packages.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Install core packages. + +;;; Code: + +;;; Compile + +;; Automatically compile all packages. +;; https://github.com/emacscollective/auto-compile + +(elpaca-setup auto-compile + (:require auto-compile) + (:when-loaded + (auto-compile-on-load-mode) + (auto-compile-on-save-mode))) + +;;; General packages + +(elpaca-setup general + (:load-after evil) + (:when-loaded + ;; Fix for issue: general #493 and evil #130, #301 + ;; https://github.com/noctuid/evil-guide#why-dont-keys-defined-with-evil-define-key-work-immediately + (defun dot/general-fix-leader-key () + "Fix leader key in *Messages* buffer." + (when-let ((messages-buffer (get-buffer "*Messages*"))) + (with-current-buffer messages-buffer + (evil-normalize-keymaps)))) + (add-hook 'emacs-startup-hook #'dot/general-fix-leader-key))) + +(elpaca-setup avy) + +(elpaca-setup hungry-delete + (:require hungry-delete) + (:when-loaded (global-hungry-delete-mode))) + +(elpaca-setup smart-tabs-mode + ;; TODO: how does this get auto-loaded? + (:when-loaded + (smart-tabs-add-language-support latex latex-mode-hook + ((latex-indent-line . 4) + (latex-indent-region . 4))) + ;; FIXME: breaks for Python files + (smart-tabs-insinuate 'c 'c++ 'java 'python 'latex))) + +(elpaca-setup super-save +(:require super-save) + (:when-loaded + (setq super-save-auto-save-when-idle t) + + ;; Fix for issues: super-save #38 and lsp-mode #1322 + (defun dot/super-save-disable-advice (orig-fun &rest args) + "Dont auto-save under these conditions." + (unless (equal (car args) " *LV*") + (apply orig-fun args))) + (advice-add 'super-save-command-advice :around #'dot/super-save-disable-advice) + + (super-save-mode))) + +(elpaca nil (setup desktop ; built-in + (:require desktop) + (:when-loaded + (setq desktop-base-file-name "state") + (setq desktop-base-lock-name "state.lock") + (setq desktop-dirname (expand-file-name "desktop/" dot-cache-dir)) + (setq desktop-path (list desktop-dirname)) + (setq desktop-globals-to-save '()) ;; Only need frames and buffers + + ;; Create directory to store desktop file in + (unless (file-directory-p desktop-dirname) + (make-directory desktop-dirname t)) + + (defun dot/desktop-save () + "Save frame state and buffers." + (interactive) + (dot/centaur-tabs-buffer-cleanup) + (desktop-save desktop-dirname t)) + + (defun dot/desktop-save-on-exit () + "Save state of buffers before closing Emacs." + (dot/desktop-save) + (desktop-release-lock desktop-dirname)) + (add-hook 'kill-emacs-hook #'dot/desktop-save-on-exit)))) + +(provide 'dot-core-packages) + +;;; dot-core-packages.el ends here diff --git a/.config/emacs/site-lisp/core/dot-core-variables.el b/.config/emacs/site-lisp/core/dot-core-variables.el new file mode 100644 index 0000000..6cef076 --- /dev/null +++ b/.config/emacs/site-lisp/core/dot-core-variables.el @@ -0,0 +1,48 @@ +;;; dot-core-variables.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Global variables. + +;;; Code: + +;; ----------------------------------------- +;; Global Variables + +;; Variables for directories, leader keys, etc. + +(defvar dot-emacs-dir (directory-file-name (file-truename user-emacs-directory)) + "Directory base.") ; ~/.config/emacs + +(defvar dot-etc-dir (expand-file-name "etc" dot-emacs-dir) + "Directory for non-volatile storage.") ; ~/.config/emacs/etc + +;; TODO: remove "-modules" when switching over +(defvar dot-cache-dir (expand-file-name "emacs" (getenv "XDG_CACHE_HOME")) + "Directory for cache data.") ; ~/.cache/emacs + +(defvar dot/leader-key "SPC" + "Leader prefix key.") + +(defvar dot/leader-alt-key "M-SPC" + "Alternative leader prefix key, used for Insert and Emacs states.") + +(defvar dot/localleader-key "SPC m" + "Local leader prefix key, for 'major-mode' specific commands.") + +(defvar dot/localleader-alt-key "M-SPC m" + "Alternative local leader prefix key, used for Insert and Emacs states.") + +(defvar dot/shell "/bin/zsh" + "Command interpreter binary path.") + +(defvar dot/hidpi (getenv "HIDPI") + "Whether the primary screen is HiDPI.") + +;; Create cache directory +(unless (file-directory-p dot-cache-dir) + (make-directory dot-cache-dir t)) + +(provide 'dot-core-variables) + +;;; dot-core-variables.el ends here diff --git a/.config/emacs/site-lisp/dot-core.el b/.config/emacs/site-lisp/dot-core.el new file mode 100644 index 0000000..0971a1e --- /dev/null +++ b/.config/emacs/site-lisp/dot-core.el @@ -0,0 +1,24 @@ +;;; dot-core.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Load configuration core. + +;;; Code: + +;; ----------------------------------------- + +(add-to-list 'load-path (locate-user-emacs-file "site-lisp/core")) + +(require 'dot-core-variables) +(require 'dot-core-customize) +(require 'dot-core-fonts) +(require 'dot-core-packages) +(require 'dot-core-config) +(require 'dot-core-functions) +(require 'dot-core-advice) +(require 'dot-core-hooks) + +(provide 'dot-core) + +;;; dot-core.el ends here diff --git a/.config/emacs/site-lisp/dot-development.el b/.config/emacs/site-lisp/dot-development.el new file mode 100644 index 0000000..595f0ec --- /dev/null +++ b/.config/emacs/site-lisp/dot-development.el @@ -0,0 +1,472 @@ +;;; dot-development.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Development. + +;;; Code: + +;; ----------------------------------------- +;; Company + +(elpaca-setup company + (:require company) + (:with-mode + (c-mode-common + emacs-lisp-mode + latex-mode + org-mode + php-mode + shell-mode + shell-script-mode) + (:hook company-mode)) + (:when-loaded + (setq company-idle-delay 0.2) + (setq company-minimum-prefix-length 2) + (setq company-show-numbers t) + (setq company-tooltip-align-annotations 't))) + +;; Sort Company completions. + +(elpaca-setup company-prescient + (:load-after company prescient) + (:when-loaded (company-prescient-mode))) + +;; Auto-completion for C/C++ headers. + +(elpaca-setup company-c-headers + (:when-loaded (add-to-list 'company-backends 'company-c-headers))) + +;; GLSL integration with company requires the package: ~glslang~. + +(when (executable-find "glslangValidator") + (elpaca-setup company-glsl + (:when-loaded (add-to-list 'company-backends 'company-glsl)))) + +;; ----------------------------------------- +;; Git + +(elpaca-setup diff-hl + (:require diff-hl) + (:with-mode prog-mode + (:hook turn-on-diff-hl-mode) + (:hook dot/diff-hl-enable-flydiff-and-fringe)) + (:when-loaded + + (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)))))) + +(elpaca-setup transient + (:when-loaded + (setq transient-history-file (expand-file-name "transient/history.el" dot-cache-dir)) + (setq transient-values-file (expand-file-name "transient/values.el" dot-cache-dir)))) + +(elpaca-setup magit + (:autoload magit-status magit-status-here) + (:with-mode git-commit-setup + (:hook git-commit-turn-on-auto-fill) + (:hook git-commit-turn-on-flyspell)) + (:with-mode magit-pre-refresh (:hook diff-hl-magit-pre-refresh)) + (:with-mode magit-post-refresh (:hook diff-hl-magit-post-refresh)) + (:load-after diff-hl transient) + (:when-loaded + (setq git-commit-fill-column 72) + (setq git-commit-summary-max-length 72) + (setq magit-completing-read-function #'completing-read) + (setq magit-diff-paint-whitespace-lines 'both) + (setq magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1) + (setq magit-process-extreme-logging nil) + (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]) + + (defun dot/magit-select-repo () + "Select project repo." + (interactive) + (let ((current-prefix-arg '(t))) + (call-interactively #'magit-status))))) + +(elpaca-setup magit-todos + (:load-after magit) + (:when-loaded + (magit-todos-mode))) + +;; ----------------------------------------- +;; Project + +;; Project manager. + +;; Adding to project.el project directory detection +;; https://michael.stapelberg.ch/posts/2021-04-02-emacs-project-override/ + +(elpaca nil (setup project ; built-in + (setq project-list-file (expand-file-name "projects" dot-cache-dir)) + (:when-loaded + + (defun dot/project-find (dir) + (let ((root (locate-dominating-file dir ".project"))) + (and root (list 'vc 'Filewise root)))) + (add-hook 'project-find-functions #'dot/project-find) + + (defun dot/find-project-root () + "Return root of the project, determined by `.git/' and `.project', +`default-directory' otherwise." + (let ((project (project-current))) + (if project + (project-root project) + 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))) + + (defun dot/project-remember-projects-under (dir maxdepth) + "Index all projects below directory DIR recursively, until MAXDEPTH." + (let ((files (mapcar 'file-name-directory + (dot/directory-files-recursively-depth + dir "\\.git$\\|\\.project$" t maxdepth)))) + (dolist (path files) + (project-remember-projects-under path)))) + + (unless (file-exists-p project-list-file) + (project-remember-projects-under "~/dotfiles") + (dot/project-remember-projects-under "~/code" 4)) + + (defun dot/project-project-name () + "Return project name." + (let ((project (project-current))) + (if project + (file-name-nondirectory (directory-file-name (project-root project))) + "-"))) + + (defun dot/project-save-project-buffers () + "Save all project buffers." + (interactive) + (let ((buffers (cl-remove-if (lambda (buffer) (not (buffer-file-name buffer))) + (project-buffers (project-current))))) + (save-some-buffers t (lambda () (member (current-buffer) buffers)))))))) + +;; ----------------------------------------- +;; Compile + +;; Enable color escape codes. + +(elpaca nil (setup ansi-color ; built-in + (:with-mode compilation-filter (:hook ansi-color-compilation-filter)) + ;; :hook (compilation-filter . ansi-color-compilation-filter) + (:when-loaded (setq ansi-color-bold-is-bright t)))) + +(elpaca nil (setup compile ; built-in + (defun dot/compile-disable-underline () "" + (face-remap-add-relative 'underline :underline nil)) + (:with-mode comint-mode (:hook dot/compile-disable-underline)) + (:when-loaded + (setq compilation-scroll-output 'first-error) + + (defun dot/compile () + "Compile project." + (interactive) + (let ((default-directory (dot/find-project-root))) + (dot/project-save-project-buffers) + (let ((current-prefix-arg '(t))) + (call-interactively 'compile))))))) + +;; ----------------------------------------- +;; Languages + +;;; Language Server Protocol + +(elpaca-setup lsp-mode + (:autoload lsp-deferred) + ;; (:require lsp-modeline lsp-mode) + (:with-mode + (c-mode ; clangd + c++-mode ; clangd + php-mode ; nodejs-intelephense + csharp-mode ; omnisharp-roslyn-bin + lua-mode ; lua-language-server + latex-mode ; texlab + kotlin-mode ; kotlin-language-server + web-mode) + (:hook lsp-deferred)) + (:when-loaded + (setq lsp-auto-guess-root t) + (setq lsp-clients-clangd-args '("-j=2" + "--background-index" + "--clang-tidy" + "--compile-commands-dir=build" + "--log=error" + "--header-insertion-decorators=0" + "--pch-storage=memory" + "--enable-config")) + (setq lsp-csharp-omnisharp-roslyn-binary-path "/usr/bin/omnisharp") + (setq lsp-csharp-server-install-dir "/usr/lib/omnisharp/") + (setq lsp-clients-lua-language-server-bin "/usr/bin/lua-language-server") + (setq lsp-clients-lua-language-server-install-dir "/usr/lib/lua-language-server/") + (setq lsp-clients-lua-language-server-main-location "/usr/lib/lua-language-server/main.lua") + (setq lsp-enable-xref t) + (setq lsp-headerline-breadcrumb-enable nil) + (setq lsp-intelephense-storage-path (expand-file-name "lsp-cache" dot-cache-dir)) + (setq lsp-keep-workspace-alive nil) + ;; (setq lsp-modeline-code-actions-enable nil) + ;; (setq lsp-modeline-diagnostics-enable nil) + ;; (setq lsp-modeline-workspace-status-enable nil) + (setq lsp-prefer-flymake nil) + (setq lsp-session-file (expand-file-name "lsp-session-v1" dot-cache-dir)) + + ;; 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 dot/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))) + + ;; This is cached to prevent unneeded I/O + (setq lsp-in-cpp-project-cache nil) + (defun dot/lsp-format-cpp-buffer () + "Format buffer in C++ projects." + (unless lsp-in-cpp-project-cache + (set (make-local-variable 'lsp-in-cpp-project-cache) + (list + (if (and (eq major-mode 'c++-mode) + (bound-and-true-p lsp-mode) + (or + (locate-dominating-file "." ".clang-format") + (locate-dominating-file "." "_clang-format"))) + t + nil)))) + (when (car lsp-in-cpp-project-cache) + (lsp-format-buffer))) + (add-hook 'before-save-hook #'dot/lsp-format-cpp-buffer))) + +(elpaca-setup lsp-ui + (:autoload lsp-ui-mode) + (:load-after flycheck lsp-mode) + (:when-loaded + (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))) + +;;; Debug Adapter Protocol + +(elpaca-setup treemacs + (:hook dot/hook-disable-line-numbers) + (:when-loaded (setq treemacs-persist-file (expand-file-name "treemacs/persist" dot-cache-dir)))) + +(elpaca-setup lsp-treemacs + (:load-after treemacs) + (:when-loaded (setq lsp-treemacs-error-list-current-project-only t))) + +(elpaca-setup dap-mode + (:with-mode lsp-after-initialize (:hook dot/dap-install-debug-adapters)) + (:load-after lsp-treemacs lsp-mode) + (:when-loaded + (setq dap-auto-configure-features '(sessions locals expressions controls tooltip)) + (setq dap-breakpoints-file (expand-file-name "dap/breakpoints" dot-cache-dir)) + (setq dap-utils-extension-path (expand-file-name "dap" dot-cache-dir)) + + ;; 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))))) + +;;; C/C++ + +(elpaca nil (setup c-mode ; built-in + ;; C++ // line comment style in c-mode + (defun dot/c-mode-comment-style () "" + (c-toggle-comment-style -1)) + (:hook dot/c-mode-comment-style))) + +;;; C# + +;; Packages: +;; - dotnet-host +;; - dotnet-runtime-6.0 +;; - dotnet-sdk-6.0 +;; - dotnet-targeting-pack-6.0 +;; - omnisharp-roslyn-bin +;; - netcoredbg (edit PKGBUILD to detect dotnet -6.0 dependencies) + +(elpaca-setup csharp-mode) + +;;; CMake + +(elpaca-setup cmake-mode + (:defer 2) + (:when-loaded (setq cmake-tab-width (default-value 'tab-width)))) + +;;; Emacs Lisp + +(elpaca nil (setup emacs-lisp ; built-in + (defun dot/elisp-init () "" + (setq-local indent-tabs-mode nil)) + (:hook dot/elisp-init))) + +;;; GLSL + +(elpaca-setup glsl-mode) + +;;; HTML + +(elpaca-setup web-mode) + +;;; Kotlin + +(elpaca-setup kotlin-mode) + +;;; Lua + +(elpaca-setup lua-mode + (:when-loaded (setq lua-indent-level (default-value 'tab-width)))) + +;;; PHP + +(elpaca-setup php-mode + (defun dot/php-mode-init () "" + (setq-local indent-tabs-mode t)) + (:hook dot/php-mode-init)) + +(elpaca-setup restclient) + +;;; Python + +(elpaca nil (setup python-mode ; built-in + (defun dot/python-mode-init () "" + (setq-local indent-tabs-mode t) + (setq-local tab-width (default-value 'tab-width)) + (setq python-indent-offset (default-value 'tab-width))) + (:hook dot/python-mode-init))) + +;;; YAML + +(elpaca-setup yaml-mode) +;; :defer t) + +;; ----------------------------------------- +;; Syntax Highlighting + +;; (elpaca-setup tree-sitter-langs)) + +;; (elpaca-setup tree-sitter) +;; (:also-load tree-sitter-langs) +;; (:when-loaded +;; (global-tree-sitter-mode) +;; (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))) + +;; ----------------------------------------- +;; Quality of Life + +;;; Flycheck, on the fly syntax checking + +(elpaca-setup flycheck + (:autoload flycheck-mode) + (:with-mode + (c-mode-common + emacs-lisp-mode + latex-mode + org-mode + php-mode + sh-mode + shell-mode + shell-script-mode) + (:hook flycheck-mode)) + (:when-loaded + (setq flycheck-clang-language-standard "c++20") + (setq flycheck-gcc-language-standard "c++20"))) + +;; For .el files which are intended to be packages +(elpaca-setup flycheck-package + (:load-after flycheck) + (:when-loaded + (add-to-list 'flycheck-checkers 'flycheck-emacs-lisp-package) + (flycheck-package-setup))) + +(elpaca-setup flycheck-clang-tidy + (:load-after flycheck) + (:with-mode flycheck-mode (:hook flycheck-clang-tidy-setup)) + (:when-loaded (setq flycheck-clang-tidy-extra-options "--format-style=file"))) + +;;; Flyspell + +;; Give Flyspell a selection menu. +(elpaca-setup flyspell-correct + (:load-after flyspell) + (:with-mode org-mode (:hook flyspell-mode)) + (:when-loaded + (setq flyspell-issue-message-flag nil) + (setq flyspell-issue-welcome-flag nil)) + + (defun dot/flyspell-toggle () + "Toggle Flyspell, prompt for language." + (interactive) + (if (symbol-value flyspell-mode) + (flyspell-mode -1) + (call-interactively 'ispell-change-dictionary) + (if (derived-mode-p 'prog-mode) + (flyspell-prog-mode) + (flyspell-mode)) + (flyspell-buffer)))) + +;;; Rainbow Delimiters + +(elpaca-setup rainbow-delimiters + (:hook-into prog-mode)) + +;;; Rainbow Mode + +(elpaca-setup rainbow-mode + (:hook-into css-mode)) + +;;; YASnippet + +(elpaca-setup yasnippet + (:autoload yas-insert-snippet) + (setq yas-snippet-dirs (list (expand-file-name "snippets" dot-emacs-dir))) + (setq yas-prompt-functions '(yas-completing-prompt)) + (:when-loaded + (yas-global-mode))) + +(elpaca-setup yasnippet-snippets + (:load-after yasnippet)) + +;; https://stackoverflow.com/questions/22735895/configuring-a-yasnippet-for-two-scenarios-1-region-is-active-2-region-is + +(provide 'dot-development) + +;;; dot-org-mode.el ends here diff --git a/.config/emacs/site-lisp/dot-elpaca.el b/.config/emacs/site-lisp/dot-elpaca.el new file mode 100644 index 0000000..cefa203 --- /dev/null +++ b/.config/emacs/site-lisp/dot-elpaca.el @@ -0,0 +1,48 @@ +;;; dot-elpaca.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Elpaca bootstrap + +;;; Code: + +;; ----------------------------------------- + +;; Elpaca bootstrap +(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory)) +(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory)) +(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git" + :ref nil + :build (:not elpaca--activate-package))) +(when-let ((repo (expand-file-name "repos/elpaca/" elpaca-directory)) + (build (expand-file-name "elpaca/" elpaca-builds-directory)) + (order (cdr elpaca-order)) + ((add-to-list 'load-path (if (file-exists-p build) build repo))) + ((not (file-exists-p repo)))) + (condition-case-unless-debug err + (if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*")) + ((zerop (call-process "git" nil buffer t "clone" + (plist-get order :repo) repo))) + (default-directory repo) + ((zerop (call-process "git" nil buffer t "checkout" + (or (plist-get order :ref) "--"))))) + (progn + (byte-recompile-directory repo 0 'force) + (require 'elpaca) + (and (fboundp 'elpaca-generate-autoloads) + (elpaca-generate-autoloads "elpaca" repo)) + (kill-buffer buffer)) + (error "%s" (with-current-buffer buffer (buffer-string)))) + ((error) + (warn "%s" err) + (delete-directory repo 'recursive)))) +(require 'elpaca-autoloads) +(add-hook 'after-init-hook #'elpaca-process-queues) +(elpaca `(,@elpaca-order)) + +;; Stop coping with startup time, its done loading when its done loading +(add-hook 'emacs-startup-hook (lambda () (setq after-init-time (current-time)))) + +(provide 'dot-elpaca) + +;;; dot-elpaca.el ends here diff --git a/.config/emacs/site-lisp/dot-evil.el b/.config/emacs/site-lisp/dot-evil.el new file mode 100644 index 0000000..29a4568 --- /dev/null +++ b/.config/emacs/site-lisp/dot-evil.el @@ -0,0 +1,104 @@ +;;; dot-evil.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Setup Evil and related packages. + +;;; Code: + +;; ----------------------------------------- + +(elpaca-setup undo-tree + (:when-loaded + (setq undo-tree-auto-save-history t) + (setq undo-tree-history-directory-alist `(("." . ,(expand-file-name "undo-tree" dot-cache-dir)))) + (global-undo-tree-mode))) + +(elpaca-setup goto-chg) + +(elpaca-setup evil + (:also-load undo-tree goto-chg) + (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-integration t) + (setq evil-want-keybinding nil) ; Needed by evil-collection + (:require evil) + (:when-loaded + + ;; Put search results in the center of the window + (defun dot/evil-scroll-center (&rest _) + "Scroll cursor to center of the window." + (evil-scroll-line-to-center nil)) + (advice-add 'evil-ex-search :after #'dot/evil-scroll-center) + (advice-add 'evil-match :after #'dot/evil-scroll-center) + + (defun dot/evil-normal-sort-paragraph () + "Sort paragraph cursor is under. +Vim equivalence: vip:sort" + (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: " + (interactive) + (evil-shift-left-line 1)) + + (defun dot/evil-insert-shift-right () + "Shift line right, retains cursor position. +Vim equivalence: " + (interactive) + (insert "\t")) + + (defun dot/evil-visual-shift-left () + "Shift visual selection left, retains the selection. +Vim equivalence: gv" + (interactive) + (call-interactively #'evil-shift-right) + (setq deactivate-mark nil)) + + (evil-mode))) + +;; Evil command aliases. + +(elpaca nil (setup evil-ex ; evil-ex.el is part of evil + (:when-loaded + (evil-ex-define-cmd "W" "w") + (evil-ex-define-cmd "Q" "q") + (evil-ex-define-cmd "WQ" "wq") + (evil-ex-define-cmd "Wq" "wq")))) + +(elpaca-setup evil-collection + (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) + (:load-after evil) + (:when-loaded + (evil-collection-init))) + +(elpaca-setup evil-nerd-commenter + (:load-after evil)) + +(provide 'dot-evil) + +;;; dot-evil.el ends here diff --git a/.config/emacs/site-lisp/dot-keybinds.el b/.config/emacs/site-lisp/dot-keybinds.el new file mode 100644 index 0000000..7f071b4 --- /dev/null +++ b/.config/emacs/site-lisp/dot-keybinds.el @@ -0,0 +1,665 @@ +;;; dot-keybinds.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; All keybinds. + +;;; Code: + +;; ----------------------------------------- +;; Useful links + +;; Mastering Emacs key bindings +;; https://www.masteringemacs.org/article/mastering-key-bindings-emacs + +;; use-package bind key +;; https://github.com/jwiegley/use-package/blob/master/bind-key.el + +;; GNU remapping commands +;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Remapping-Commands.html + +;; GNU binding combinations of modifiers +;; https://www.gnu.org/software/emacs/manual/html_node/efaq/Binding-combinations-of-modifiers-and-function-keys.html + +;; Doom Emacs bindings +;; https://github.com/hlissner/doom-emacs/blob/develop/modules/config/default/+evil-bindings.el + +;; Keybindings and States +;; https://github.com/noctuid/evil-guide#keybindings-and-states + +;; General.el +;; https://github.com/noctuid/general.el + +;; ----------------------------------------- +;; Disable Native + +;; Disable keybinds of native modes that clash with other custom keybinds. + +(elpaca nil (setup emacs + (:global + "M-h" nil + "M-j" nil + "M-k" nil + "M-l" nil + ))) + +(elpaca nil (setup org + (:bind "M-h" nil + "C-M-h" nil + ))) + +(elpaca nil (setup cc-mode + (:bind-into c-mode-base-map + "M-j" nil + "C-M-h" nil + ))) + +(elpaca nil (setup nxml-mode + (:bind "M-h" nil + ))) + +;; ----------------------------------------- +;; Disable Package + +;; Disable keybinds of installed packages that clash with other custom keybinds. + +(elpaca nil (setup evil-states + (:bind-into evil-motion-state-map dot/leader-key nil + ))) + +(elpaca nil (setup magit + (:evil-bind normal + ;; Do not close magit when pressing escape + "" nil))) + +(elpaca nil (setup php-mode + (:bind "M-j" nil + "C-M-h" nil + ))) + +;; ----------------------------------------- +;; Set Native + +;; Set keybinds to native functionality. + +;;; Set Native Global Keybinds + +(elpaca nil (setup emacs + (:global + ;; Buffers + "C-x C-b" ibuffer + "M-w" kill-buffer-and-window + + ;; Config edit/reload + "C-c r" dot/config-reload + "C-c v" dot/config-visit + + ;; Find file + "C-x C-f" dot/find-file-in-project-root + + ;; Split and follow window + "C-x 2" split-follow-horizontally + "C-x 3" split-follow-vertically + + ;; Terminal + "" ansi-term + + ;; Universal prefix argument + "C-M-u" universal-argument + ))) + +;;; Set Native Mode Keybinds + +;; Dired +(elpaca nil (setup dired + (:bind + [remap dired-find-file] dot/dired-find-file + [remap dired-up-directory] dot/dired-up-directory + ))) + +;; Org +(elpaca nil (setup org + (:bind "M-c" org-edit-special + ))) +(elpaca nil (setup org-src + (:bind "M-c" org-edit-src-exit + "M-k" org-edit-src-abort + ))) +(elpaca nil (setup org-capture + (:bind "M-c" org-capture-finalize + "M-w" org-capture-refile + "M-k" org-capture-kill + ))) + +;; ----------------------------------------- +;; Set Package + +;; Set keybinds to functionality of installed packages. + +(elpaca nil (setup emacs + (:global + ;; Buffers + "M-h" centaur-tabs-backward-tab + "M-j" centaur-tabs-forward-group + "M-k" centaur-tabs-backward-group + "M-l" centaur-tabs-forward-tab + "M-H" centaur-tabs-move-current-tab-to-left + "M-L" centaur-tabs-move-current-tab-to-right + "M-\`" evil-switch-to-windows-last-buffer + ;; Other + "M-s" avy-goto-char-timer + "M-x" dot/M-x + ))) + +(elpaca nil (setup company + (:bind-into company-active-map + ;; Company completion selection + "M-n" nil + "M-p" nil + "M-h" company-abort + "M-j" company-select-next + "M-k" company-select-previous + "M-l" company-complete-selection + "" company-abort + ))) + +(elpaca nil (setup evil-ex + (:bind-into evil-ex-completion-map + ;; Evil command history selection + "M-h" abort-recursive-edit + "M-j" next-complete-history-element + "M-k" previous-complete-history-element + "M-l" exit-minibuffer + ))) + +(elpaca nil (setup emacs + (:global + ;; flyspell-correct + [remap ispell-word] flyspell-correct-at-point ; z= + + ;; Helpful overwrite default help functions + [remap describe-command] helpful-command + [remap describe-function] helpful-callable + [remap describe-key] helpful-key + [remap describe-symbol] helpful-at-point + [remap describe-variable] helpful-variable + ) + (setup which-key + (:when-loaded + (which-key-add-key-based-replacements "C-h o" "describe-symbol-at-point"))))) + +;; LSP +(elpaca nil (setup lsp-mode + (:bind-into lsp-signature-mode-map + "M-j" lsp-signature-next + "M-k" lsp-signature-previous + ))) + +;; Magit +(elpaca nil (setup magit + (:bind-into magit-log-select-mode-map + "M-c" magit-log-select-pick + "M-k" magit-log-select-quit + ))) + +;; Org-roam +(elpaca nil (setup org-roam + (:bind [down-mouse-1] org-roam-visit-thing + ))) + +;; Minibuffer completion selection +(elpaca nil (setup minibuffer + (:bind-into minibuffer-local-map + "M-J" next-history-element + "M-K" previous-history-element + "M-h" abort-recursive-edit + "M-i" vertico-quick-insert + "M-j" vertico-next + "M-k" vertico-previous + "M-l" vertico-exit + "M-m" vertico-quick-exit + "" dot/vertico-backspace + "" evil-delete-backward-char-and-join + ))) + +;; with-editor +(elpaca nil (setup with-editor + (:bind + "M-c" with-editor-finish + "M-k" with-editor-cancel + ))) + +;;; Global evil keymap + +(elpaca nil (setup evil + (:bind-into evil-normal-state-map + "C-n" neotree-toggle-in-project-root + "C-S-p" evil-paste-pop-next + "S-" scroll-down-line + "S-" scroll-up-line + ) + + (:bind-into evil-insert-state-map + "" dot/evil-insert-shift-left ; + "TAB" dot/evil-insert-shift-right ; + ) + + (:bind-into evil-visual-state-map + "<" dot/evil-visual-shift-left ; " dot/evil-visual-shift-right ; >gv + ) + + (:bind-into evil-ex-map + "e" dot/find-file-in-project-root + ))) + +;;; Other evil state-related keybinds + +;; Custom (M-x customize) +(elpaca nil (setup cus-edit + (:evil-bind-into normal custom-mode-map + [down-mouse-1] widget-button-click + ))) + +;; Dashboard +(elpaca nil (setup dashboard + (:evil-bind normal + [down-mouse-1] widget-button-click + "g" dashboard-refresh-buffer + "m" dot/dashboard-goto-bookmarks + "p" dot/dashboard-goto-projects + "r" dot/dashboard-goto-recent-files + ))) + +;; Dap +(elpaca nil (setup dap-ui + (:evil-bind-into normal dap-ui-session-mode-map + "D" dap-ui-delete-session + ))) + +;; Deft +(elpaca nil (setup deft + (:evil-bind normal + [down-mouse-1] widget-button-click + "+" deft-new-file-named + "-" deft-new-file + "a" deft-archive-file + "c" deft-filter-clear + "d" deft-delete-file + "f" deft-find-file + "g" deft-refresh + "q" kill-this-buffer + "R" deft-rename-file + "s" deft-filter + "ts" '("Toggle search" . deft-toggle-incremental-search) ; which-key + "tt" '("Toggle sort" . deft-toggle-sort-method) ; custom string + ))) + +;; Elfeed +(elpaca nil (setup elfeed + (:evil-bind-into normal elfeed-search-mode-map + "b" elfeed-search-browse-url + "c" elfeed-search-clear-filter + "gr" '("Refresh buffer" . elfeed-search-update--force) + "gR" '("Update feeds" . elfeed-search-fetch) + "q" elfeed-search-quit-window + "u" elfeed-search-tag-all-unread + "U" nil + "r" elfeed-search-untag-all-unread + ) + (:evil-bind-into normal elfeed-show-mode-map + "b" elfeed-show-visit + "g" elfeed-show-refresh + "q" elfeed-kill-buffer + "u" elfeed-show-tag--unread + "y" elfeed-show-yank + ))) + +;; Magit +(elpaca nil (setup magit + (:evil-bind (normal visual) + "{" magit-section-backward-sibling + "}" magit-section-forward-sibling + ))) + +;; Minibuffer +(elpaca nil (setup minibuffer + (:evil-bind-into normal minibuffer-local-map + "TAB" vertico-insert + "j" vertico-next + "k" vertico-previous + "" vertico-previous + "" vertico-next + ) + (:evil-bind-into insert minibuffer-local-map + "TAB" vertico-insert + ))) + +;; Mu4e +(elpaca nil (setup mu4e + (:evil-bind-into normal mu4e-compose-mode-map + "q" mu4e-message-kill-buffer + "M-c" message-send-and-exit + "M-k" mu4e-message-kill-buffer + ))) + +;; Neotree +(elpaca nil (setup neotree + (:evil-bind normal + "RET" neotree-enter + "" neotree-collapse-all ; + "c" neotree-create-node + "r" neotree-rename-node + "d" neotree-delete-node + "h" neotree-select-previous-sibling-node + "g" neotree-refresh + "j" neotree-next-line + "k" neotree-previous-line + "l" neotree-enter + "C" neotree-change-root + "H" neotree-hidden-file-toggle + "q" neotree-hide + ))) + +;; Org +(elpaca nil (setup org + (:evil-bind normal + "RET" dot/org-ret-at-point + ) + (:evil-bind insert + "RET" evil-ret + ) + (:evil-bind-into motion org-agenda-mode-map + "RET" org-agenda-switch-to + ))) + +;; Wdired +(elpaca nil (setup wdired + (:evil-bind (normal insert) + "M-c" wdired-finish-edit + "M-k" wdired-abort-changes + ))) + +;; ----------------------------------------- +;; Set leader key + +;; General.el ~leader key binds. + +;;; Global Leader + +(elpaca nil (setup general + (:when-loaded + (general-create-definer space-leader + :prefix dot/leader-key + :non-normal-prefix dot/leader-alt-key + :global-prefix dot/leader-alt-key + :states '(normal visual insert motion emacs) + :keymaps 'override) ; prevent leader keybindings from ever being overridden + + (space-leader + "SPC" '(dot/M-x :which-key "Execute command") + "RET" '(consult-bookmark :which-key "Go to bookmark") + + ;; Apps + "a" '(:ignore t :which-key "apps") + "a d" '(deft :which-key "Deft") + "a e" '(elfeed :which-key "Elfeed") + + ;; Buffer / bookmark + "b" '(:ignore t :which-key "buffer/bookmark") + "b a" '(auto-revert-mode :which-key "Auto revert buffer") + "b b" '(consult-buffer :which-key "Switch buffer") + "b d" '(dot/dashboard-goto :which-key "Dashboard") + "b k" '(kill-current-buffer :which-key "Kill buffer") + "b m" '(bookmark-set :which-key "Make bookmark") + "b n" '(evil-buffer-new :which-key "New empty buffer") + "b r" '(revert-buffer :which-key "Revert buffer") + "b s" '(basic-save-buffer :which-key "Save buffer") + "b B" '(ibuffer :which-key "List buffers") + "b C" '(dot/centaur-tabs-buffer-cleanup :which-key "Cleanup buffers") + "b M" '(bookmark-delete :which-key "Delete bookmark") + "b S" '(evil-write-all :which-key "Save all buffers") + "b " '(previous-buffer :which-key "Previous buffer") + "b " '(next-buffer :which-key "Next buffer") + + ;; Comments + "c" '(:ignore t :which-key "comment/config") + "c c" '(evilnc-comment-or-uncomment-lines :which-key "Toggle comment") + "c p" '(evilnc-comment-or-uncomment-paragraphs :which-key "Toggle comment paragraph") + "c y" '(evilnc-comment-and-kill-ring-save :which-key "Comment and copy") + + ;; Elisp + "e" '(:ignore t :which-key "elisp") + "e ;" '(eval-expression :which-key "Evaluate expression") + "e b" '(eval-buffer :which-key "Evaluate buffer") + "e e" '(eval-last-sexp :which-key "Evaluate last sexp") + "e r" '(eval-region :which-key "Evaluate region") + "e t" '(dot/reload-theme :which-key "Reload theme") + + ;; File + "f" '(:ignore t :which-key "file") + "f d" '(dired :which-key "Find directory") + "f f" '(dot/find-file-in-project-root :which-key "Find file") + "f o" '(ff-find-other-file :which-key "Find header/source file") + "f r" '(consult-recent-file :which-key "Find recent file") + "f R" '(rename-file-and-buffer :which-key "Rename file") + "f s" '(basic-save-buffer :which-key "Save file") + "f S" '(write-file :which-key "Save file as...") + "f u" '(dot/sudo-find-file :which-key "Sudo find file") + "f U" '(dot/sudo-this-file :which-key "Sudo this file") + "f e" '(:ignore t :which-key "emacs") + "f e c" '(dot/config-visit :which-key "Config visit") + "f e f" '(dot/find-file-emacsd :which-key "Find emacs file") + "f e r" '(dot/config-reload :which-key "Config reload") + + ;; Go to + "g" '(:ignore t :which-key "goto") + "g b" '(consult-bookmark :which-key "Go to bookmark") + "g f" '(consult-flycheck :which-key "Go to flycheck error") + "g m" '(consult-mark :which-key "Go to marker") + + ;; Help + "h" '(:keymap help-map :which-key "help") + "h o" '(:ignore t :which-key "describe-symbol-at-point") + + ;; Insert + "i" '(:ignore t :which-key "insert") + "i b" '(dot/indent-buffer :which-key "Indent buffer") + "i f" '(fill-region :which-key "Reflow region") + "i F" '(fill-paragraph :which-key "Reflow paragraph") + "i r" '(indent-region :which-key "Indent region") + "i s" '(dot/evil-normal-sort-paragraph :which-key "Sort paragraph") + "i S" '(dot/insert-spaces-until-column :which-key "Insert spaces") + "i y" '(yas-insert-snippet :which-key "Insert yasnippet") + + ;; Notes + "n" '(:ignore t :which-key "notes") + "n a" '(org-agenda :which-key "Org agenda") + "n r" '(:ignore t :which-key "org-roam") + "n r c" '(org-roam-capture :which-key "Capture") + "n r C" '(org-roam-db-sync :which-key "Build cache") + "n r f" '(org-roam-node-find :which-key "Find node") + "n r g" '(org-roam-graph :which-key "Show graph") + "n r i" '(org-roam-node-insert :which-key "Insert") + "n r I" '(dot/org-roam-node-insert-immediate :which-key "Insert (without capture)") + "n r r" '(org-roam-buffer-toggle :which-key "Toggle buffer") + "n r s" '(org-roam-ui-mode :which-key "Toggle server") + + ;; Project + "p" '(:keymap project-prefix-map :which-key "project") + "p b" '(consult-project-buffer :which-key "project-switch-buffer") + "p f" '(consult-project-extra-find :which-key "project-find-file") + "p g" '(consult-grep :which-key "project-find-regexp") + + ;; Quit + "q" '(:ignore t :which-key "quit") + "q q" '(save-buffers-kill-terminal :which-key "Quit Emacs") + "q Q" '(save-buffers-kill-emacs :which-key "Quit Emacs (and daemon)") + "q f" '(delete-frame :which-key "Close frame") + "q o" '(delete-other-frames :which-key "Close other frames") + + ;; Search + "s" '(:ignore t :which-key "search") + "s a" '(avy-goto-char-timer :which-key "Avy goto char") + "s f" '(consult-find :which-key "Search file") + "s l" '(avy-goto-line :which-key "Avy goto line") + "s p" '(consult-grep :which-key "Search project") + "s q" '(evil-ex-nohighlight :which-key "Stop search") + "s s" '(consult-line :which-key "Search buffer") + + ;; Tabs / toggle + "t" '(:ignore t :which-key "tabs/toggle") + "t f" '(dot/toggle-fringe :which-key "Toggle fringe") + "t g" '(centaur-tabs-switch-group :which-key "Switch tab group") + "t h" '(centaur-tabs-backward-group :which-key "Tab backward group") + "t j" '(centaur-tabs-select-end-tab :which-key "Tab select first") + "t k" '(centaur-tabs-select-beg-tab :which-key "Tab select last") + "t l" '(centaur-tabs-forward-group :which-key "Tab forward group") + "t n" '(neotree-toggle-in-project-root :which-key "Toggle Neotree") + "t s" '(dot/flyspell-toggle :which-key "Toggle spell checker") + "t w" '(visual-line-mode :which-key "Toggle line wrapping") + + ;; Update packages + "U" '(elpaca-update-all :which-key "Update packages") + + ;; Version control + "v" '(:ignore t :which-key "git") + "v b" '(magit-branch-checkout :which-key "Magit switch branch") + "v B" '(magit-blame-addition :which-key "Magit blame") + "v C" '(magit-clone :which-key "Magit clone") + "v F" '(magit-fetch :which-key "Magit fetch") + "v L" '(magit-log :which-key "Magit log") + "v s" '(magit-show-commit :which-key "Magit show commit") + "v S" '(magit-stage-file :which-key "Stage file") + "v U" '(magit-unstage-file :which-key "Unstage file") + "v v" '(magit-status :which-key "Magit status") + "v V" '(magit-status-here :which-key "Magit status here") + "v c" '(:ignore t :which-key "create") + "v c c" '(magit-commit-create :which-key "Commit") + "v c b" '(magit-branch-and-checkout :which-key "Branch") + "v c r" '(magit-init :which-key "Initialize repo") + "v f" '(:ignore t :which-key "file") + "v f c" '(magit-find-git-config-file :which-key "Find gitconfig file") + "v f D" '(magit-file-delete :which-key "Delete file") + "v f f" '(magit-find-file :which-key "Find file") + "v f R" '(magit-file-rename :which-key "Rename file") + "v l" '(:ignore t :which-key "list") + "v l r" '(magit-list-repositories :which-key "List repositories") + "v l s" '(magit-list-submodules :which-key "List submodules") + "v r" '(dot/magit-select-repo :which-key "Select repo") + + ;; Window + "w" '(:ignore t :which-key "window") + "w +" '(evil-window-increase-height :which-key "Increase window height") + "w -" '(evil-window-decrease-height :which-key "Decrease window height") + "w <" '(evil-window-decrease-width :which-key "Decrease window width") + "w =" '(balance-windows :which-key "Balance windows") + "w >" '(evil-window-increase-width :which-key "Increase window width") + "w _" '(evil-window-set-height :which-key "Maximize window height") + "w h" '(windmove-left :which-key "Focus window left") + "w j" '(windmove-down :which-key "Focus window down") + "w k" '(windmove-up :which-key "Focus window up") + "w l" '(windmove-right :which-key "Focus window right") + "w o" '(delete-other-windows :which-key "Close other windows") + "w s" '(split-follow-horizontally :which-key "Split horizontal") + "w v" '(split-follow-vertically :which-key "Split vertical") + "w w" '(other-window :which-key "Focus other window") + "w q" '(dot/centaur-tabs-kill-buffer-or-window :which-key "Close window") + "w r" '(winner-redo :which-key "Redo window configuration") + "w u" '(winner-undo :which-key "Undo window configuration") + "w " '(windmove-left :which-key "Focus window left") + "w " '(windmove-right :which-key "Focus window right") + "w " '(windmove-up :which-key "Focus window up") + "w " '(windmove-down :which-key "Focus window down") + ) + + ;; Evaluated keybinds. + + (with-eval-after-load 'lsp-mode + (space-leader lsp-mode-map + "l" lsp-command-map + "l = f" '(dot/lsp-format-buffer-or-region :which-key "format buffer or region") + )) + + (with-eval-after-load 'dap-mode + (space-leader lsp-mode-map + "l d" '(dap-hydra :which-key "DAP hydra") + ))))) + +;; Source: +;; https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-evil.el#L712 +;; https://github.com/suyashbire1/emacs.d/blob/master/init.el + +;;; Local Leader + +(elpaca nil (setup general + (:when-loaded + (general-create-definer local-leader + :prefix dot/localleader-key + :non-normal-prefix dot/localleader-alt-key + :global-prefix dot/localleader-alt-key + :states '(normal visual insert motion emacs) + :keymaps 'override ; prevent leader keybindings from ever being overridden + "" '(:ignore t :which-key "") + ) + + (local-leader c++-mode-map + "i" '(:ignore t :which-key "insert") + "i i" '(dot/copy-cpp-function-implementation :which-key "Copy function implementation") + ) + + (local-leader org-mode-map + "'" '(org-edit-special :which-key "Org edit") + "e" '(org-export-dispatch :which-key "Org export") + "o" '(org-open-at-point :which-key "Org open at point") + "q" '(org-set-tags-command :which-key "Org tags") + + "g" '(:ignore t :which-key "goto") + "g o" '(consult-outline :which-key "Org go to heading") + + "i" '(:ignore t :which-key "insert") + "i c" '(org-table-insert-column :which-key "Insert table column") + "i h" '(org-table-insert-hline :which-key "Insert table hline") + "i H" '(org-table-hline-and-move :which-key "Insert table hline and move") + "i r" '(org-table-insert-row :which-key "Insert table row") + "i t" '(org-insert-structure-template :which-key "Insert template") + + "l" '(:ignore t :which-key "links") + "l i" '(org-id-store-link :which-key "Store ID link") + "l l" '(org-insert-link :which-key "Insert link") + "l s" '(org-store-link :which-key "Store link") + "l S" '(org-insert-last-stored-link :which-key "Insert stored link") + + "s" '(:ignore t :which-key "tree/subtree") + "s h" '(org-promote-subtree :which-key "Org promote subtree") + "s j" '(org-metadown :which-key "Org move subtree down") + "s k" '(org-metaup :which-key "Org move subtree up") + "s l" '(org-demote-subtree :which-key "Org demote subtree") + "s " '(org-promote-subtree :which-key "Org promote subtree") + "s " '(org-demote-subtree :which-key "Org demote subtree") + "s " '(org-move-subree-up :which-key "Org move subtree up") + "s " '(org-move-subtree-down :which-key "Org move subtree down") + + "t" '(:ignore t :which-key "toggle") + "t t" '(org-todo :which-key "Org todo state") + "t l" '(org-toggle-link-display :which-key "Org link display") + ) + + (local-leader org-src-mode-map + "k" '(org-edit-src-abort :which-key "Org Edit abort")) + + (local-leader elfeed-search-mode-map + "g" '(elfeed-search-update--force :which-key "Elfeed refresh buffer") + "G" '(elfeed-search-fetch :which-key "Elfeed update feeds") + ) + + (local-leader elfeed-show-mode-map + "g" '(elfeed-show-refresh :which-key "Elfeed refresh buffer") + )))) + +;; c-fill-paragraph Reflow comment +;; https://youtu.be/hbmV1bnQ-i0?t=1910 + +(provide 'dot-keybinds) + +;;; dot-keybinds.el ends here diff --git a/.config/emacs/site-lisp/dot-mail.el b/.config/emacs/site-lisp/dot-mail.el new file mode 100644 index 0000000..9be81ed --- /dev/null +++ b/.config/emacs/site-lisp/dot-mail.el @@ -0,0 +1,148 @@ +;;; dot-mail.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Mail configuration. + +;;; Code: + +;; ----------------------------------------- +;; Mail Functions + +(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))))) + +;; Mail in Emacs with mu4e + +;; Useful mu4e manual pages: + +;; Key bindings +;; [https://www.djcbsoftware.nl/code/mu/mu4e/MSGV-Keybindings.html#MSGV-Keybindings] + +(elpaca nil (setup mu4e ; loaded from AUR package + (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e") + (:autoload mu4e mu4e-update-index) + (:when-loaded + (add-to-list 'auth-sources (expand-file-name "authinfo.gpg" dot-etc-dir)) + (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 " (expand-file-name "isync/mbsyncrc" (getenv "XDG_CONFIG_HOME")))) + (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)))) + +;; Use mu4e-alert to show new e-mail notifications. +;; https://github.com/iqbalansari/mu4e-alert + +(elpaca-setup mu4e-alert + (:defer 20) + (:when-loaded + (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))) + +;; Sending mail. + +(elpaca nil (setup smtpmail ; built-in + (setq smtpmail-default-smtp-server "mail.riyyi.com") + (:load-after mu4e) + (:when-loaded + (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)))) + +(elpaca nil (setup sendmail ; built-in + (:load-after mu4e) + (:when-loaded (setq send-mail-function 'smtpmail-send-it)))) + +(elpaca nil (setup message ; built-in + (:load-after mu4e) + (:when-loaded + (setq message-kill-buffer-on-exit t) + (setq message-send-mail-function 'smtpmail-send-it)))) + +;; 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 + +(provide 'dot-mail) + +;;; dot-mail.el ends here diff --git a/.config/emacs/site-lisp/dot-org-mode.el b/.config/emacs/site-lisp/dot-org-mode.el new file mode 100644 index 0000000..9755fba --- /dev/null +++ b/.config/emacs/site-lisp/dot-org-mode.el @@ -0,0 +1,268 @@ +;;; dot-org-mode.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Load org-mode modules. + +;;; Code: + +;; ----------------------------------------- +;; LaTeX Configuration + +(elpaca nil (setup tex-mode ; built-in + (:when-loaded + (defun dot/tex-mode-init () "" + (setq indent-tabs-mode t) + (setq tab-width 4) + (setq tex-indent-basic 4)) + (:hook dot/tex-mode-init) + + (with-eval-after-load 'project + (defun compile-latex () + "Compile LaTeX project." + (interactive) + (let ((default-directory (dot/find-project-root))) + (dot/project-save-project-buffers) + (shell-command "make"))))))) + +;; ----------------------------------------- +;; Org Configuration + +;; Base Org. + +(elpaca nil (setup org ; built-in + (setq org-directory (expand-file-name "documents/org" (getenv "HOME"))) + (setq org-default-notes-file (expand-file-name "notes.org" org-directory)) + (:when-loaded + (setq org-adapt-indentation nil) + (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")) + + (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 + table -- go to next row + 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)) + ('table-cell (org-table-next-row)) + (_ (evil-ret)) + ))))))) + +;; Org agenda. + +(elpaca nil (setup org-agenda ; built-in + (:load-after evil org) + (:when-loaded + (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)))) + +;; Org capture. + +(elpaca nil (setup org-capture ; built-in + ;; Org-capture in new tab, rather than split window + (:hook delete-other-windows))) + +;; Org keys. + +(elpaca nil (setup org-keys ; built-in + (:when-loaded + (setq org-return-follows-link t)))) + +;; Org links. + +(elpaca nil (setup ol ; built-in + (:when-loaded + ;; Do not open links to .org files in a split window + (add-to-list 'org-link-frame-setup '(file . find-file))))) + +;; Org source code blocks. + +(elpaca nil (setup org-src ; built-in + (:when-loaded + (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)))) + +;; Org exporter. + +(elpaca nil (setup ox ; built-in + (:when-loaded + (setq org-export-coding-system 'utf-8-unix)))) + +;; Org latex exporter. + +(elpaca nil (setup ox-latex ; built-in + (:when-loaded + ;; 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")) + ;; Add -shell-escape so pdflatex exports minted correctly + (setcar org-latex-pdf-process (replace-regexp-in-string + "-%latex -interaction" + "-%latex -shell-escape -interaction" + (car org-latex-pdf-process)))))) + +;;; Org Bullets + +(elpaca-setup org-bullets + (:hook-into org-mode)) + +;;; Org Export Packages + +;; HTML exporter. + +(elpaca-setup htmlize + (:when-loaded (setq org-export-html-postamble nil))) +;;org-export-html-postamble-format ; TODO + +;; GitHub flavored Markdown exporter. + +(elpaca-setup ox-gfm) + +;;; Org Roam + +(elpaca-setup org-roam + (:autoload org-roam-node-find) ;; TODO, is this enough? + (setq org-roam-v2-ack t) + (:when-loaded + (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||:structure:}\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))) + +;; Enable https://www.orgroam.com/manual.html#org_002droam_002dprotocol, needed to process org-protocol:// links + +(elpaca nil (setup org-roam-protocol ; org-roam-protocol.el is part of org-roam + (:load-after org-roam) + (:when-loaded + + ;; 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)))))) + +;; The roam-ref protocol bookmarks to add: + +;; javascript:location.href = +;; 'org-protocol://roam-ref?template=r' +;; + '&ref=' + encodeURIComponent(location.href) +;; + '&title=' + encodeURIComponent(document.title) +;; + '&body=' + encodeURIComponent(window.getSelection()) + +;; Setup org-roam-ui, runs at http://127.0.0.1:35901. + +(elpaca-setup org-roam-ui + (:load-after org-roam) + (:when-loaded + (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))) + +;; Easily searchable .org files via Deft. + +(elpaca-setup deft + (:hook dot/hook-disable-line-numbers) + (:when-loaded + (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 + (with-eval-after-load 'evil + (evil-set-initial-state 'deft-mode 'insert)) + + (defun deft-parse-title (file contents) + "Parse the given FILE and CONTENTS and determine the title." + (if (string-match "#\\+\\(TITLE\\|title\\):\s*\\(.*\\)$" contents) + (match-string 2 contents) + (deft-base-filename file))))) + +;;; Org "Table of Contents" + +;; Generate table of contents without exporting. +(elpaca-setup toc-org + (:hook-into org-mode)) + +(provide 'dot-org-mode) + +;;; dot-org-mode.el ends here diff --git a/.config/emacs/site-lisp/dot-rss.el b/.config/emacs/site-lisp/dot-rss.el new file mode 100644 index 0000000..312e1d7 --- /dev/null +++ b/.config/emacs/site-lisp/dot-rss.el @@ -0,0 +1,29 @@ +;;; dot-rss.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; RSS. + +;;; Code: + +;; ----------------------------------------- + +(elpaca-setup elfeed + (:autoload elfeed) + (:with-mode dot/hook-disable-line-numbers + (:hook-into elfeed-search-mode) + (:hook-into elfeed-show-mode)) + (:when-loaded + (setq elfeed-db-directory (expand-file-name "elfeed" dot-cache-dir)) + (setq elfeed-enclosure-default-dir "~/downloads/") + (setq elfeed-search-filter "@6-months-ago +unread") + (setq elfeed-search-clipboard-type 'CLIPBOARD) + (setq elfeed-search-title-max-width 100) + (setq elfeed-search-title-min-width 30) + (setq elfeed-search-trailing-width 55) + (setq elfeed-show-unique-buffers t) + (load (expand-file-name "elfeed-feeds" dot-etc-dir)))) + +(provide 'dot-rss) + +;;; dot-rss.el ends here diff --git a/.config/emacs/site-lisp/dot-selection.el b/.config/emacs/site-lisp/dot-selection.el new file mode 100644 index 0000000..9a7be64 --- /dev/null +++ b/.config/emacs/site-lisp/dot-selection.el @@ -0,0 +1,79 @@ +;;; dot-selection.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Incremental narrowing in Emacs. + +;;; Code: + +(elpaca-setup prescient + (:require prescient) + (:when-loaded + (setq completion-styles '(prescient basic)) + (setq prescient-completion-enable-sort nil) + (setq prescient-filter-method '(literal regexp fuzzy)) + (setq prescient-save-file (expand-file-name "prescient-save.el" dot-cache-dir)) + (prescient-persist-mode))) + +(elpaca-setup (vertico :files (:defaults "extensions/*")) + (:load-after prescient) + (:when-loaded + (setq vertico-sort-function #'prescient-completion-sort) + (setq vertico-sort-override-function #'prescient-completion-sort) + + (defun dot/vertico-prescient-remember () + "Remember the chosen candidate with Prescient." + (when (>= vertico--index 0) + (prescient-remember + (substring-no-properties + (nth vertico--index vertico--candidates))))) + (advice-add #'vertico-insert :after #'dot/vertico-prescient-remember) + + (setq vertico-previous-directory nil) + (defun dot/vertico-backspace () + "In Vertico file completion, backward kill sexp, delete char otherwise." + (interactive) + (if (not (and (active-minibuffer-window) + minibuffer-completing-file-name)) + (backward-delete-char 1) + (setq vertico-previous-directory + (concat (file-name-nondirectory (directory-file-name (minibuffer-contents))) + "/")) + (vertico-directory-delete-word 1))) + + (vertico-mode)) + + (defun dot/vertico-dired-goto-last-visited (&rest _) + "Go to directory candidate that was last visited." + (when minibuffer-completing-file-name + (setq vertico--index (or (seq-position vertico--candidates vertico-previous-directory) + (when (string= vertico-previous-directory "~/") + (seq-position vertico--candidates (concat user-login-name "/"))) + (if (= vertico--total 0) -1 0))) + (setq vertico-previous-directory nil))) + (advice-add 'vertico--update-candidates :after #'dot/vertico-dired-goto-last-visited)) + +(elpaca nil (setup vertico-mouse ; vertico-mouse.el is part of vertico + (:load-after vertico) + (:when-loaded (vertico-mouse-mode)))) + +(elpaca-setup marginalia + (:load-after vertico) + (:when-loaded + (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light)) + (marginalia-mode))) + +(elpaca-setup consult + (:load-after vertico) + (:when-loaded (setq consult-narrow-key (kbd "?")))) + +(elpaca-setup consult-flycheck + (:load-after consult flycheck)) + +(elpaca-setup consult-project-extra + (:load-after consult project) + (:when-loaded (setq project-switch-commands 'consult-project-extra-find))) + +(provide 'dot-selection) + +;;; dot-selection.el ends here diff --git a/.config/emacs/site-lisp/dot-setup-el.el b/.config/emacs/site-lisp/dot-setup-el.el new file mode 100644 index 0000000..8ec2ad5 --- /dev/null +++ b/.config/emacs/site-lisp/dot-setup-el.el @@ -0,0 +1,107 @@ +;;; dot-setup.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Configure SetupEl and keywords. + +;;; Code: + +;; ----------------------------------------- +;; SetupEl + +;; Install and load SetupEl immediately +(elpaca setup (require 'setup) + +;;; Configure custom macros + +(setup-define :load-after + (lambda (&rest features) + (let ((body `(require ',(setup-get 'feature)))) + (dolist (feature (nreverse features)) + (setq body `(with-eval-after-load ',feature ,body))) + body)) + :documentation "Load the current feature after FEATURES.") + +(setup-define :autoload + (lambda (func) + (let ((fn (if (memq (car-safe func) '(quote function)) + (cadr func) + func))) + `(unless (fboundp (quote ,fn)) + (autoload (function ,fn) ,(symbol-name (setup-get 'feature)) nil t)))) + :documentation "Autoload COMMAND if not already bound." + :repeatable t + :signature '(FUNC ...)) + +(setup-define :defer + (lambda (secs) + `(if (numberp ,secs) + (run-with-idle-timer ,secs nil (lambda () (require ',(setup-get 'feature)))) + ,(setup-quit))) + :documentation "Defer loading of feature for SECS idle seconds.") + +;;; Configure custom macros for evil bindings + +(setup-define :with-evil-state + (lambda (states &rest body) + (setup-bind body (states states))) + :documentation "Change the STATE that BODY will bind to." + :indent 1) + +(setup-define :evil-bind-impl + (lambda (key command) + `(evil-define-key* ',(setup-get 'states) ,(setup-get 'map) ,key ,command)) + :documentation "Bind KEY to COMMAND in the current map." + :after-loaded t + :ensure '(kbd func) + :repeatable t) + +(setup-define :evil-bind + (lambda (states &rest keybinds) + `(with-eval-after-load 'evil + (:with-evil-state ,states (:evil-bind-impl ,@keybinds)))) + :documentation "Bind KEYBINDS in STATES in the current map.") + +(setup-define :evil-bind-into + (lambda (states feature-or-map &rest keybinds) + (if (string-match-p "-map\\'" (symbol-name feature-or-map)) + `(:with-map ,feature-or-map (:evil-bind ,states ,@keybinds)) + `(:with-feature ,feature-or-map (:evil-bind ,states ,@keybinds)))) + :documentation "Bind KEYBINDS in STATE into the map of FEATURE-OR-MAP. +The arguments REST are handled as by `:evil-bind'." + :indent 1) +) + +;;; Add setup.el macro + +;;;###autoload +(defmacro elpaca-setup (order &rest body) + "Execute BODY in `setup' declaration after ORDER is finished. +If the :disabled keyword is present in body, the package is completely ignored. +This happens regardless of the value associated with :disabled. +The expansion is a string indicating the package has been disabled." + (declare (indent 1)) + (if (memq :disabled body) + (format "%S :disabled by elpaca-setup" order) + (let ((o order)) + (when-let ((ensure (cl-position :ensure body))) + (setq o (if (null (nth (1+ ensure) body)) nil order) + body (append (cl-subseq body 0 ensure) + (cl-subseq body (+ ensure 2))))) + `(elpaca ,o (setup + ,(if-let (((memq (car-safe order) '(quote \`))) + (feature (flatten-tree order))) + (cadr feature) + (elpaca--first order)) + ,@body))))) + +;; Startup benchmark +(elpaca-setup benchmark-init + (:require benchmark-init) + (:when-loaded + (benchmark-init/activate) + (add-hook 'elpaca-after-init-hook #'benchmark-init/deactivate))) + +(provide 'dot-setup-el) + +;;; dot-setup.el ends here diff --git a/.config/emacs/site-lisp/dot-ui.el b/.config/emacs/site-lisp/dot-ui.el new file mode 100644 index 0000000..d1b52c9 --- /dev/null +++ b/.config/emacs/site-lisp/dot-ui.el @@ -0,0 +1,249 @@ +;;; dot-ui.el --- -*- lexical-binding: t; -*- + +;;; Commentary: + +;; Setup UI packages. + +;;; Code: + +;; ----------------------------------------- +;; All the icons + +(elpaca-setup all-the-icons + (:require all-the-icons) + (:when-loaded + + ;; Install all-the-icons if font files are not found + (dot/run-after-new-frame + (unless (find-font (font-spec :name "all-the-icons")) + (all-the-icons-install-fonts t))))) + +(elpaca-setup all-the-icons-dired + (:hook-into dired-mode) + (:load-after all-the-icons) + (:when-loaded (setq all-the-icons-dired-monochrome nil))) + +;; ----------------------------------------- +;; Centaur tabs + +;; Places buffers as tabs in a bar at the top of the frame. + +(elpaca-setup centaur-tabs + (:load-after all-the-icons) + (:with-mode + (eshell-mode + help-mode + helpful-mode + mu4e-view-mode + neotree-mode + shell-mode) + (:hook centaur-tabs-local-mode)) + (:when-loaded + (setq centaur-tabs-enable-ido-completion nil) + (setq centaur-tabs-height (if dot/hidpi 38 18)) + (setq centaur-tabs-modified-marker "•") + (setq centaur-tabs-set-icons t) + (setq centaur-tabs-set-modified-marker t) + (setq centaur-tabs-style "slant") + + (setq centaur-tabs-project-buffer-group-calc nil) + (defun centaur-tabs-buffer-groups () + "Organize tabs into groups by buffer." + (unless centaur-tabs-project-buffer-group-calc + (set (make-local-variable 'centaur-tabs-project-buffer-group-calc) + (list + (cond + ((string-equal "*" (substring (buffer-name) 0 1)) "Emacs") + ((or (memq major-mode '(magit-process-mode + magit-status-mode + magit-diff-mode + magit-log-mode + magit-file-mode + magit-blob-mode + magit-blame-mode)) + (string= (buffer-name) "COMMIT_EDITMSG")) "Magit") + ((project-current) (dot/project-project-name)) + ((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 "Other"))))) + (symbol-value 'centaur-tabs-project-buffer-group-calc)) + + (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 matches below blacklist + (string-match-p "^ ?\\*.*\\*" 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))) + +;; ----------------------------------------- +;; Dashboard + +(elpaca-setup page-break-lines + (:require page-break-lines)) + +(elpaca-setup dashboard + (:require dashboard) + (:hook dot/hook-disable-line-numbers) + (:when-loaded + (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) + (setq dashboard-banner-logo-title "GNU Emacs master race!") + (setq dashboard-center-content t) + (setq dashboard-page-separator "\n\f\n") + (setq dashboard-projects-backend 'project-el) + (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"))) + + (let ((command-line-args '("emacs"))) ;; TODO: Remove this when switching over + (dashboard-setup-startup-hook) + ) + )) + +;; ----------------------------------------- +;; Helpful + +;; A better *help* buffer. + +(elpaca-setup helpful + (:require helpful) + (:hook dot/hook-disable-line-numbers)) + +;; ----------------------------------------- +;; Neotree + +;; Provides Emacs with a file tree. + +(elpaca-setup neotree + (:autoload neotree-toggle) + (:hook dot/hook-disable-line-numbers) + (:hook hl-line-mode) + + ;; This needs to be in init to actually start loading the package + (with-eval-after-load 'project + (defun neotree-toggle-in-project-root () + "Toggle Neotree in project root." + (interactive) + (let ((default-directory (dot/find-project-root))) + (call-interactively #'neotree-toggle)))) + + (:when-loaded + (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)))) + +;; ----------------------------------------- +;; Telephone Line + +;; Emacs mode line replacement. + +(elpaca-setup telephone-line + (:require telephone-line) + (:when-loaded + (setq telephone-line-height (if dot/hidpi 30 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-project-segment)))) + (telephone-line-mode))) + +;; ----------------------------------------- +;; Theme + +(elpaca-setup hybrid-reverse-theme + (:require hybrid-reverse-theme) + (:when-loaded + (dot/run-after-new-frame + (load-theme 'hybrid-reverse t)))) + +;; ----------------------------------------- +;; Which-key + +;; Popup that displays available key bindings. + +(elpaca-setup which-key + (:hook-into elpaca-after-init) + (:when-loaded + (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)))))) + +(provide 'dot-ui) + +;;; dot-ui.el ends here diff --git a/.config/emacs/snippets/c++-mode/namespace b/.config/emacs/snippets/c++-mode/namespace index 44cd8c7..bbcb002 100644 --- a/.config/emacs/snippets/c++-mode/namespace +++ b/.config/emacs/snippets/c++-mode/namespace @@ -4,6 +4,6 @@ # -- namespace ${1:Namespace} { - $0 +$0 } // namespace $1