#+STARTUP: overview #+TITLE: Ricemacs, an Emacs Configuration #+AUTHOR: Riyyi #+LANGUAGE: en #+OPTIONS: toc:nil #+SETUPFILE: https://fniessen.github.io/org-html-themes/org/theme-readtheorg.setup #+LATEX_HEADER: \usepackage{color} #+LATEX_HEADER: \usepackage[top=100pt,bottom=100pt,left=75pt,right=75pt]{geometry} #+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: - [[#lexical-binding][Lexical Binding]] - [[#global-variables][Global Variables]] - [[#customizations][Customizations]] - [[#package-management][Package Management]] - [[#ensure][Ensure]] - [[#auto-update][Auto update]] - [[#compile][Compile]] - [[#packages][Packages]] - [[#general-packages][General Packages]] - [[#evil][Evil]] - [[#telephone-line][Telephone Line]] - [[#neotree][NeoTree]] - [[#centaur-tabs][Centaur Tabs]] - [[#projectile][Projectile]] - [[#org-packages][Org Packages]] - [[#org-toc][Org ToC]] - [[#org-roam][Org Roam]] - [[#org-export-packages][Org Export Packages]] - [[#completion][Completion]] - [[#company][Company]] - [[#yasnippet][YASnippet]] - [[#checkers][Checkers]] - [[#flycheck][Flycheck]] - [[#flyspell][Flyspell]] - [[#programming-integration][Programming Integration]] - [[#lsp][LSP]] - [[#dap][DAP]] - [[#programming-languages][Programming Languages]] - [[#cc][C/C++]] - [[#lua][Lua]] - [[#php][PHP]] - [[#cmake][CMake]] - [[#glsl][GLSL]] - [[#yaml][YAML]] - [[#rss][RSS]] - [[#git][Git]] - [[#prettify][Prettify]] - [[#general][General]] - [[#buffers][Buffers]] - [[#electric][Electric]] - [[#file-paths][File Paths]] - [[#file-backups-versioning][File Backups Versioning]] - [[#formatting][Formatting]] - [[#hide-elements][Hide Elements]] - [[#org][Org]] - [[#org-config][Org Config]] - [[#org-agenda][Org Agenda]] - [[#org-keys][Org Keys]] - [[#org-links][Org Links]] - [[#org-source-code-blocks][Org Source Code Blocks]] - [[#org-export][Org Export]] - [[#recentf][Recentf]] - [[#tabs][Tabs]] - [[#utf-8][UTF-8]] - [[#window][Window]] - [[#functions][Functions]] - [[#general-functions][General Functions]] - [[#package-functions][Package Functions]] - [[#auto-package-update-functions][Auto Package Update Functions]] - [[#centaur-tabs-functions][Centaur Tabs Functions]] - [[#dap-functions][DAP Functions]] - [[#dashboard-functions][Dashboard Functions]] - [[#diff-hl-functions][Diff-hl Functions]] - [[#evil-functions][Evil functions]] - [[#lsp-functions][LSP Functions]] - [[#neotree-functions][Neotree Functions]] - [[#org-functions][Org Functions]] - [[#org-roam-functions][Org Roam Functions]] - [[#projectile-functions][Projectile Functions]] - [[#selectrum-functions][Selectrum Functions]] - [[#which-key-functions][Which-Key Functions]] - [[#advice-and-aliases][Advice and Aliases]] - [[#advice][Advice]] - [[#aliases][Aliases]] - [[#general-1][General]] - [[#package][Package]] - [[#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]] * Lexical Binding #+BEGIN_SRC emacs-lisp ;;; -*- lexical-binding: t; -*- #+END_SRC * 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")) (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. *** General Packages #+BEGIN_SRC emacs-lisp (use-package hybrid-reverse-theme :ensure nil :load-path "~/code/elisp/emacs-hybrid-reverse" :config (load-theme 'hybrid-reverse t)) (use-package all-the-icons :defer t :config ;; Install all-the-icons if font files are not found (unless (file-exists-p "~/.local/share/fonts/all-the-icons.ttf") (call-interactively #'all-the-icons-install-fonts))) (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 5) (setq which-key-sort-order 'dot/which-key-prefix-then-key-order-alpha) (setq which-key-sort-uppercase-first nil)) (use-package general) (use-package selectrum :hook (emacs-startup . selectrum-mode)) (use-package prescient :after selectrum :config (setq prescient-filter-method '(literal regexp fuzzy)) (setq prescient-save-file (concat dot-cache-dir "/prescient-save.el")) (prescient-persist-mode)) (use-package selectrum-prescient :after (selectrum prescient) :config (selectrum-prescient-mode)) (use-package marginalia :after selectrum :config (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light)) (marginalia-mode)) (use-package consult :after selectrum :config (setq consult-project-root-function #'dot/find-project-root)) (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)) #+END_SRC *** Evil Evil mode and related packages. #+BEGIN_SRC emacs-lisp (use-package undo-tree :config (global-undo-tree-mode)) (use-package goto-chg) (use-package evil :after (undo-tree goto-chg) :init (setq evil-ex-complete-emacs-commands nil) (setq evil-kill-on-visual-paste nil) (setq evil-operator-state-cursor 'box) ; Do not set half cursor (setq evil-search-module 'evil-search) (setq evil-split-window-below t) (setq evil-undo-system 'undo-tree) (setq evil-vsplit-window-right t) (setq evil-want-C-u-scroll t) (setq evil-want-Y-yank-to-eol t) (setq evil-want-keybinding nil) ; Needed by evil-collection :config (evil-mode)) (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 *** Telephone Line Emacs mode line replacement. #+BEGIN_SRC emacs-lisp (use-package telephone-line :config (setq telephone-line-height (if dot/hidpi 20 15)) (setq telephone-line-lhs '((evil . (telephone-line-evil-tag-segment)) (accent . (telephone-line-erc-modified-channels-segment telephone-line-process-segment telephone-line-buffer-segment)) (nil . (telephone-line-projectile-segment)))) (telephone-line-mode)) #+END_SRC *** 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) :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 *** Centaur Tabs Places buffers as tabs in a bar at the top. #+BEGIN_SRC emacs-lisp (use-package centaur-tabs :after all-the-icons :demand :hook ((eshell-mode help-mode helpful-mode neotree-mode org-roam-backlinks-mode shell-mode) . centaur-tabs-local-mode) :config (setq centaur-tabs-enable-ido-completion nil) (setq centaur-tabs-height (if dot/hidpi 28 18)) (setq centaur-tabs-modified-marker "•") (setq centaur-tabs-set-icons t) (setq centaur-tabs-set-modified-marker t) (setq centaur-tabs-style "slant") (centaur-tabs-headline-match) (centaur-tabs-mode)) #+END_SRC *** Projectile Project manager. #+BEGIN_SRC emacs-lisp (use-package projectile :defer t :config (setq projectile-cache-file (concat dot-cache-dir "/projectile.cache")) (setq projectile-completion-system 'default) (setq projectile-enable-caching t) (setq projectile-indexing-method 'hybrid) (setq projectile-known-projects-file (concat dot-cache-dir "/projectile-bookmarks.eld")) (setq projectile-project-search-path '("~")) (setq projectile-sort-order 'recentf) (projectile-mode)) #+END_SRC *** Org Packages **** Org ToC Generate table of contents without exporting. #+BEGIN_SRC emacs-lisp (use-package toc-org :defer t) #+END_SRC **** Org Roam Setup =org-roam=. #+BEGIN_SRC emacs-lisp (use-package org-roam :hook (emacs-startup . org-roam-mode) :hook (org-roam-backlinks-mode . dot/hook-disable-line-numbers) :hook (org-roam-backlinks-mode . dot/hook-disable-mode-line) :config (setq org-image-actual-width nil) (setq org-roam-completion-system 'default) (setq org-roam-db-location (expand-file-name "org-roam.db" dot-cache-dir)) (setq org-roam-directory (expand-file-name "./" org-directory)) ;; Exclude Syncthing backup directory (setq org-roam-file-exclude-regexp "\\.stversions") (setq org-roam-title-to-slug-function #'dot/org-roam-title-to-slug) (setq org-roam-verbose nil) ;; Templates used when creating a new file (setq org-roam-capture-templates '(("d" "default" plain #'org-roam-capture--get-point "%?" :file-name "%<%Y%m%d%H%M%S>-${slug}" :head "#+TITLE: ${title}\n#+ROAM_TAGS: %^{Roam tags}\n" :unnarrowed t)))) #+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 #'org-roam-capture--get-point "%?" :file-name "${slug}" :head "#+TITLE: ${title}\n#+ROAM_KEY: ${ref}\n\n${body}" :unnarrowed t)))) #+END_SRC The roam-ref protocol bookmarks to add: #+BEGIN_SRC javascript :tangle no 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-server=. #+BEGIN_SRC emacs-lisp (use-package simple-httpd :after org-roam) (use-package org-roam-server :after (org-roam simple-httpd) :config (setq org-roam-server-host "127.0.0.1") (setq org-roam-server-port 8080) (setq org-roam-server-network-arrows "from") (setq org-roam-server-style (concat "button#toggle-preview { margin: 4px; }" "div#view-menu { margin: 4px; }" "div#controls { right: 4px; left: 4px; bottom: 4px; }" "button#toggle-list-type-button { margin: 0 4px; }" "label#colormode { transform: translate(-25%, 0); }" "label.toggle-off.btn-sm { padding-left: 0px; }" ))) #+END_SRC Easily searchable .org files via Deft. #+BEGIN_SRC emacs-lisp (use-package deft :hook (deft-mode . dot/hook-disable-line-numbers) :config (setq deft-auto-save-interval 0) (setq deft-default-extension "org") (setq deft-directory "~/documents/org/") (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) (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)) #+END_SRC **** Org Export Packages #+BEGIN_SRC emacs-lisp ;; HTML exporter (use-package htmlize :defer t :config (setq org-export-html-postamble nil)) ;org-export-html-postamble-format @ToDo ;; Github flavored Markdown exporter (use-package ox-gfm :defer t) #+END_SRC *** Completion Autocomplete packages (includes code completion and snippets). **** 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)) (use-package company-prescient :after company :config (company-prescient-mode 1)) #+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 *** Checkers **** Flycheck On the fly syntax checking. #+BEGIN_SRC emacs-lisp (use-package flycheck :hook ((c-mode-common emacs-lisp-mode latex-mode org-mode php-mode sh-mode shell-mode shell-script-mode) . flycheck-mode) :config (setq flycheck-clang-language-standard "c++17") (setq flycheck-gcc-language-standard "c++17")) ;; For .el files which are intended to be packages (use-package flycheck-package :after flycheck :config (add-to-list 'flycheck-checkers 'flycheck-emacs-lisp-package) (flycheck-package-setup)) (use-package flycheck-clang-tidy :after flycheck :hook (flycheck-mode . flycheck-clang-tidy-setup) :config (setq flycheck-clang-tidy-extra-options "--format-style=file")) #+END_SRC **** Flyspell Give Flyspell a selection menu. #+BEGIN_SRC emacs-lisp (use-package flyspell-correct :after flyspell :config (setq flyspell-issue-message-flag nil) (setq flyspell-issue-welcome-flag nil)) #+END_SRC *** Programming Integration **** LSP 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 . lsp-deferred) :config (setq lsp-auto-guess-root t) (setq lsp-clients-clangd-args '("-j=2" "--background-index" "--clang-tidy" "--compile-commands-dir=build" "--log=error" "--pch-storage=memory")) (setq lsp-clients-lua-language-server-install-dir "/usr/share/lua-language-server/") (setq lsp-clients-lua-language-server-bin "/usr/bin/lua-language-server") (setq lsp-enable-xref t) (setq lsp-headerline-breadcrumb-enable nil) (setq lsp-intelephense-storage-path (concat dot-cache-dir "/lsp-cache")) (setq lsp-keep-workspace-alive nil) (setq lsp-prefer-flymake nil) (setq lsp-session-file (concat dot-cache-dir "/lsp-session-v1")) ;; Mark clangd args variable as safe to modify via .dir-locals.el (put 'lsp-clients-clangd-args 'safe-local-variable #'listp) ;; Enable which-key descriptions (dolist (leader-key (list dot/leader-key dot/leader-alt-key)) (let ((lsp-keymap-prefix (concat leader-key " l"))) (lsp-enable-which-key-integration)))) (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-enable nil) (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-enable t) (setq lsp-ui-flycheck-list-position 'right) (setq lsp-ui-flycheck-live-reporting t) (setq lsp-ui-peek-enable nil) (setq lsp-ui-sideline-enable nil) (setq lsp-ui-sideline-show-symbol nil)) #+END_SRC **** DAP 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))) #+END_SRC *** Programming Languages **** C/C++ #+BEGIN_SRC emacs-lisp (use-package company-c-headers :after company :config (push 'company-c-headers company-backends)) (use-package company-glsl :after company :config (when (executable-find "glslangValidator") (add-to-list 'company-backends 'company-glsl))) #+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) (setq lsp-ui-doc-enable t)))) (use-package restclient :defer t) #+END_SRC **** CMake #+BEGIN_SRC emacs-lisp (use-package cmake-mode :defer t) #+END_SRC **** GLSL #+BEGIN_SRC emacs-lisp (use-package glsl-mode :defer t) #+END_SRC **** YAML #+BEGIN_SRC emacs-lisp (use-package yaml-mode :defer t) #+END_SRC *** RSS #+BEGIN_SRC emacs-lisp (use-package 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 *** 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)) (use-package transient :defer t :config (setq transient-history-file (concat dot-cache-dir "/transient/history.el"))) (use-package magit :after (diff-hl transient) :hook (git-commit-setup . git-commit-turn-on-auto-fill) :hook (git-commit-setup . git-commit-turn-on-flyspell) :hook (magit-pre-refresh . diff-hl-magit-pre-refresh) :hook (magit-post-refresh . diff-hl-magit-post-refresh) :config (setq git-commit-summary-max-length 70) (setq magit-diff-paint-whitespace-lines 'both) (setq magit-repository-directories '(("~/dotfiles" . 0) ("~/code" . 3)))) #+END_SRC *** Prettify #+BEGIN_SRC emacs-lisp (use-package page-break-lines) (use-package dashboard :demand :hook (dashboard-mode . dot/hook-disable-line-numbers) :config (setq initial-buffer-choice (lambda () (get-buffer "*dashboard*"))) (setq dashboard-banner-logo-title "GNU Emacs master race!") (setq dashboard-center-content t) (setq dashboard-page-separator "\n\f\n") (setq dashboard-set-file-icons t) (setq dashboard-set-footer nil) (setq dashboard-set-heading-icons t) (setq dashboard-show-shortcuts t) (setq dashboard-startup-banner 'logo) (setq dashboard-items '((projects . 10) (bookmarks . 5) (recents . 5))) (dashboard-setup-startup-hook)) ;; A better *help* buffer (use-package helpful :hook (helpful-mode . dot/hook-disable-line-numbers)) (use-package rainbow-mode :hook (prog-mode . rainbow-mode)) (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode)) (use-package org-bullets :hook (org-mode . org-bullets-mode)) #+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 ** 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 ** Org *** Org Config #+BEGIN_SRC emacs-lisp (use-package org :config (setq org-directory (concat (getenv "HOME") "/documents/org")) (setq org-default-notes-file (expand-file-name "notes.org" org-directory)) (setq org-adapt-indentation nil) (setq org-ellipsis "⤵") ;; 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 :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 Keys #+BEGIN_SRC emacs-lisp (use-package org-keys :ensure nil :config (setq org-return-follows-link t)) #+END_SRC *** Org Links #+BEGIN_SRC emacs-lisp (use-package ol :ensure nil :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 :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 Export #+BEGIN_SRC emacs-lisp ;; Org exporter (use-package ox :ensure nil :defer t :config (setq org-export-coding-system 'utf-8-unix)) ;; Org latex exporter (use-package ox-latex :ensure nil :defer t :config ;; Define how minted (highlighted src code) is added to src code blocks (setq org-latex-listings 'minted) (setq org-latex-minted-options '(("frame" "lines") ("linenos=true"))) ;; Set 'Table of Contents' layout (setq org-latex-toc-command "\\newpage \\tableofcontents \\newpage") ;; Add minted package to every LaTeX header (add-to-list 'org-latex-packages-alist '("" "minted")) ;; Append -shell-escape so pdflatex exports minted correctly (add-to-list 'org-latex-pdf-process (replace-regexp-in-string "%latex " "%latex -shell-escape " (car org-latex-pdf-process)))) #+END_SRC ** Recentf #+BEGIN_SRC emacs-lisp (use-package recentf :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 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 * 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/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/find-file-recentf () "Use `completing-read' to open a recent file." (interactive) (let ((files (mapcar 'abbreviate-file-name recentf-list))) (find-file (completing-read "Find file (recent): " 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 ** Package Functions Functions that use package functionality. *** Auto Package Update Functions #+BEGIN_SRC emacs-lisp (defun dot/update-packages () "Update all packages." (interactive) (package-refresh-contents) (auto-package-update-now) (package-quickstart-refresh)) #+END_SRC *** Centaur Tabs Functions #+BEGIN_SRC emacs-lisp (with-eval-after-load 'centaur-tabs (defun centaur-tabs-buffer-groups () "Organize tabs into groups by buffer." (list (cond ((string-equal "*" (substring (buffer-name) 0 1)) "Emacs") ((memq major-mode '(org-mode emacs-lisp-mode)) "Org Mode") ((derived-mode-p 'dired-mode) "Dired") ((derived-mode-p 'prog-mode 'text-mode) "Editing") (t "User")))) (defun centaur-tabs-hide-tab (buffer) "Hide from the tab bar by BUFFER name." (let ((name (format "%s" buffer))) (or ;; Current window is dedicated window (window-dedicated-p (selected-window)) ;; Buffer name does match below blacklist (string-match-p (concat "\\(CAPTURE-\\)?" (format-time-string "%Y%m%d%H%M%S") "-.*\\.org") name) (string-match-p (concat "^ ?\\*\\(" "Agenda Commands\\|" "e?shell\\|" "Compile-Log\\|" "Completions\\|" "clangd\\|" ; lsp c/c++ "dap-mouse\\|" "dap-ui-\\|" "Debug\\|" "Faces\\|" "Flycheck\\|" "Help\\|" "helpful\\|" "httpd\\|" "iph\\|" ; lsp php "org-roam\\|" "Org tags\\|" "Org todo" "\\).*") name)))) (defun dot/centaur-tabs-is-buffer-unimportant (buffer) "Return t if BUFFER is unimportant and can be killed without caution." (let ((name (format "%s" buffer))) (cond ((centaur-tabs-hide-tab name) t) ((string-match-p "^magit\\(-[a-z]+\\)*: .*" name) t) (t nil)))) (defun dot/centaur-tabs-buffer-cleanup () "Clean up all the hidden buffers." (interactive) (dolist (buffer (buffer-list)) (when (dot/centaur-tabs-is-buffer-unimportant buffer) (kill-buffer buffer)))) (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)))) #+END_SRC *** DAP Functions #+BEGIN_SRC emacs-lisp (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 *** Dashboard Functions #+BEGIN_SRC emacs-lisp (with-eval-after-load 'dashboard (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)))) #+END_SRC Fix keybinds.. #+BEGIN_SRC emacs-lisp (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"))) #+END_SRC *** Diff-hl Functions #+BEGIN_SRC emacs-lisp (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)))) #+END_SRC *** Evil functions #+BEGIN_SRC emacs-lisp (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-beginning-position) (line-end-position))) (defun dot/evil-visual-shift-left () "Shift visual selection left, retains the selection. Vim equivalence: gv" (interactive) (evil-shift-right (region-beginning) (region-end)) (funcall (evil-visual-restore))) #+END_SRC *** LSP Functions #+BEGIN_SRC emacs-lisp (defun lsp-format-region-or-buffer () "Format the selection (or buffer) with LSP." (interactive) (unless (bound-and-true-p lsp-mode) (user-error "Not in an LSP buffer")) (call-interactively (if (use-region-p) #'lsp-format-region #'lsp-format-buffer))) #+END_SRC *** Neotree Functions #+BEGIN_SRC emacs-lisp (defun neotree-toggle-in-project-root () "Toggle Neotree in project root." (interactive) (let ((default-directory (dot/find-project-root))) (call-interactively #'neotree-toggle))) #+END_SRC *** Org Functions #+BEGIN_SRC emacs-lisp (defun dot/org-ret-at-point () "Org return key at point. If point is on: checkbox -- toggle it link -- follow it otherwise -- run the default (evil-ret) expression" (interactive) (let ((type (org-element-type (org-element-context)))) (pcase type ('link (if org-return-follows-link (org-open-at-point) (evil-ret))) ((guard (org-at-item-checkbox-p)) (org-toggle-checkbox)) (_ (evil-ret)) ))) #+END_SRC *** Org Roam Functions #+BEGIN_SRC emacs-lisp (defun dot/org-roam-title-to-slug (title) "Convert TITLE to a filename-suitable slug, strip out common words." (let* ((common-words '("a" "an" "and" "as" "at" "by" "is" "it" "of" "the" "to")) (title (replace-regexp-in-string "\\(c\\+\\+\\)" "cpp" title)) (title (replace-regexp-in-string "\\(c\\#\\)" "cs" title)) (words (split-string (org-roam--title-to-slug title) "\_"))) (string-join (seq-remove (lambda (element) (member element common-words)) words) "_"))) #+END_SRC *** Projectile Functions #+BEGIN_SRC emacs-lisp (defun dot/find-project-root () "Return root of the project, determined by `.git/' and `.projectile', `default-directory' otherwise." (let ((search-directory (projectile-project-root))) (if search-directory search-directory default-directory))) (defun find-file-in-project-root () "Find file in project root." (interactive) (let ((default-directory (dot/find-project-root))) (call-interactively 'find-file))) (defun compile-latex () "Compile LaTeX project." (interactive) (let ((default-directory (dot/find-project-root))) (projectile-save-project-buffers) (shell-command "make"))) #+END_SRC *** Selectrum Functions #+BEGIN_SRC emacs-lisp (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))) #+END_SRC *** Which-Key Functions #+BEGIN_SRC emacs-lisp (with-eval-after-load 'which-key (defun dot/which-key-prefix-then-key-order-alpha (acons bcons) "Order y 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 * 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 *** General Make confirm easier, by just pressing y/n. #+BEGIN_SRC emacs-lisp (defalias 'yes-or-no-p 'y-or-n-p) #+END_SRC *** Package Evil command aliases. #+BEGIN_SRC emacs-lisp (with-eval-after-load 'evil-ex (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 * 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) ;; Enable 'table of contents' in org (add-hook 'org-mode-hook 'toc-org-mode) ;; Org-capture in new tab, rather than split window (add-hook 'org-capture-mode-hook 'delete-other-windows) ;; C++ // style comments in c-mode (add-hook 'c-mode-hook (lambda () (c-toggle-comment-style 0))) ;; LaTeX, set correct tab mode (add-hook 'latex-mode-hook (lambda () (setq indent-tabs-mode t))) ;; 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)) #+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") '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 ;; 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") ;; 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 ; << ) (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 ) ;; 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) ) #+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" '(bookmark-jump :which-key "Jump 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" '(switch-to-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 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") "f d" '(dired :which-key "Find directory") "f f" '(find-file-in-project-root :which-key "Find file") "f o" '(ff-find-other-file :which-key "Find header/source file") "f r" '(dot/find-file-recentf :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") ;; Git "g" '(:ignore t :which-key "git") "g b" '(magit-branch-checkout :which-key "Magit switch branch") "g B" '(magit-blame-addition :which-key "Magit blame") "g c" '(:ignore t :which-key "create") "g c c" '(magit-commit-create :which-key "Commit") "g c b" '(magit-branch-and-checkout :which-key "Branch") "g c r" '(magit-init :which-key "Initialize repo") "g C" '(magit-clone :which-key "Magit clone") "g f" '(:ignore t :which-key "file") "g f c" '(magit-find-git-config-file :which-key "Find gitconfig file") "g f D" '(magit-file-delete :which-key "Delete file") "g f f" '(magit-find-file :which-key "Find file") "g f R" '(magit-file-rename :which-key "Rename file") "g F" '(magit-fetch :which-key "Magit fetch") "g g" '(magit-status :which-key "Magit status") "g G" '(magit-status-here :which-key "Magit status here") "g l" '(:ignore t :which-key "list") "g l r" '(magit-list-repositories :which-key "List repositories") "g l s" '(magit-list-submodules :which-key "List submodules") "g L" '(magit-log :which-key "Magit log") "g s" '(magit-show-commit :which-key "Magit show commit") "g S" '(magit-stage-file :which-key "Stage file") "g U" '(magit-unstage-file :which-key "Unstage file") ;; 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 b" '(org-roam-switch-to-buffer :which-key "Switch buffer") "n r c" '(org-roam-capture :which-key "Capture") "n r C" '(org-roam-db-build-cache :which-key "Build cache") "n r f" '(org-roam-find-file :which-key "Find file") "n r g" '(org-roam-graph-show :which-key "Show graph") "n r i" '(org-roam-insert :which-key "Insert") "n r I" '(org-roam-insert-immediate :which-key "Insert (without capture)") "n r r" '(org-roam :which-key "Toggle side-buffer") "n r s" '(org-roam-server-mode :which-key "Toggle server") ;; Projectile "p" '(:keymap projectile-command-map :package projectile :which-key "projectile") ;; 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 b" '(bookmark-jump :which-key "Jump to bookmark") "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 b" '(centaur-tabs-group-buffer-groups :which-key "Group tabs by buffer") "t f" '(dot/toggle-fringe :which-key "Toggle fringe") "t p" '(centaur-tabs-group-by-projectile-project :which-key "Group tabs by project") "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 w" '(visual-line-mode :which-key "Toggle line wrapping") ;; Update packages "U" '(dot/update-packages :which-key "Update packages") ;; 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 " '(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") ;; winner-redo (built-in window history) ;; winner-undo ) #+END_SRC Evaluated keybinds. #+BEGIN_SRC emacs-lisp (with-eval-after-load 'lsp-mode (space-leader lsp-mode-map "l" lsp-command-map )) (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 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") "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") "q" '(org-set-tags-command :which-key "Org tags") "s" '(:ignore t :which-key "tree/subtree") "s h" '(org-promote-subtree :which-key "Org promote subtree") "s j" '(org-move-subree-down :which-key "Org move subtree down") "s k" '(org-move-subtree-up :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) |