Features
Key features.
Preamble
;;; features.el --- Cunene: My emacs configuration. -*- lexical-binding: t -*- ;; Author: Marco Craveiro <marco_craveiro@gmail.com> URL: ;; https://github.com/mcraveiro/prelude Version: 0.0.3 Keywords: convenience ;; This file is not part of GNU Emacs. ;;; Commentary: ;; General editor configuration ;;; License: ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License ;; as published by the Free Software Foundation; either version 3 ;; of the License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Code:
Regular Expressions
reb |
Built-in |
Setup REB.
Links:
(require 're-builder) (setq reb-re-syntax 'string) ;; No need for double-slashes
Use REB with query replace regex.
Links:
(defun cunene/reb-replace-regexp (&optional delimited) "Run `query-replace-regexp' with the contents of `re-builder'. With non-nil optional argument DELIMITED, only replace matches surrounded by word boundaries." (interactive "P") (reb-update-regexp) (let* ((re (cunene/reb-target-binding reb-regexp)) (re-printed (with-output-to-string (print re))) (replacement (read-from-minibuffer (format "Replace regexp %s with: " (substring re-printed 1 (1- (length re-printed))))))) (with-current-buffer reb-target-buffer (query-replace-regexp re replacement delimited)))) (define-key reb-mode-map (kbd "C-M-%") 'cunene/reb-replace-regexp)
Dired
;; Dired switches (setq dired-listing-switches "-lGh1v --group-directories-first") (setq-default list-directory-brief-switches "-CF") (require 'dired) (add-hook 'dired-before-readin-hook #'(lambda () (when (file-remote-p default-directory) (setq dired-actual-switches "-l")))) ;; always delete and copy recursively (require 'dired) (setq dired-recursive-deletes 'always dired-recursive-copies 'always) ;; if there is a dired buffer displayed in the next window, use its ;; current subdir, instead of the current subdir of this dired buffer (setq dired-dwim-target t) ;; enable some really cool extensions like C-x C-j(dired-jump) (require 'dired-x) (use-package vscode-icon :commands (vscode-icon-for-file)) ;; (use-package dired-sidebar ;; :commands (dired-sidebar-toggle-sidebar) ;; :init ;; (add-hook 'dired-sidebar-mode-hook ;; (lambda () ;; (unless (file-remote-p default-directory) ;; (auto-revert-mode)))) ;; :config ;; (push 'toggle-window-split dired-sidebar-toggle-hidden-commands) ;; (push 'rotate-windows dired-sidebar-toggle-hidden-commands) ;; (setq dired-sidebar-theme 'icons ;; dired-sidebar-should-follow-file t ;; dired-sidebar-use-term-integration t ;; dired-sidebar-use-custom-font t ;; ;; dired-sidebar-face `(:family "Helvetica" :height 80) ;; dired-sidebar-face `(:height 0.6 :family "Source Code Pro") ;; dired-sidebar-width 45))
Treemacs
(use-package treemacs :ensure t :defer t :init (with-eval-after-load 'winum (define-key winum-keymap (kbd "M-0") #'treemacs-select-window)) :config (progn (setq treemacs-collapse-dirs (if treemacs-python-executable 3 0) treemacs-deferred-git-apply-delay 0.5 treemacs-directory-name-transformer #'identity treemacs-display-in-side-window t treemacs-eldoc-display 'simple treemacs-file-event-delay 2000 treemacs-file-extension-regex treemacs-last-period-regex-value treemacs-file-follow-delay 0.2 treemacs-file-name-transformer #'identity treemacs-follow-after-init t treemacs-expand-after-init t treemacs-find-workspace-method 'find-for-file-or-pick-first treemacs-git-command-pipe "" treemacs-goto-tag-strategy 'refetch-index treemacs-header-scroll-indicators '(nil . "^^^^^^") treemacs-hide-dot-git-directory t treemacs-indentation 2 treemacs-indentation-string " " treemacs-is-never-other-window nil treemacs-max-git-entries 5000 treemacs-missing-project-action 'ask treemacs-move-files-by-mouse-dragging t treemacs-move-forward-on-expand nil treemacs-no-png-images nil treemacs-no-delete-other-windows t treemacs-project-follow-cleanup nil treemacs-persist-file (expand-file-name ".cache/treemacs-persist" user-emacs-directory) treemacs-position 'left treemacs-read-string-input 'from-child-frame treemacs-recenter-distance 0.1 treemacs-recenter-after-file-follow nil treemacs-recenter-after-tag-follow nil treemacs-recenter-after-project-jump 'always treemacs-recenter-after-project-expand 'on-distance treemacs-litter-directories '("/node_modules" "/.venv" "/.cask") treemacs-project-follow-into-home nil treemacs-show-cursor nil treemacs-show-hidden-files t treemacs-silent-filewatch nil treemacs-silent-refresh nil treemacs-sorting 'alphabetic-asc treemacs-select-when-already-in-treemacs 'move-back treemacs-space-between-root-nodes t treemacs-tag-follow-cleanup t treemacs-tag-follow-delay 1.5 treemacs-text-scale nil treemacs-user-mode-line-format nil treemacs-user-header-line-format nil treemacs-wide-toggle-width 70 treemacs-width 35 treemacs-width-increment 1 treemacs-width-is-initially-locked t treemacs-workspace-switch-cleanup nil) ;; The default width and height of the icons is 22 pixels. If you are ;; using a Hi-DPI display, uncomment this to double the icon size. ;;(treemacs-resize-icons 44) (treemacs-follow-mode t) (text-scale-adjust -2) (treemacs-filewatch-mode t) (treemacs-fringe-indicator-mode 'always) (when treemacs-python-executable (treemacs-git-commit-diff-mode t)) (pcase (cons (not (null (executable-find "git"))) (not (null treemacs-python-executable))) (`(t . t) (treemacs-git-mode 'deferred)) (`(t . _) (treemacs-git-mode 'simple))) (treemacs-hide-gitignored-files-mode nil)) :bind (:map global-map ("M-0" . treemacs-select-window) ("C-x t 1" . treemacs-delete-other-windows) ("C-x t t" . treemacs) ("C-x t d" . treemacs-select-directory) ("C-x t B" . treemacs-bookmark) ("C-x t C-t" . treemacs-find-file) ("C-x t M-t" . treemacs-find-tag))) ;; (use-package treemacs-evil ;; :after (treemacs evil) ;; :ensure t) (use-package treemacs-projectile :after (treemacs projectile) :ensure t) (use-package treemacs-icons-dired :hook (dired-mode . treemacs-icons-dired-enable-once) :ensure t) (use-package treemacs-magit :after (treemacs magit) :ensure t) (use-package treemacs-persp ;;treemacs-perspective if you use perspective.el vs. persp-mode :after (treemacs persp-mode) ;;or perspective vs. persp-mode :ensure t :config (treemacs-set-scope-type 'Perspectives)) (use-package treemacs-tab-bar ;;treemacs-tab-bar if you use tab-bar-mode :after (treemacs) :ensure t :config (treemacs-set-scope-type 'Tabs))
IBuffer
(use-package ibuffer :bind (:map ibuffer-mode-map ("/ e" . ibuffer-filter-by-ede-project) ("% e" . ibuffer-mark-by-ede-project-regexp) ("s e" . ibuffer-do-sort-by-ede-project)) :config (require 'all-the-icons) (progn (global-set-key (kbd "<f5>") 'ibuffer) ;; Shortcut for ibuffer (when (display-graphic-p) ;; Display buffer icons on GUI (define-ibuffer-column icon (:name " ") (let ((icon (if (and buffer-file-name (all-the-icons-match-to-alist buffer-file-name all-the-icons-regexp-icon-alist)) (all-the-icons-icon-for-file (file-name-nondirectory buffer-file-name) :height 0.9 :v-adjust -0.05) (all-the-icons-icon-for-mode major-mode :height 0.9 :v-adjust -0.05)))) (if (symbolp icon) (setq icon (all-the-icons-faicon "file-o" :face 'all-the-icons-dsilver :height 0.9 :v-adjust -0.05)) icon)))) (add-hook 'ibuffer-mode-hook ;; Setup filter groups #'(lambda () (ibuffer-auto-mode 1) (ibuffer-switch-to-saved-filter-groups "home") (ibuffer-do-sort-by-filename/process)))) (setq ibuffer-formats '((mark modified read-only locked " " (icon 2 2 :left :elide) (name 18 18 :left :elide) " " (size 9 -1 :right) " " (mode 16 16 :left :elide) " " filename-and-process) (mark " " (name 16 -1) " " filename))) (setq ibuffer-filter-group-name-face '(:inherit (font-lock-string-face bold))) (setq ibuffer-show-empty-filter-groups nil) ;; Remove empty groups (setq ibuffer-expert t) ;; Enable expert mode (setq ibuffer-saved-filter-groups ;; Group buffers (quote (("home" ("c++" (mode . c++-mode)) ("images" (mode . image-mode)) ("python" (or (mode . python-mode) (name . "^\\*Python\\*$"))) ("fsharp" (or (mode . inferior-fsharp-mode) (mode . fsharp-mode))) ("csharp" (or (name . "^\\*sharper-log\\*$") (mode . csharp-ts-mode) (mode . csharp-mode) (mode . csproj-mode) (mode . sln-mode))) ("java" (mode . java-mode)) ("csv" (mode . csv-mode)) ("kotlin" (mode . kotlin-mode)) ("ruby" (mode . ruby-mode)) ("perl" (mode . perl-mode)) ("json" (mode . json-mode)) ("docker" (mode . dockerfile-mode)) ("javascript" (or (mode . javascript-mode) (mode . js2-mode) (mode . js-mode))) ("php" (mode . php-mode)) ("prodigy" (name . "^\\*prodigy")) ("mongo" (mode . inf-mongo-mode)) ("org" (or (name . "^\\*Org Agenda") (name . "^\\*org-roam\\*$") (mode . org-mode))) ("xml" (mode . nxml-mode)) ("sql" (or (mode . sql-mode) (name . "^\\*SQL"))) ("make" (or (mode . cmake-mode) (mode . makefile-mode) (mode . makefile-gmake-mode))) ("t4" (name . ".tt$")) ("bash" (mode . sh-mode)) ("awk" (mode . awk-mode)) ("clojure" (or (mode . inf-clojure-mode) (mode . clojure-mode))) ("plantuml" (mode . plantuml-mode)) ("latex" (or (name . ".tex$") (name . ".texi$") (mode . tex-mode) (mode . latex-mode))) ("markdown" (or (mode . markdown-mode) (mode . gfm-mode))) ("emacs-lisp" (or (mode . emacs-lisp-mode) (name . "^\\*Async-native-compile-log\\*$") (name . "^\\*ielm\\*$") (name . "^\\*Compile-Log\\*$"))) ("powershell" (or (mode . powershell-mode) (name . "^\\*PowerShell"))) ("logs" (or (mode . log4j-mode) (mode . logview-mode))) ("grep" (or (name . "^\\*Occur\\*$") (name . "^\\*Moccur\\*$") (name . "^\\*rg\\*$") (mode . grep-mode))) ("irc" (or (mode . erc-list-mode) (mode . erc-mode))) ("shell" (or (name . "^\\*Shell Command Output\\*$") (mode . shell-mode) (mode . ssh-mode) (mode . eshell-mode) (name . "^\\*compilation\\*$"))) ("file management" (or (mode . dired-mode) (mode . tar-mode))) ("sidebars" (or (mode . dired-sidebar-mode) (mode . ibuffer-sidebar-mode))) ("org" (mode . org-mode-)) ("text files" (or (mode . conf-unix-mode) (mode . conf-space-mode) (mode . text-mode))) ("yaml" (mode . yaml-mode)) ("msdos" (mode . dos-mode)) ("patches" (or (name . "^\\*Assoc file dif") (mode . diff-mode))) ("version control" (or (name . "^\\.gitignore") (name . "^\\*svn-") (name . "^\\*vc") (name . "^\\*cvs") (name . "^\\magit"))) ("snippets" (mode . snippet-mode)) ("semantic" (or (mode . data-debug-mode) (name . "^\\*Parser Output\\*$") (name . "^\\*Lexer Output\\*$"))) ("web browsing" (or (mode . w3m-mode) (mode . eww-mode) (mode . verb-mode) (name . "^\\*Verb") (name . "^\\HTTP") (name . "^\\*httpd\\*$") (mode . twittering-mode))) ("music" (or (mode . bongo-playlist-mode) (mode . bongo-library-mode))) ("mail" (or (mode . gnus-group-mode) (mode . gnus-summary-mode) (mode . gnus-article-mode) (name . "^\\*imap log\\*$") (name . "^\\*gnus trace\\*$") (name . "^\\*nnimap imap."))) ("web development" (or (mode . html-mode) (mode . css-mode))) ("documentation" (or (mode . Info-mode) (mode . apropos-mode) (mode . woman-mode) (mode . helpful-mode) (mode . help-mode) (mode . Man-mode))) ("lsp" (or (name . "^\\*eldoc") (name . "^\\*clangd") (name . "^\\*company-") (name . "^\\*omnisharp") (name . "^\\*Ilist") (name . "^\\*lsp"))) ("system" (or (name . "^\\*Packages\\*$") (name . "^\\*helm M-x\\*$") (name . "^\\*helm mini\\*$") (name . "^\\*helm projectile\\*$") (name . "^\\*RTags Log\\*$") (name . "^\\**RTags Diagnostics\\*$") (name . "^\\*tramp") (name . "^\\**input/output of") (name . "^\\**threads of") (name . "^\\**breakpoints of") (name . "^\\**Flycheck") (name . "^\\*Flymake Log\\*$") (name . "^\\**sx-search-result*") (name . "^\\**gud-dogen.knit") (name . "^\\**Warnings*") (name . "^\\*debug tramp") (name . "^\\*Proced log\\*$") (name . "^\\*Ediff Registry\\*$") (name . "^\\*Bookmark List\\*$") (name . "^\\*RE-Builder\\*$") (name . "^\\*Kill Ring\\*$") (name . "^\\*Calendar\\*$") (name . "^\\*icalendar-errors\\*$") (name . "^\\*Proced\\*$") (name . "^\\*WoMan-Log\\*$") (name . "^\\*Apropos\\*$") (name . "^\\*Completions\\*$") (name . "^\\*Help\\*$") (name . "^\\*helpful") (name . "^\\*Dired log\\*$") (name . "^\\*scratch\\*$") (name . "^\\*gnuplot\\*$") (name . "^\\*Flycheck errors\\*$") (name . "^\\*compdb:") (name . "^\\*Backtrace\\*$") (name . "^\\*dashboard\\*$") (name . "^\\*timer-list\\*$") (name . "^\\*Messages\\*$"))) ("Treemacs" (or (name . "^Treemacs Update") (name . "^\\*nnimap imap."))) ))))) (use-package ibuffer-sidebar :commands (ibuffer-sidebar-toggle-sidebar) :config (setq ibuffer-sidebar-use-custom-font t ibuffer-sidebar-face `(:family "Source Code Pro" :height 0.8))) (use-package ibuffer-vc) (defun cunene/sidebar-toggle () "Toggle both `dired-sidebar' and `ibuffer-sidebar'." (interactive) (dired-sidebar-toggle-sidebar) (ibuffer-sidebar-toggle-sidebar))
Buffers and Windows
desktop |
Built-in |
shackle |
https://github.com/wasamasa/shackle |
windswap |
https://github.com/purcell/windswap |
windmove |
Built-in |
winner |
Built-in |
framemove |
https://github.com/emacsmirror/framemove |
Bind keys to manage windows and buffers that are more popular.
(global-set-key (kbd "s-w") #'delete-window) (global-set-key (kbd "s-W") #'kill-this-buffer)
Save and restore Emacs status, including buffers, point and window configurations.
;; could not get it to work via use-package; commands did not kick-in ;; and kept trying to reload from elpa. (require 'desktop) (desktop-save-mode 1) (setq history-length 250 desktop-base-file-name (cunene/cache-concat "desktop/desktop") desktop-base-lock-name (cunene/cache-concat "desktop/desktop.lock") desktop-restore-eager 4 desktop-restore-forces-onscreen nil desktop-restore-frames t) (setq desktop-globals-to-save (append '((extended-command-history . 30) (file-name-history . 100) (grep-history . 30) (compile-history . 30) (minibuffer-history . 50) (query-replace-history . 60) (read-expression-history . 60) (regexp-history . 60) (regexp-search-ring . 20) (search-ring . 20) (kill-ring . 20) (shell-command-history . 50) register-alist))) ;; run a desktop save periodically. (run-with-timer 300 300 (lambda () (desktop-save-in-desktop-dir) (savehist-save) (message nil)) ; clear the "Desktop saved in..." message ) (defun cunene/emacs-process-p (pid) "If pid is the process ID of an emacs process, return t, else nil. Also returns nil if pid is nil." (when pid (let ((attributes (process-attributes pid)) (cmd)) (dolist (attr attributes) (if (string= "comm" (car attr)) (setq cmd (cdr attr)))) (if (and cmd (or (string= "emacs" cmd) (string= "emacs.exe" cmd))) t)))) (defadvice desktop-owner (after pry-from-cold-dead-hands activate) "Don't allow dead emacsen to own the desktop file." (when (not (cunene/emacs-process-p ad-return-value)) (setq ad-return-value nil))) (use-package windswap :demand :bind (("<f6> <down>" . windswap-down) ("<f6> <up>" . windswap-up) ("<f6> <left>" . windswap-left) ("<f6> <right>" . windswap-right)))
Window management.
shackle
gives you the means to put an end to popped up buffers not behaving they way you'd like them to. By setting up simple rules you can for instance make Emacs always select help buffers for you or make everything reuse your currently selected window.— Vasilij Schneidermann
;; Enforce rules for popups ;; (use-package shackle ;; :hook (after-init . shackle-mode) ;; :init ;; (setq shackle-default-size 0.4 ;; shackle-default-alignment 'below ;; shackle-default-rule nil ;; shackle-select-reused-windows t ;; shackle-rules ;; '((("*Help*" "*Apropos*") :select t :size 0.3 :align 'below :autoclose t) ;; (compilation-mode :select t :size 0.3 :align 'below :autoclose t) ;; (comint-mode :select t :size 0.4 :align 'below :autoclose t) ;; ("*Completions*" :size 0.3 :align 'below :autoclose t) ;; ("*Pp Eval Output*" :size 15 :align 'below :autoclose t) ;; ("*Backtrace*" :select t :size 15 :align 'below) ;; (("*Warnings*" "*Messages*") :size 0.3 :align 'below :autoclose t) ;; ("^\\*.*Shell Command.*\\*$" :regexp t :size 0.3 :align 'below :autoclose t) ;; ("\\*[Wo]*Man.*\\*" :regexp t :select t :align 'below :autoclose t) ;; ("*Calendar*" :select t :size 0.3 :align 'below) ;; (("*shell*" "*eshell*" "*ielm*") :popup t :size 0.3 :align 'below) ;; ("^\\*vc-.*\\*$" :regexp t :size 0.3 :align 'below :autoclose t) ;; ("*gud-debug*" :select t :size 0.4 :align 'below :autoclose t) ;; ("\\*ivy-occur .*\\*" :regexp t :select t :size 0.3 :align 'below) ;; (" *undo-tree*" :select t) ;; ("*quickrun*" :select t :size 15 :align 'below) ;; ("*tldr*" :size 0.4 :align 'below :autoclose t) ;; ("*Finder*" :select t :size 0.3 :align 'below :autoclose t) ;; ("^\\*macro expansion\\**" :regexp t :size 0.4 :align 'below) ;; ("^\\*elfeed-entry" :regexp t :size 0.7 :align 'below :autoclose t) ;; (" *Install vterm* " :size 0.35 :same t :align 'below) ;; (("*Paradox Report*" "*package update results*") :size 0.2 :align 'below :autoclose t) ;; ("*Package-Lint*" :size 0.4 :align 'below :autoclose t) ;; ("*How Do You*" :select t :size 0.5 :align 'below :autoclose t) ;; ((youdao-dictionary-mode osx-dictionary-mode fanyi-mode) :select t :size 0.5 :align 'below :autoclose t) ;; (("*Org Agenda*" " *Agenda Commands*" " *Org todo*" "*Org Dashboard*" "*Org Select*") ;; :select t :size 0.1 :align 'below :autoclose t) ;; (("\\*Capture\\*" "^CAPTURE-.*\\.org*") :regexp t :select t :size 0.3 :align 'below :autoclose t) ;; ("*ert*" :size 15 :align 'below :autoclose t) ;; (overseer-buffer-mode :size 15 :align 'below :autoclose t) ;; (" *Flycheck checkers*" :select t :size 0.3 :align 'below :autoclose t) ;; ((flycheck-error-list-mode flymake-diagnostics-buffer-mode) ;; :select t :size 0.25 :align 'below :autoclose t) ;; (("*lsp-help*" "*lsp session*") :size 0.3 :align 'below :autoclose t) ;; ("*DAP Templates*" :select t :size 0.4 :align 'below :autoclose t) ;; (dap-server-log-mode :size 15 :align 'below :autoclose t) ;; ("*rustfmt*" :select t :size 0.3 :align 'below :autoclose t) ;; ((rustic-compilation-mode rustic-cargo-clippy-mode rustic-cargo-outdated-mode rustic-cargo-test-mode) ;; :select t :size 0.3 :align 'below :autoclose t) ;; (profiler-report-mode :select t :size 0.5 :align 'below) ;; ("*ELP Profiling Restuls*" :select t :size 0.5 :align 'below) ;; ((inferior-python-mode inf-ruby-mode swift-repl-mode) :size 0.4 :align 'below) ;; ("*prolog*" :size 0.4 :align 'below) ;; (("*Gofmt Errors*" "*Go Test*") :select t :size 0.3 :align 'below :autoclose t) ;; (godoc-mode :select t :size 0.4 :align 'below :autoclose t) ;; ((grep-mode occur-mode rg-mode deadgrep-mode ag-mode pt-mode) :select t :size 0.4 :align 'below) ;; (Buffer-menu-mode :select t :size 0.5 :align 'below :autoclose t) ;; (gnus-article-mode :select t :size 0.7 :align 'below :autoclose t) ;; (helpful-mode :select t :size 0.3 :align 'below :autoclose t) ;; (devdocs-mode :select t :size 0.4 :align 'below :autoclose t) ;; ((process-menu-mode list-environment-mode cargo-process-mode) :select t :size 0.3 :align 'below) ;; (("*docker-containers*" "*docker-images*" "*docker-networks*" "*docker-volumes*") ;; :size 0.4 :align 'below :autoclose t) ;; (bookmark-bmenu-mode :select t :size 0.4 :align 'below) ;; (tabulated-list-mode :size 0.4 :align 'below :autclose t))) ;; :config ;; (with-no-warnings ;; (defvar shackle--popup-window-list nil ;; "All popup windows.") ;; (defvar-local shackle--current-popup-window nil ;; "Current popup window.") ;; (put 'shackle--current-popup-window 'permanent-local t) ;; (defun cunene/shackle-last-popup-buffer () ;; "View last popup buffer." ;; (interactive) ;; (ignore-errors ;; (display-buffer shackle-last-buffer))) ;; (bind-key "C-h z" #'cunene/shackle-last-popup-buffer) ;; ;; Add keyword: `autoclose' ;; (defun cunene/shackle-display-buffer-hack (fn buffer alist plist) ;; (let ((window (funcall fn buffer alist plist))) ;; (setq shackle--current-popup-window window) ;; (when (plist-get plist :autoclose) ;; (push (cons window buffer) shackle--popup-window-list)) ;; window)) ;; (advice-add #'shackle-display-buffer :around #'cunene/shackle-display-buffer-hack) ;; (defun cunene/shackle-close-popup-window-hack (&rest _) ;; "Close current popup window via `C-g'." ;; (setq shackle--popup-window-list ;; (cl-loop for (window . buffer) in shackle--popup-window-list ;; if (and (window-live-p window) ;; (equal (window-buffer window) buffer)) ;; collect (cons window buffer))) ;; ;; `C-g' can deactivate region ;; (when (and (called-interactively-p 'interactive) ;; (not (region-active-p))) ;; (if (one-window-p) ;; (let ((window (selected-window))) ;; (when (equal (buffer-local-value 'shackle--current-popup-window ;; (window-buffer window)) ;; window) ;; (winner-undo))) ;; (let* ((window (caar shackle--popup-window-list)) ;; (buffer (cdar shackle--popup-window-list)) ;; (process (get-buffer-process buffer))) ;; (when (and (window-live-p window) ;; (equal (window-buffer window) buffer)) ;; (when (process-live-p process) ;; (kill-process process)) ;; (delete-window window) ;; (pop shackle--popup-window-list)))))) ;; (advice-add #'keyboard-quit :before #'cunene/shackle-close-popup-window-hack) ;; ;; Compatible with org ;; (advice-add #'org-switch-to-buffer-other-window ;; :override #'switch-to-buffer-other-window)))
Bind shorthands to move between windows.
(use-package windmove :ensure nil :bind ( ("<f2> <left>" . windmove-left) ("<f2> <down>" . windmove-down) ("<f2> <up>" . windmove-up) ("<f2> <right>" . windmove-right))) ;; (require 'framemove) ;; (setq framemove-hook-into-windmove t)
Allow undo's and redo's with window configurations.
Winner mode is a global minor mode that records the changes in the window configuration (i.e. how the frames are partitioned into windows) so that the changes can be "undone" using the command
winner-undo
.— Ivar Rummelhoff
(use-package winner :ensure nil :hook (after-init . winner-mode))
Org
org |
Built-in |
org-present |
https://github.com/rlister/org-present |
ox-tufte |
https://github.com/dakrone/ox-tufte |
This very file is organized with org-mode
. Like Markdown, but with
superpowers.
Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.
— Carsten Dominik
(use-package org :ensure nil :bind (("C-c A" . org-agenda) ("C-c B" . org-switchb) ("C-c c" . org-capture) ("C-c l" . org-store-link)) :hook (org-mode . auto-fill-mode) :config (setq org-startup-folded t org-adapt-indentation nil org-confirm-babel-evaluate nil org-cycle-separator-lines 0 org-hide-leading-stars t org-highlight-latex-and-related '(latex) org-descriptive-links t org-edit-src-content-indentation 0 org-src-preserve-indentation nil org-edit-src-persistent-message nil org-fontify-done-headline t org-fontify-quote-and-verse-blocks t org-fontify-whole-heading-line t org-return-follows-link t org-src-tab-acts-natively t org-src-window-setup 'current-window org-startup-truncated nil org-support-shift-select 'always org-adapt-indentation nil ;; 'headline-data https://emacs.stackexchange.com/questions/69199/is-there-indentation-in-org-src-blocks org-duration-format (quote h:mm) org-fold-core-style 'overlays) ;; https://github.com/org-roam/org-roam/pull/223 (org-babel-do-load-languages 'org-babel-load-languages '( (awk . t) (calc .t) (emacs-lisp . t) (gnuplot . t) (latex . t) ; (ledger . t) (js . t) ; (http . t) (python . t) (gnuplot . t) (R . t) ; (sh . t) (sql . t) (sqlite . t) ; (mustache . t) (plantuml . t))) (require 'ob-shell) (require 'org-indent) (add-to-list 'org-babel-load-languages '(shell . t)) (modify-syntax-entry ?' "'" org-mode-syntax-table) (advice-add 'org-src--construct-edit-buffer-name :override #'cunene/org-src-buffer-name)) ;; Follow org links on the same window. ;; https://emacs.stackexchange.com/questions/62720/open-org-link-in-the-same-window (setf (cdr (assoc 'file org-link-frame-setup)) 'find-file) ;; too slow on large files. ;; (use-package org-superstar ;; :ensure t ;; :hook (org-mode . org-superstar-mode)) ;; (use-package org-sidebar ;; :ensure t) (use-package org-fancy-priorities :diminish :ensure t :hook (org-mode . org-fancy-priorities-mode) :config (setq org-fancy-priorities-list '("🅰" "🅱" "🅲" "🅳" "🅴"))) (use-package hl-todo :ensure t :bind (:map hl-todo-mode-map ("C-c o" . hl-todo-occur)) :hook ((prog-mode org-mode) . cunene/hl-todo-init) :init (defun cunene/hl-todo-init () (setq-local hl-todo-keyword-faces '(("TODO" . "#ff9977") ("DOING" . "#FF00BC") ("DONE" . "#44bc44") ("BLOCKED" . "#003366") ("FIXME" . "#FF0000") ("DEBUG" . "#A020F0") ("GOTCHA" . "#FF4500") ("STUB" . "#1E90FF") )) (hl-todo-mode))) (use-package citeproc) (use-package citeproc-org :after org) (use-package org-present :after org) (use-package org-roam :after org) (use-package org-roam-ui :after org-roam) ;; FIXME breaks flycheck ;; (add-to-list 'display-buffer-alist ;; '("\\*org-roam\\*" ;; (display-buffer-in-side-window) ;; ;; (dedicated . t) ;; (side . right) ;; (slot . 0) ;; (window-width . 0.25) ;; (preserve-size . (t nil)) ;; (window-parameters . ((no-other-window . t) ;; (no-delete-other-windows . t))))) ;; Get `org-roam-preview-visit' and friends to replace the main window. This ;;should be applicable only when `org-roam-mode' buffer is displayed in a ;;side-window. (add-hook 'org-roam-mode-hook (lambda () (setq-local display-buffer--same-window-action '(display-buffer-use-some-window (main))))) (defun cunene/occur-non-ascii () "Find any non-ascii characters in the current buffer." (interactive) (occur "[^[:ascii:]]")) ;; export glossaries and acronyms. (add-hook 'org-export-before-parsing-hook 'org-ref-acronyms-before-parsing) (add-hook 'org-export-before-parsing-hook 'org-ref-glossary-before-parsing) (setq org-latex-pdf-process '("latexmk -shell-escape -bibtex -pdf %f")) (setq org-latex-listings t) (setq bibtex-dialect 'biblatex) (add-to-list 'org-latex-packages-alist '("" "listings")) (add-to-list 'org-latex-packages-alist '("" "color")) (setq org-highlight-latex-and-related nil) ;; add classic thesis (add-to-list 'org-latex-classes '("scrreprt" "\\documentclass[11pt]{scrreprt}" ("\\part{%s}" . "\\part*{%s}") ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
(defun cunene/org-cycle-parent (argument) "Go to the nearest parent heading and execute `org-cycle'. ARGUMENT determines the visible heading." (interactive "p") (if (org-at-heading-p) (outline-up-heading argument) (org-previous-visible-heading argument)) (org-cycle)) (defun cunene/org-show-next-heading-tidily () "Show next entry, keeping other entries closed." (interactive) (if (save-excursion (end-of-line) (outline-invisible-p)) (progn (org-show-entry) (outline-show-children)) (outline-next-heading) (unless (and (bolp) (org-at-heading-p)) (org-up-heading-safe) (outline-hide-subtree) (user-error "Boundary reached")) (org-overview) (org-reveal t) (org-show-entry) (outline-show-children))) (defun cunene/org-show-previous-heading-tidily () "Show previous entry, keeping other entries closed." (interactive) (let ((pos (point))) (outline-previous-heading) (unless (and (< (point) pos) (bolp) (org-at-heading-p)) (goto-char pos) (outline-hide-subtree) (user-error "Boundary reached")) (org-overview) (org-reveal t) (org-show-entry) (outline-show-children))) (defun cunene/org-src-buffer-name (name &rest _) "Simple buffer name. !NAME is the name of the buffer." (format "*%s*" name)) (use-package org-agenda :ensure nil :bind ("C-c a" . org-agenda) :config (setq org-agenda-files (directory-files-recursively "~/Documents/org/" "\\.org$")) ;; (setq org-agenda-files '( ;; "~/Documents/org/work.org" ;; "~/Documents/org/reminder.org" ;; )) (setq org-agenda-start-with-log-mode t) (setq org-agenda-prefix-format '((agenda . " %i %-24:c%?-16t%-10e% s") (todo . " %i %-24:c %-10e") (tags . " %i %-24:c") (search . " %i %-24:c"))) ;;https://www.philnewton.net/blog/how-i-get-work-done-with-emacs/ (setq org-agenda-custom-commands '(("d" "Today's Tasks" ((agenda "" ((org-agenda-span 1) (org-agenda-overriding-header "Today's Tasks"))))))) ;; Formatting of time stamps in clock table. (setq org-time-clocksum-format (quote (:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t))) (setq org-duration-format (quote h:mm)))
Completion
Vertico
vertico |
https://github.com/minad/vertico |
Vertico provides a performant and minimalistic vertical completion UI based on the default completion system. The focus of Vertico is to provide a UI which behaves correctly under all circumstances. By reusing the built-in facilities system, Vertico achieves full compatibility with built-in Emacs completion commands and completion tables. Vertico only provides the completion UI but aims to be highly flexible, extendable and modular.
(use-package vertico :init (vertico-mode) :config (setq vertico-resize t) ;; Grow and shrink the Vertico minibuffer (setq vertico-cycle t)) ;; enable cycling for `vertico-next' and `vertico-previous'. ;; from vendor directory. (use-package vertico-quick :load-path cunene/vendor-packages :bind (:map vertico-map ("M-q" . vertico-quick-insert) ("C-q" . vertico-quick-exit)))
Orderless
orderless |
https://github.com/oantolin/orderless |
This package provides an orderless completion style that divides the pattern into space-separated components, and matches candidates that match all of the components in any order. Each component can match in any one of several ways: literally, as a regexp, as an initialism, in the flex style, or as multiple word prefixes. By default, regexp and literal matches are enabled.
;; Use the `orderless' completion style. Additionally enable ;; `partial-completion' for file path expansion. `partial-completion' is ;; important for wildcard support. Multiple files can be opened at once ;; with `find-file' if you enter a wildcard. You may also give the ;; `initials' completion style a try. (use-package orderless :config (setq completion-styles '(orderless) completion-category-defaults nil completion-category-overrides '((file (styles partial-completion))))) ;; A few more useful configurations... (use-package emacs :init ;; Add prompt indicator to `completing-read-multiple'. ;; Alternatively try `consult-completing-read-multiple'. (defun cunene/crm-indicator (args) (cons (concat "[CRM] " (car args)) (cdr args))) (advice-add #'completing-read-multiple :filter-args #'cunene/crm-indicator) ;; Do not allow the cursor in the minibuffer prompt (setq minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) ;; Emacs 28: Hide commands in M-x which do not work in the current mode. ;; Vertico commands are hidden in normal buffers. (setq read-extended-command-predicate #'command-completion-default-include-p) ;; Enable recursive minibuffers (setq enable-recursive-minibuffers t)) ;; Use `consult-completion-in-region' if Vertico is enabled. ;; Otherwise use the default `completion--in-region' function. (setq completion-in-region-function (lambda (&rest args) (apply (if vertico-mode #'consult-completion-in-region #'completion--in-region) args)))
Marginalia
marginalia |
https://github.com/minad/marginalia |
This package provides marginalia-mode which adds marginalia to the minibuffer completions. Marginalia are marks or annotations placed at the margin of the page of a book or in this case helpful colorful annotations placed at the margin of the minibuffer for your completion candidates. Marginalia can only add annotations to the completion candidates. It cannot modify the appearance of the candidates themselves, which are shown unaltered as supplied by the original command.
;; Enable richer annotations using the Marginalia package (use-package marginalia ;; Either bind `marginalia-cycle` globally or only in the minibuffer :bind (("M-A" . marginalia-cycle) :map minibuffer-local-map ("M-A" . marginalia-cycle)) ;; The :init configuration is always executed (Not lazy!) :init ;; Must be in the :init section of use-package such that the mode gets ;; enabled right away. Note that this forces loading the package. (marginalia-mode)) (use-package all-the-icons-completion :after (marginalia all-the-icons) :hook (marginalia-mode . all-the-icons-completion-marginalia-setup) :init (all-the-icons-completion-mode)) (use-package completing-read-xref :load-path cunene/vendor-packages :commands (completing-read-xref-show-xrefs completing-read-xref-show-xrefs) :init (setq xref-show-definitions-function 'completing-read-xref-show-defs))
Corfu
Corfu | https://github.com/minad/corfu |
Corfu enhances in-buffer completion with a small completion popup. The current candidates are shown in a popup below or above the point. The candidates can be selected by moving up and down. Corfu is the minimalistic in-buffer completion counterpart of the Vertico minibuffer UI.
(use-package corfu :ensure t ;; Optional customizations :config (setq corfu-quit-no-match 'separator) corfu-echo-mode :custom (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' (corfu-auto t) ;; Enable auto completion (corfu-separator ?\s) ;; Orderless field separator (corfu-quit-at-boundary nil) ;; Never quit at completion boundary (corfu-quit-no-match nil) ;; Never quit, even if there is no match (corfu-preview-current nil) ;; Disable current candidate preview (corfu-preselect 'prompt) ;; Preselect the prompt (corfu-on-exact-match nil) ;; Configure handling of exact matches (corfu-scroll-margin 5) ;; Use scroll margin ;; Enable Corfu only for certain modes. :hook ((prog-mode . corfu-mode) (shell-mode . corfu-mode) (eshell-mode . corfu-mode)) ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can ;; be used globally (M-/). See also the customization variable ;; `global-corfu-modes' to exclude certain modes. :init (global-corfu-mode) (setq corfu-popupinfo-delay 0.2) (corfu-popupinfo-mode)) (use-package nerd-icons-corfu :ensure t :config (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) ;; Optionally: (setq nerd-icons-corfu-mapping '((array :style "cod" :icon "symbol_array" :face font-lock-type-face) (boolean :style "cod" :icon "symbol_boolean" :face font-lock-builtin-face) ;; ... (t :style "cod" :icon "code" :face font-lock-warning-face)))) (use-package pcmpl-args :ensure t) (add-hook 'eshell-mode-hook (lambda () (setq-local corfu-auto nil) (corfu-mode))) ;; (defun corfu-send-shell (&rest _) ;; "Send completion candidate when inside comint/eshell." ;; (cond ;; ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) ;; (eshell-send-input)) ;; ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) ;; (comint-send-input)))) ;; (advice-add #'corfu-insert :after #'corfu-send-shell) ;; A few more useful configurations... (use-package emacs :init ;; TAB cycle if there are only few candidates (setq completion-cycle-threshold 3) ;; Emacs 28: Hide commands in M-x which do not apply to the current mode. ;; Corfu commands are hidden, since they are not supposed to be used via M-x. (setq read-extended-command-predicate #'command-completion-default-include-p) ;; Enable indentation+completion using the TAB key. ;; `completion-at-point' is often bound to M-TAB. (setq tab-always-indent 'complete))
Cape
Cape | https://github.com/minad/cape |
Cape provides Completion At Point Extensions which can be used in combination with Corfu, Company or the default completion UI. The completion backends used by completion-at-point are so called completion-at-point-functions (Capfs).
;; Add extensions (use-package cape :ensure t ;; Bind dedicated completion commands ;; Alternative prefix keys: C-c p, M-p, M-+, ... :bind (("C-c p p" . completion-at-point) ;; capf ("C-c p t" . complete-tag) ;; etags ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion ("C-c p h" . cape-history) ("C-c p f" . cape-file) ("C-c p k" . cape-keyword) ("C-c p s" . cape-elisp-symbol) ("C-c p e" . cape-elisp-block) ("C-c p a" . cape-abbrev) ("C-c p l" . cape-line) ("C-c p w" . cape-dict) ("C-c p :" . cape-emoji) ("C-c p \\" . cape-tex) ("C-c p _" . cape-tex) ("C-c p ^" . cape-tex) ("C-c p &" . cape-sgml) ("C-c p r" . cape-rfc1345)) :init ;; Add to the global default value of `completion-at-point-functions' which is ;; used by `completion-at-point'. The order of the functions matters, the ;; first function returning a result wins. Note that the list of buffer-local ;; completion functions takes precedence over the global list. (add-to-list 'completion-at-point-functions #'cape-dabbrev) (add-to-list 'completion-at-point-functions #'cape-file) (add-to-list 'completion-at-point-functions #'cape-elisp-block) (add-to-list 'completion-at-point-functions #'cape-history) (add-to-list 'completion-at-point-functions #'cape-keyword) ;;(add-to-list 'completion-at-point-functions #'cape-tex) ;;(add-to-list 'completion-at-point-functions #'cape-sgml) ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345) ;;(add-to-list 'completion-at-point-functions #'cape-abbrev) (add-to-list 'completion-at-point-functions #'cape-dict) (add-to-list 'completion-at-point-functions #'cape-elisp-symbol) ;;(add-to-list 'completion-at-point-functions #'cape-line) )
Consult
consult |
https://github.com/minad/consult |
consult-flycheck |
https://github.com/minad/consult-flycheck |
consult-dir |
https://github.com/karthink/consult-dir |
consult-yasnippet |
https://github.com/mohkale/consult-yasnippet |
consult-flyspell |
https://gitlab.com/OlMon/consult-flyspell |
flyspell-correct |
https://github.com/d12frosted/flyspell-correct |
Consult provides search and navigation commands based on the Emacs completion function completing-read. Completion allows you to quickly select an item from a list of candidates. Consult offers asynchronous and interactive consult-grep and consult-ripgrep commands, and the line-based search command consult-line. Furthermore Consult provides an advanced buffer switching command consult-buffer to switch between buffers, recently opened files, bookmarks and buffer-like candidates from other sources. Some of the Consult commands are enhanced versions of built-in Emacs commands.
(use-package consult :bind (("C-x r x" . consult-register) ("C-x r b" . consult-bookmark) ("C-c k" . consult-kmacro) ("C-x M-:" . consult-complex-command) ;; orig. repeat-complet-command ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window ("C-x 5 b" . consult-buffer-other-frame) ("M-#" . consult-register-load) ("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated) ("C-M-#" . consult-register) ("M-g o" . consult-outline) ("M-g h" . consult-org-heading) ("M-g a" . consult-org-agenda) ("M-g m" . consult-mark) ("C-x b" . consult-buffer) ("M-g g" . consult-goto-line) ;; orig. goto-line ("M-g o" . consult-outline) ("M-g m" . consult-mark) ("M-g k" . consult-global-mark) ("M-g i" . consult-imenu) ("M-g I" . consult-project-imenu) ("M-g e" . consult-error) ;; M-s bindings (search-map) ("M-s f" . consult-find) ("M-s L" . consult-locate) ("M-s g" . consult-grep) ("M-s G" . consult-git-grep) ("M-s r" . consult-ripgrep) ("M-s l" . consult-line) ("M-s m" . consult-multi-occur) ("M-s k" . consult-keep-lines) ("M-s u" . consult-focus-lines) ;; Isearch integration ("M-g l" . consult-line) ("M-s m" . consult-multi-occur) ("C-x c o" . consult-multi-occur) ("C-x c SPC" . consult-mark) :map isearch-mode-map ("M-e" . consult-isearch) ;; orig. isearch-edit-string ("M-s e" . consult-isearch) ;; orig. isearch-edit-string ("M-s l" . consult-line)) :init (setq register-preview-delay 0 register-preview-function #'consult-register-format) :config (setq consult-project-root-function #'projectile-project-root consult-narrow-key "<")) (setq xref-show-xrefs-function #'consult-xref xref-show-definitions-function #'consult-xref) (use-package consult-flycheck :after flycheck) ;; Consult directory navigation (use-package consult-dir :bind (("C-x C-d" . consult-dir) :map vertico-map ("C-x C-d" . consult-dir) ("C-x C-j" . consult-dir-jump-file))) (use-package consult-yasnippet) (use-package flyspell-correct :after flyspell :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper))) (use-package consult-flyspell :config ;; default settings (setq consult-flyspell-select-function nil consult-flyspell-set-point-after-word t consult-flyspell-always-check-buffer nil)) (setq consult-flyspell-select-function 'flyspell-correct-at-point)
Embark
embark |
https://github.com/oantolin/embark |
Embark makes it easy to choose a command to run based on what is near point, both during a minibuffer completion session (in a way familiar to Helm or Counsel users) and in normal buffers. Bind the command embark-act to a key and it acts like prefix-key for a keymap of actions (commands) relevant to the target around point. With point on an URL in a buffer you can open the URL in a browser or eww or download the file it points to. If while switching buffers you spot an old one, you can kill it right there and continue to select another. Embark comes preconfigured with over a hundred actions for common types of targets such as files, buffers, identifiers, s-expressions, sentences; and it is easy to add more actions and more target types. Embark can also collect all the candidates in a minibuffer to an occur-like buffer or export them to a buffer in a major-mode specific to the type of candidates, such as dired for a set of files, ibuffer for a set of buffers, or customize for a set of variables.
(use-package embark :ensure t :bind (("C-." . embark-act) ;; pick some comfortable binding ("M-." . embark-dwim) ;; good alternative: M-. ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings' :init ;; Optionally replace the key help with a completing-read interface (setq prefix-help-command #'embark-prefix-help-command) ;; Show the Embark target at point via Eldoc. You may adjust the ;; Eldoc strategy, if you want to see the documentation from ;; multiple providers. Beware that using this can be a little ;; jarring since the message shown in the minibuffer can be more ;; than one line, causing the modeline to move up and down: ;; (add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target) ;; (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly) :config ;; Hide the mode line of the Embark live/completions buffers (add-to-list 'display-buffer-alist '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil (window-parameters (mode-line-format . none))))) ;; Consult users will also want the embark-consult package. (use-package embark-consult :ensure t ; only need to install it, embark loads it after consult if found :hook (embark-collect-mode . consult-preview-at-point-mode))
Undo
undo-tree |
https://gitlab.com/tsc25/undo-tree |
(defvar cunene/undo-tree-directory (cunene/cache-concat "undo") "Location of the undo-tree save files.") (use-package undo-tree :diminish undo-tree-mode :config (setq undo-tree-visualizer-diff nil ;; causes problems with other buffers undo-tree-visualizer-timestamps nil undo-tree-enable-undo-in-region t undo-tree-visualizer-relative-timestamps nil undo-tree-history-directory-alist `((".*" . ,cunene/undo-tree-directory)) undo-tree-auto-save-history t) ;; autosave the undo-tree history (global-undo-tree-mode 1)) (add-to-list 'display-buffer-alist '("*undo-tree" (display-buffer-reuse-window display-buffer-in-side-window) (side . right) (window-width . 0.15) (reusable-frames . nil)))
Bookmarks
bookmark+ | https://www.emacswiki.org/emacs/BookmarkPlus |
(use-package bookmark+ :load-path cunene/vendor-packages :config (setq bookmark-default-file (concat user-emacs-directory "bookmarks") bookmark-save-flag 1))
bm | https://github.com/joodland/bm |
This package provides visible, buffer local, bookmarks and the ability to jump forward and backward to the next bookmark.
It was created because I missed the bookmarks from M$ Visual Studio in GNU Emacs. I think they provide an easy way to navigate in a buffer.
For the org-mode support, see:
(use-package bm :demand t :init ;; restore on load (even before you require bm) (setq bm-restore-repository-on-load t) :config ;; Allow cross-buffer 'next' (setq bm-cycle-all-buffers t) ;; where to store persistant files (setq bm-repository-file (cunene/cache-concat "bm/bm-repository")) ;; show bookmark in fringe only. (setq bm-highlight-style 'bm-highlight-only-fringe) ;; save bookmarks (setq-default bm-buffer-persistence t) ;; Loading the repository from file when on start up. (add-hook 'after-init-hook 'bm-repository-load) ;; Saving bookmarks (add-hook 'kill-buffer-hook #'bm-buffer-save) ;; Saving the repository to file when on exit. ;; kill-buffer-hook is not called when Emacs is killed, so we ;; must save all bookmarks first. (add-hook 'kill-emacs-hook #'(lambda nil (bm-buffer-save-all) (bm-repository-save))) ;; The `after-save-hook' is not necessary to use to achieve persistence, ;; but it makes the bookmark data in repository more in sync with the file ;; state. (add-hook 'after-save-hook #'bm-buffer-save) ;; Restoring bookmarks (add-hook 'find-file-hooks #'bm-buffer-restore) (add-hook 'after-revert-hook #'bm-buffer-restore) ;; The `after-revert-hook' is not necessary to use to achieve persistence, ;; but it makes the bookmark data in repository more in sync with the file ;; state. This hook might cause trouble when using packages ;; that automatically reverts the buffer (like vc after a check-in). ;; This can easily be avoided if the package provides a hook that is ;; called before the buffer is reverted (like `vc-before-checkin-hook'). ;; Then new bookmarks can be saved before the buffer is reverted. ;; Make sure bookmarks is saved before check-in (and revert-buffer) (add-hook 'vc-before-checkin-hook #'bm-buffer-save) :bind (("<f9>" . bm-toggle) ("S-<f9>" . bm-previous) ("C-<f9>" . bm-next))) (defvar cunene/bm-after-goto-hook nil "Hook run after jumping to a bookmark in `bm-goto'.") (add-hook 'cunene/bm-after-goto-hook 'org-bookmark-jump-unhide) (defun cunene/bm-goto (bookmark) "Goto specified BOOKMARK." (if (bm-bookmarkp bookmark) (progn (if bm-goto-position (goto-char (max ;; sometimes marker-position is before start of overlay ;; marker is not updated when overlay hooks are called. (overlay-start bookmark) (marker-position (overlay-get bookmark 'position)))) (goto-char (overlay-start bookmark))) (run-hooks 'cunene/bm-after-goto-hook) (setq bm-wrapped nil) ; turn off wrapped state (if bm-recenter (recenter)) (let ((annotation (overlay-get bookmark 'annotation))) (if annotation (message annotation))) (when (overlay-get bookmark 'temporary-bookmark) (bm-bookmark-remove bookmark))) (when (> bm-verbosity-level 0) (message "Bookmark not found."))))
Highlighting
beacon |
https://github.com/Malabarba/beacon |
hi-lock |
https://www.masteringemacs.org/article/highlighting-by-word-line-regexp |
dimmer |
https://github.com/gonewest818/dimmer.el |
;; Highlight current line. (add-hook 'ibuffer-mode-hook #'hl-line-mode) (add-hook 'bongo-mode-hook #'hl-line-mode) (add-hook 'occur-mode-hook #'hl-line-mode) (add-hook 'svn-status-mode-hook #'hl-line-mode) (add-hook 'dired-mode-hook #'hl-line-mode) (add-hook 'grep-setup-hook #'hl-line-mode) (add-hook 'compilation-mode-hook #'hl-line-mode) (add-hook 'magit-mode-hook #'hl-line-mode) (add-hook 'vc-git-log-view-mode-hook #'hl-line-mode) (add-hook 'logview-mode-hook #'hl-line-mode) (add-hook 'find-dired-mode-hook #'hl-line-mode) (add-hook 'gnus-summary-mode-hook #'hl-line-mode) (add-hook 'org-agenda-finalize-hook #'hl-line-mode) (add-hook 'org-agenda-finalize-hook #'hl-line-mode) ;; Turn on local highlighting for list-buffers (defadvice list-buffers (after highlight-line activate) (save-excursion (set-buffer "*Buffer List*") (hl-line-mode))) (use-package beacon :init (beacon-mode 1)) (require 'hi-lock) (defun cunene/unhighlight-symbol-at-point () "Remove highlight of symbol at point." (interactive) (unhighlight-regexp (concat "\\_<" (thing-at-point 'symbol) "\\_>"))) ;; Key bindings (global-set-key (kbd "S-<f12>") 'cunene/unhighlight-symbol-at-point) (global-set-key (kbd "<f12>") 'highlight-symbol-at-point) (global-set-key (kbd "C-<f12>") 'highlight-symbol-next) (global-set-key (kbd "M-<f12>") 'highlight-symbol-prev) (use-package dimmer :custom (dimmer-fraction 0.3) :config (dimmer-mode))
Search
engine-mode |
https://github.com/hrs/engine-mode |
anzu |
https://github.com/emacsorphanage/anzu |
engine-mode is a global minor mode for Emacs. It enables you to easily define search engines, bind them to keybindings, and query them from the comfort of your editor.
(use-package engine-mode :config (engine-mode t) (defengine duckduckgo "https://duckduckgo.com/?q=%s" :keybinding "d") (defengine google "http://www.google.com/search?ie=utf-8&oe=utf-8&q=%s" :keybinding "g")) (use-package google-this :config (google-this-mode 1)) (setq isearch-allow-scroll t isearch-wrap-pause 'no-ding) (defadvice isearch-update (before my-isearch-reposite activate) (sit-for 0) (recenter 1)) ;; anzu-mode enhances isearch & query-replace by showing total matches and ;; current match position (use-package anzu :diminish anzu-mode :config (global-anzu-mode) :bind (("M-%" . anzu-query-replace) ("C-M-%" . anzu-query-replace-regexp)))
Fonts
(use-package font-lock-ext :load-path cunene/vendor-packages)
Snippets
(setq-default abbrev-mode 1) (use-package yasnippet :hook (after-init . yas-global-mode) :diminish yas :bind (:map yas-minor-mode-map ("C-c & t" . yas-describe-tables) ("C-c & &" . org-mark-ring-goto))) (use-package yasnippet-snippets :init (yasnippet-snippets-initialize)) ;; useful with YAS. See: ;; https://emacs.stackexchange.com/questions/45629/template-for-new-file (use-package autoinsert :config (setq auto-insert-query nil) (auto-insert-mode 1) (add-hook 'find-file-hook 'auto-insert) ;; (setq auto-insert-alist nil) ;; remove this like to restore defaults ;; (add-to-list 'auto-insert-alist '("CMakeLists\\.txt$" . [nega/yas-cmake-bp])) )
Spell checking
(add-hook 'text-mode-hook 'flyspell-mode) (add-hook 'prog-mode-hook 'flyspell-prog-mode)
Thesaurus
(use-package define-word :config (setq define-word-default-service 'wordnik) (defun url-http-user-agent-string () "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36 ")) (defun cunene/define-word (&rest args) "Create a buffer for display word instead of using messages." (interactive) (let ((buffer (get-buffer-create "Define Word"))) (set-buffer buffer) (erase-buffer) (set-buffer-major-mode buffer) (apply 'insert args) (display-buffer buffer))) (setq define-word-displayfn-alist (cl-loop for (service . _) in define-word-services collect (cons service #'cunene/define-word)))
Logs
logview | https://github.com/doublep/logview |
(use-package logview :config (setq logview-cache-filename (cunene/cache-concat "logview/logview-cache.extmap") logview-additional-submodes '( ("dogen" (format . "TIMESTAMP [LEVEL] [NAME]") (levels . "SLF4J") (timestamp "ISO 8601 datetime + micros")) ("dotnet" (format . "LEVEL TIMESTAMP [THREAD] NAME IGNORED - MESSAGE") (levels . "SLF4J")))) (add-hook 'logview-mode-hook #'read-only-mode))
Workspaces
eyebrowse | https://depp.brause.cc/eyebrowse |
(use-package eyebrowse :config (setq eyebrowse-new-workspace t) ;; also save side and slot windows configuration. (add-to-list 'window-persistent-parameters '(window-side . writable)) (add-to-list 'window-persistent-parameters '(window-slot . writable)) (eyebrowse-mode t)) ;; example: (cunene/eyebrowse-create-config "proj: code") (defun cunene/eyebrowse-create-config (name) (eyebrowse-create-window-config) (eyebrowse-rename-window-config (eyebrowse--get 'current-slot) name) )
Switching
ace-window | https://github.com/abo-abo/ace-window |
(use-package ace-window :config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)) (custom-set-faces '(aw-leading-char-face ((t (:inherit ace-jump-face-foreground :height 5.0))))) :bind ("M-o" . ace-window)) ;; Window switching. (C-x o goes to the next window) (global-set-key (kbd "C-x O") (lambda () (interactive) (other-window -1))) ;; back one
Diffing
ztree |
https://github.com/fourier/ztree |
diff-at-point |
https://gitlab.com/ideasman42/emacs-diff-at-point |
ztree-diff
ztree-diff is a directory-diff tool for Emacs inspired by commercial tools like Beyond Compare or Araxis Merge. It supports showing the difference between two directories; calling Ediff for not matching files, copying between directories, deleting file/directories, hiding/showing equal files/directories.
(use-package ztree :ensure t) (use-package diff-at-point :ensure t) (add-hook 'diff-mode-hook (lambda () (define-key diff-mode-shared-map (kbd "<C-M-return>") 'diff-at-point-goto-source-and-close))) (add-hook 'prog-mode-hook (lambda () (define-key prog-mode-map (kbd "<C-M-return>") 'diff-at-point-open-and-goto-hunk))) ;; ediff (setq ediff-window-setup-function 'ediff-setup-windows-plain ediff-split-window-function 'split-window-horizontally ediff-diff-options "-w") (defvar cunene/ediff-do-hexl-diff nil "variable used to store trigger for doing diff in hexl-mode") (defadvice ediff-files-internal (around ediff-files-internal-for-binary-files activate) "catch the condition when the binary files differ the reason for catching the error out here (when re-thrown from the inner advice) is to let the stack continue to unwind before we start the new diff otherwise some code in the middle of the stack expects some output that isn't there and triggers an error" (let ((file-A (ad-get-arg 0)) (file-B (ad-get-arg 1)) cunene/ediff-do-hexl-diff) (condition-case err (progn ad-do-it) (error (if cunene/ediff-do-hexl-diff (let ((buf-A (find-file-noselect file-A)) (buf-B (find-file-noselect file-B))) (with-current-buffer buf-A (hexl-mode 1)) (with-current-buffer buf-B (hexl-mode 1)) (ediff-buffers buf-A buf-B)) (error (error-message-string err))))))) (defadvice ediff-setup-diff-regions (around ediff-setup-diff-regions-for-binary-files activate) "when binary files differ, set the variable " (condition-case err (progn ad-do-it) (error (setq cunene/ediff-do-hexl-diff (and (string-match-p "^Errors in diff output. Diff output is in.*" (error-message-string err)) (string-match-p "^\\(Binary \\)?[fF]iles .* and .* differ" (buffer-substring-no-properties (line-beginning-position) (line-end-position))))) (error (error-message-string err)))))
IRC
(setq erc-join-buffer 'bury) (add-hook 'erc-mode-hook (lambda () (erc-fill-mode nil)))
Mastodon
(use-package mastodon :config (setq mastodon-active-user "MarcoCraveiro") (setq mastodon-instance-url "https://emacs.ch"))
Postamble
;;; features.el ends here