Add Melpa
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(require 'use-package)
(setq use-package-always-ensure t)
(use-package use-package-ensure-system-package
:ensure nil)
Utility packages that add functions that make configuration easier or configure some aspect of Emacs so that I don’t have to.
I like to know how fast Emacs has started.
(add-hook 'emacs-startup-hook
#'(lambda ()
(message "Emacs ready in %s with %d garbage collections."
(emacs-init-time)
gcs-done)))
For keeping mode line clean.
(use-package blackout)
Helper functions for configuring keybindings, hooks and many more.
There is general-def
that’s is used for keybinding,
general-setq
that is used for setting “customize” variables,
general-add-hook
, general-remove-hook
for adding or removing hooks in bulk (can add to more that one hook at a time and more than one function at the time),
general-advice-add
, general-advice-remove
for adding and removing advice… There are some others but I don’t use them.
There is also use-package
integration for all of these functions and they are:
:general for general-def
:ghook and :gfhook for general-add-hook
(use-package general)
What the title says.
(use-package gcmh
:config
(gcmh-mode 1)
(setq gcmh-idle-delay 5)
(blackout 'gcmh-mode))
Helping me so that I don’t have to configure Emacs not to clutter .emacs.d.
(use-package no-littering
:demand t
:config
(setq auto-save-file-name-transforms
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
(setq custom-file (no-littering-expand-etc-file-name "custom.el"))
;; here because it needs to be after no-littering
;; should be moved somewhere else
(when (file-exists-p custom-file)
(load-file custom-file))
(no-littering-theme-backups)
(with-eval-after-load 'recentf
(add-to-list 'recentf-exclude no-littering-var-directory)
(add-to-list 'recentf-exclude no-littering-etc-directory)))
Help with discovery of keybindings.
(use-package which-key
:config
(setq which-key-idle-delay 0.5)
(which-key-mode 1)
(with-eval-after-load 'which-key
(blackout 'which-key-mode)))
Small snippets in help buffer that show how a function is used.
(use-package elisp-demos
:config
(advice-add 'describe-function-1 :after #'elisp-demos-advice-describe-function-1))
;; (with-eval-after-load 'helpful
;; (advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update))
Ansi collor in buffers. Run command to add ansi collors to buffer.
(defun kr-display-ansi-colors ()
(interactive)
(let ((inhibit-read-only t))
(ansi-color-apply-on-region (point-min) (point-max))))
(defun ansi-color-after-scroll (window start)
"Used by ansi-color-mode minor mode"
(ansi-color-apply-on-region start (window-end window t) t))
(define-minor-mode ansi-color-mode
"A very primitive minor mode to view log files containing ANSI color codes.
Pros: this minor mode runs `ansi-color-apply-on-region' lazily,
i.e. only the visible part of the buffer. Hence, it does NOT
freeze Emacs even if the log file is huge.
Cons: a) when the minor code is toggled off, it does not undo
what has already been ansi colorized. b) assumes the buffer
content etc. does not change. c) jumping to random places within
the buffer may incur incorrect/incomplete colorization.
How to install: put this code into your init.el, then evaluate it or
restart Emacs for the code to take effect.
How to use: in the log buffer of need run `M-x ansi-color-mode'.
Alternatively, feel free to enable this minor mode via mode hooks
so that you needn't enable it manually.
-- lgfang
"
:global nil
:lighter ""
(if ansi-color-mode
(progn
(ansi-color-apply-on-region (window-start) (window-end) t)
(add-hook 'window-scroll-functions 'ansi-color-after-scroll 80 t))
(remove-hook 'window-scroll-functions 'ansi-color-after-scroll t)))
(defun kr-unix-ts-to-str (&optional time zone)
"Convert unix timestamp integer to human-readable string in RFC3339 format."
(interactive "nTimestamp: ")
(setq zone (or zone "UTC"))
(setq ts-str (format "%s" (or time (current-word))))
(if (numberp (read ts-str))
(progn
(setq ts-int (string-to-number ts-str))
;; send message to Message buffer
;; copy to kill-ring (clipboard)
(setq rfc_str (format-time-string "%Y-%m-%dT%H:%M:%S%z" ts-int zone))
(message (format "%d %s ==> %s" ts-int zone rfc_str))
(kill-new rfc_str))
(message "not a number")))
(defun kr-unix-ts-to-str-dwim ()
(interactive)
(if mark-active
(let ((ts (buffer-substring-no-properties (region-beginning) (region-end))))
(kr-unix-ts-to-str ts))
(call-interactively #'kr-unix-ts-to-str)))
(with-eval-after-load 'meow
(meow-define-keys 'normal
'("gu". kr-unix-ts-to-str-dwim)))
(defun kr-toggle-final-newline ()
(interactive)
(setq require-final-newline (not require-final-newline))
(message "set require-final-newline to %s" require-final-newline))
(general-def mode-specific-map
"fN" 'kr-toggle-final-newline)
Setup keybindings for builtin features that are not tied to any mode.
Change builtin emacs keybingings that I can’t put in any category
(general-def
"C-h l" 'find-library)
(general-def
"M-;" 'comment-line
"C-x C-;" 'comment-dwim)
(general-def 'global
"C-<backspace>" 'cycle-spacing)
Help at point key is C-z h
. Every mode that implements a help at point needs to change it to point to it’s “help-at-point” function
(define-key global-map (kbd "C-z") nil)
(general-def
"C-z h" 'describe-symbol)
(defun kr-go-to-scratch ()
(interactive)
(switch-to-buffer "*scratch*"))
(use-package scratch
:config
(general-def mode-specific-map
"b S" 'scratch
"b s" 'scratch-buffer
"b r" 'revert-buffer))
This is manly for magit but can be used for some other funcitonality.
(general-def transient-base-map
"<escape>" 'transient-quit-one)
Binding for emacs builtin command. Binding it to mode-specific-map
(C-c
) so that with the help of meow we can call it with SPC
. For example call switch-to-buffer
with SPC b b
.
(general-def mode-specific-map
"b b" 'switch-to-buffer
"b d" 'kill-current-buffer
"b r" 'revert-buffer
"b D" 'kill-buffer
"w w" 'other-window
"w W" 'window-swap-states
"w v" 'split-window-right
"w h" 'split-window-below
"w D" 'delete-other-windows
"w d" 'delete-window
"f s" 'save-buffer
"f S" 'save-some-buffers
"f d" 'list-directory
"f f" 'find-file
"f j" 'dired-jump)
Here is configuration that concerns Emacs builtin features. Changing options, enabling and configuring modes etc. Big packages like org-mode will get their own section.
Inspired by https://github.com/natecox/dotfiles/blob/master/emacs/emacs.d/nathancox.org
To debug a LISP function use debug-on-entry
. You step in with d
and over with e
(setq confirm-kill-emacs 'y-or-n-p)
(setq use-file-dialog nil)
(setq initial-scratch-message nil
sentence-end-double-space nil
ring-bell-function 'ignore
frame-resize-pixelwise t)
;; (setq user-full-name "Luca Cambiaghi"
;; user-mail-address "[email protected]")
;; always allow 'y' instead of 'yes'.
(defalias 'yes-or-no-p 'y-or-n-p)
;; default to utf-8 for all the things
(set-language-environment "UTF-8")
;; don't show any extra window chrome
(when (window-system)
(tool-bar-mode -1)
(toggle-scroll-bar -1))
;; less noise when compiling elisp
;; (setq byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local))
;; (setq native-comp-async-report-warnings-errors nil)
;; use common convention for indentation by default
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
;; Delete files to trash
(setq delete-by-moving-to-trash t)
;; Uniquify buffer names
(setq-default uniquify-buffer-name-style 'forward)
;; Better scrolling behaviour
(setq-default
hscroll-step 1
scroll-margin 4
hscroll-margin 4
mouse-yank-at-point t
auto-window-vscroll nil
mouse-wheel-scroll-amount '(1)
mouse-wheel-tilt-scroll t
scroll-conservatively most-positive-fixnum)
;; Better interaction with clipboard
(setq-default save-interprogram-paste-before-kill t)
;; Some usefull builtin minor modes
(column-number-mode 1)
(global-auto-revert-mode 1)
;; Maybe gives some optimization
(add-hook 'focus-out-hook #'garbage-collect)
(tooltip-mode -1)
;; delete whitespace
(add-hook 'before-save-hook #'whitespace-cleanup)
(setq view-read-only t)
(add-hook 'help-mode-hook 'visual-line-mode)
(setq help-window-select t)
(setq help-window-keep-selected t)
(setq help-enable-variable-value-editing t)
(put 'help-fns-edit-variable 'disabled nil)
(defun kr-describe-at-point (symbol)
"Call `describe-symbol' for the SYMBOL at point."
(interactive (list (symbol-at-point)))
(if (and symbol (or (fboundp symbol)
(boundp symbol)
(facep symbol)))
(describe-symbol symbol)
(call-interactively #'describe-symbol)))
(general-def
"C-z h" 'kr-describe-at-point
"C-h s" 'shortdoc-display-group
"C-h b" 'describe-keymap
"C-h B" 'describe-bindings)
(global-subword-mode 1)
(blackout 'subword-mode)
(blackout 'visual-line-mode)
(use-package eldoc
:config
(setq eldoc-echo-area-display-truncation-message t)
(setq eldoc-echo-area-use-multiline-p nil)
(setq eldoc-echo-area-prefer-doc-buffer nil))
(use-package eldoc-box
:general (eglot-mode-map
"C-h ." 'eldoc-box-help-at-point))
(recentf-mode 1)
(setq recentf-max-saved-items 75)
(setq recentf-exclude `(,(expand-file-name "straight/build/" user-emacs-directory)
,(expand-file-name "eln-cache/" user-emacs-directory)))
;; ,(expand-file-name "etc/" user-emacs-directory)
;; ,(expand-file-name "var/" user-emacs-directory)
(save-place-mode 1)
(set-register ?c `(file . ,(expand-file-name kr/config-org user-emacs-directory)))
(set-register ?i `(file . ,(expand-file-name "init.el" user-emacs-directory)))
I making a custom input method for Serbian language because all the other methods that exist are stupid. Reference how to make custom input method.
(quail-define-package
"custom-latin" "Custom" "CS" nil
"Custom keyboard layout."
nil t nil nil nil nil nil nil nil nil t)
(quail-define-rules
("x" ?š)
("X" ?Š)
("w" ?č)
("W" ?Č)
("q" ?ć)
("Q" ?Ć)
("y" ?ž)
("Y" ?Ž)
("dj" ?đ)
("Dj" ?Đ)
("DJ" ?Đ))
(setq default-input-method "custom-latin")
(add-hook 'emacs-startup-hook
#'(lambda ()
(setq ispell-program-name (executable-find "aspell"))))
(setq calendar-date-style 'european)
(setq calendar-week-start-day 1)
(require 'ediff)
;; (winner-mode 1)
(add-hook 'ediff-after-quit-hook-internal 'winner-undo)
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
(setq ediff-split-window-function 'split-window-horizontally)
(defvar my-ediff-last-windows nil)
(defun my-store-pre-ediff-winconfig ()
(setq my-ediff-last-windows (current-window-configuration)))
(defun my-restore-pre-ediff-winconfig ()
(set-window-configuration my-ediff-last-windows))
(add-hook 'ediff-before-setup-hook #'my-store-pre-ediff-winconfig)
(add-hook 'ediff-quit-hook #'my-restore-pre-ediff-winconfig)
(setq isearch-lazy-count t)
(add-hook 'lisp-mode-hook #'auto-insert-mode)
;; add color codes to compilation mode
(add-hook 'compilation-filter-hook 'ansi-color-compilation-filter)
(repeat-mode 1)
General MacOs specific configuration
Check if we run on Mac
(defvar kr-mac-p (if (string= system-type "darwin") t nil))
Setup PATH and other env varables.
(use-package exec-path-from-shell
:config
(require 'exec-path-from-shell)
(setq exec-path-from-shell-arguments '("-l"))
(when (memq window-system '(mac ns))
(dolist (var '("NPM_TOKEN" "NVM_DIR" "INFOPATH"))
(add-to-list 'exec-path-from-shell-variables var))
(exec-path-from-shell-initialize)))
(when kr-mac-p
(setq mouse-wheel-flip-direction t))
(when (string= system-type "darwin")
(setq mac-option-modifier 'meta))
(when kr-mac-p
(general-def 'global-map
"C-<tab>" 'tab-next
"C-S-<tab>" 'tab-previous))
(setq ns-command-modifier 'super)
(setq ns-option-modifier 'meta)
(when kr-mac-p
(setq trash-directory (expand-file-name "~/.Trash/")))
Small enhancements
(defun base64-encode-region-prefix-arg (&rest _args)
"Pass prefix arg as third arg to `base64-encode-region'."
(interactive "r\nP"))
(advice-add 'base64-encode-region :before #'base64-encode-region-prefix-arg)
(add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p)
Make parrent directory when it doesn’t exist. Taken form here
(defun kr-er-auto-create-missing-dirs ()
(let ((target-dir (file-name-directory buffer-file-name)))
(unless (file-exists-p target-dir)
(make-directory target-dir t))))
(add-to-list 'find-file-not-found-functions #'kr-er-auto-create-missing-dirs)
Setup for display-buffer-alist
. See this for reference.
This is maybe the most important variable to set, it makes switch-to-buffer
obey display-buffer-alist
rules.
(setq switch-to-buffer-obey-display-actions t)
(defun kr-swith-to-buffer-obey ()
(interactive)
(let ((switch-to-buffer-obey-display-actions nil))
(call-interactively 'switch-to-buffer)))
(general-def
"C-x C-S-b" 'kr-swith-to-buffer-obey)
(setq split-height-threshold 120)
(defun kr-display-buffer-reuse-window (buffer alist)
"Same ad `display-buffer-reuse-window' just doesn't respect
'inhibit-same-window' alist variable"
(let* ((alist-entry (assq 'reusable-frames alist))
(frames (cond (alist-entry (cdr alist-entry))
((if (eq pop-up-frames 'graphic-only)
(display-graphic-p)
pop-up-frames)
0)
(display-buffer-reuse-frames 0)
(t (last-nonminibuffer-frame))))
(window (if (eq buffer (window-buffer))
(selected-window)
;; Preferably use a window on the selected frame,
;; if such a window exists (Bug#36680).
(let* ((windows (delq (selected-window)
(get-buffer-window-list
buffer 'nomini frames)))
(first (car windows))
(this-frame (selected-frame)))
(cond
((eq (window-frame first) this-frame)
first)
((catch 'found
(dolist (next (cdr windows))
(when (eq (window-frame next) this-frame)
(throw 'found next)))))
(t first))))))
(when (window-live-p window)
(prog1 (window--display-buffer buffer window 'reuse alist)
(unless (cdr (assq 'inhibit-switch-frame alist))
(window--maybe-raise-frame (window-frame window)))))))
Function that toggles if a window can be selected with ~~other-window~ C-x o
function.
(defun kr-disable-window-select ()
"Make it so that you can't select this window with `C-x o'."
(interactive)
(if (not (window-parameter (selected-window) 'no-other-window))
(set-window-parameter (selected-window) 'no-other-window t)
(set-window-parameter (selected-window) 'no-other-window nil)))
Always open sly REPL in other window
(add-to-list 'display-buffer-alist
`("*sly-mrepl for sbcl*"
kr-display-buffer-reuse-window
(inhibit-same-window . t)))
Open sly-db window below sly-mrepl window
(defun kr-sly-db-new-window-direction (buffer alist)
"Control where sly-db buffer is shown.
BUFFER and ALIST are the same type that are needed
for `display-buffer' funcitons."
(display-buffer "*sly-mrepl for sbcl*")
(add-to-list 'alist (cons 'window (get-buffer-window "*sly-mrepl for sbcl*")))
(display-buffer-in-direction buffer alist))
(add-to-list 'display-buffer-alist
`("*sly-db for sbcl (thread [0-9]+)*"
kr-sly-db-new-window-direction
(direction . below)
(window-height . 0.5)))
Enable tab
completion
(setq tab-always-indent 'complete)
(setq completion-styles '(basic partial-completion))
Prescient is only used for sorting candidates
(use-package prescient
:config
(setq prescient-filter-method '(literal prefix literal-prefix regexp fuzzy))
(prescient-persist-mode 1))
(use-package corfu-prescient
:config
(setq corfu-prescient-override-sorting t)
(setq corfu-prescient-enable-filtering t)
(add-to-list 'corfu-prescient-completion-category-overrides
'(eglot
(styles prescient basic)))
(corfu-prescient-mode 1))
(use-package vertico-prescient
:config
(setq vertico-prescient-override-sorting t)
(setq vertico-prescient-enable-filtering nil)
(vertico-prescient-mode 1))
Used for filtering candidates
(use-package orderless
:ensure t
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))
(use-package vertico
:config
(vertico-mode 1)
(vertico-mouse-mode 1)
(setq vertico-cycle t)
(vertico-multiform-mode 1)
(setq vertico-multiform-commands
'((xref-find-references-at-mouse buffer)
(consult-yank-pop indexed)
(project-find-regexp buffer)
(consult-grep buffer)
(consult-ripgrep buffer)
(consult-git-grep buffer)
(consult-imenu buffer)
(eglot-find-implementation buffer)
(imenu buffer)))
;; (setq vertico-multiform-categories
;; '((file reverse)))
(add-hook 'minibuffer-setup-hook #'vertico-repeat-save)
(add-hook 'rfn-eshadow-update-overlay-hook 'vertico-directory-tidy) ; Correct file path when changed)
(general-def
"M-c" 'vertico-repeat)
(general-def 'vertico-map
"C-j" 'vertico-next
"C-k" 'vertico-previous
"C-<backspace>" 'vertico-directory-delete-word
"<backspace>" 'vertico-directory-delete-char
"<enter>" 'vertico-directory-enter)
(general-def 'vertico-reverse-map
"C-k" 'vertico-next
"C-j" 'vertico-previous)
(setq read-extended-command-predicate
#'command-completion-default-include-p)
(setq enable-recursive-minibuffers t)
(set-face-foreground 'vertico-group-title
"#65737E"))
corfu config:
(use-package corfu
:config
(setq corfu-cycle t)
(setq corfu-auto t)
(setq corfu-auto-prefix 1)
(setq corfu-auto-delay 0.1)
(setq corfu-max-width 50)
(setq corfu-min-width corfu-max-width)
(setq corfu-preselect-first t)
(global-corfu-mode 1)
(general-def 'corfu-map
"S-SPC" 'corfu-insert-separator
"M-h" 'corfu-info-documentation
"C-j" 'corfu-next
"C-n" 'corfu-next
"C-k" 'corfu-previous
"C-p" 'corfu-previous))
(use-package cape
:config
(add-hook 'completion-at-point-functions #'cape-file))
(setq dabbrev-case-replace nil)
(general-def
"M-/" 'dabbrev-completion
"C-M-/" 'dabbrev-expand)
(with-eval-after-load 'abbrev
(blackout 'abbrev-mode))
(defun kr-font-available-p (font-name)
(find-font (font-spec :name font-name)))
(cond
((kr-font-available-p "Cascadia Code")
(set-frame-font "Cascadia Code-12"))
((kr-font-available-p "Menlo")
(set-frame-font "Menlo-12"))
((kr-font-available-p "DejaVu Sans Mono")
(set-frame-font "DejaVu Sans Mono-12"))
((kr-font-available-p "Inconsolata")
(set-frame-font "Inconsolata-12")))
(if kr-mac-p
(set-face-attribute 'default nil :height 135)
(set-face-attribute 'default nil :height 115))
(use-package doom-themes
:demand t
:config
(if kr-mac-p
(load-theme 'doom-oceanic-next t)
(load-theme 'doom-xcode t))
;; global-hl-line-mode and region have the same color so i change it here
;; (set-face-attribute 'region nil :background "#454545")
(set-face-attribute 'secondary-selection nil :background "#151A2D")
;; (set-face-attribute 'highlight nil :background "#454545")
;; tab-bar-mode face
(set-face-attribute 'tab-bar nil :background "#1e2029")
(set-face-attribute 'tab-bar-tab nil
:foreground "#ffffff"
:background "#282a36"
:overline "gray90"
:box nil))
(when window-system
(add-to-list 'initial-frame-alist '(fullscreen . maximized)))
alternative package undo-hl
.
(use-package goggles
:hook ((prog-mode text-mode) . goggles-mode)
:config
(with-eval-after-load 'goggles
(blackout 'goggles-mode)))
(use-package hl-todo
:hook (prog-mode . hl-todo-mode)
:config
(general-def 'hl-todo-mode-map
"C-z [t" 'hl-todo-previous
"C-z ]t" 'hl-todo-next)
(with-eval-after-load 'meow-mode
(meow-define-keys 'normal
'("[t" . "C-z [t")
'("]t" . "C-z ]t")))
(setq hl-todo-highlight-punctuation ":")
(setq hl-todo-keyword-faces
'(("TODO" . "#FF4500")
("FIXME" . "#FF0000")
("DEBUG" . "#A020F0")
("GOTCHA" . "#FF4500")
("STUB" . "#1E90FF")
("NOTE" . "#AAD700"))))
(setq display-line-numbers-width 3)
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(global-hl-line-mode 1)
(use-package evil-matchit
:config
(with-eval-after-load 'meow
(general-def meow-normal-state-keymap
"%" 'evilmi-jump-items-native)))
Smart paren I’m using to pair characters like quotes.
(use-package smartparens
:config
(require 'smartparens-config)
(defun indent-between-pair (&rest _ignored)
(newline)
(indent-according-to-mode)
(forward-line -1)
(indent-according-to-mode))
(sp-local-pair 'prog-mode "{" nil :post-handlers '((indent-between-pair "RET")))
(sp-local-pair 'prog-mode "[" nil :post-handlers '((indent-between-pair "RET")))
(sp-local-pair 'prog-mode "(" nil :post-handlers '((indent-between-pair "RET")))
(smartparens-global-mode 1)
(show-smartparens-global-mode -1) ; alternative to show-paren-mode
(show-paren-mode 1)
(set-face-background 'show-paren-match "#7d7b7b")
(blackout 'smartparens-mode))
(use-package expand-region
:config
(setq expand-region-subword-enabled t))
(use-package embrace
:config
(general-def meow-normal-state-keymap
"C" 'embrace-commander))
(use-package puni
:config
(general-def 'meow-normal-state-keymap
"D" 'puni-kill-line
">" 'k-compine-slurp-and-barf-forward
"<" 'k-compine-slurp-and-barf-back)
(defun k-compine-slurp-and-barf-forward (arg)
(interactive "p")
(if (> arg 0)
(puni-slurp-forward arg)
(puni-barf-forward (- arg))))
(defun k-compine-slurp-and-barf-back (arg)
(interactive "p")
(if (> arg 0)
(puni-slurp-backward arg)
(puni-barf-backward (- arg)))))
(use-package undo-tree
:config
(global-undo-tree-mode 1)
(general-def undo-tree-visualizer-mode-map
"k" 'undo-tree-visualize-undo
"j" 'undo-tree-visualize-redo
"h" 'undo-tree-visualize-switch-branch-left
"l" 'undo-tree-visualize-switch-branch-right)
;; changes needed for undo-tree to play nice with meow
(general-def undo-tree-map
"C-x r u" nil
"C-x r U" nil
"C-x C-r u" 'undo-tree-save-state-to-register
"C-x C-r U" 'undo-tree-restore-state-from-register
"C-x r" 'find-file-read-only)
(blackout 'undo-tree-mode))
(defun kr-unpop-to-mark-command ()
"Unpop off mark ring. Does nothing if mark ring is empty."
(interactive)
(when mark-ring
(setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
(set-marker (mark-marker) (car (last mark-ring)) (current-buffer))
(when (null (mark t)) (ding))
(setq mark-ring (nbutlast mark-ring))
(goto-char (marker-position (car (last mark-ring))))))
(unless (package-installed-p 'find-char)
(package-vc-install "https://github.com/casouri/find-char"))
(use-package find-char)
(use-package marginalia
:config
(marginalia-mode 1)
(setq marginalia-annotators '(marginalia-annotators-heavy
marginalia-annotators-light nil)))
To search for multiple words with consult-ripgrep
you should search e.g. for
#defun#some words
. The first filter is passed to an async ripgrep
process
and the second filter to the completion-style filtering (?).
(use-package consult
:config
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
(general-def
[remap switch-to-buffer] 'consult-buffer
[remap apropos-command] 'consult-apropos
[remap yank-pop] 'consult-yank-pop
[remap goto-line] 'consult-goto-line
[remap project-switch-to-buffer] 'project-list-buffers
[remap project-list-buffers] 'consult-project-buffer
"C-s" 'consult-line)
(general-def mode-specific-map
"bB" 'consult-buffer-other-window
"bf" 'consult-focus-lines
"i" 'consult-imenu)
(setq consult-narrow-key "<")
;; preview only works with consult commands
(setq consult-preview-key 'any)
(with-eval-after-load 'consult
(consult-customize
consult-buffer
:preview-key "C-o")))
- You can act on candidates with
C-l
and ask to remind bindings withC-h
- You can run
embark-export
on all results (e.g. after aconsult-line
) withC-l E
- You can run
embark-export-snapshot
withC-l S
- You can run
(use-package embark
:config
(general-def
"C-." 'embark-act)
(general-def 'mode-specific-map
"a a" 'embark-act))
(use-package embark-consult
:after (embark consult))
(use-package xref
:ensure nil
:config
(setq xref-prompt-for-identifier nil)
(general-def
"s-[" 'xref-go-back
"s-]" 'xref-go-forward
"s-<mouse-1>" 'xref-find-references-at-mouse))
(unless (package-installed-p 'empx)
(package-vc-install "https://github.com/ISouthRain/empx"))
(use-package empx
:disabled
:config
(empx-mode 1))
General TUI apps that are emacs.
Emacs builtin file menager.
(setq dired-dwim-target t)
(setq dired-isearch-filenames 'dwim)
(setq dired-recursive-copies 'always)
(setq dired-recursive-deletes 'always)
(setq dired-create-destination-dirs 'always)
(setq dired-listing-switches "-valh --group-directories-first")
(add-hook 'dired-mode-hook 'toggle-truncate-lines)
(add-hook 'dired-mode-hook #'(lambda () (unless (file-remote-p default-directory)
(auto-revert-mode))))
(when (string= system-type "darwin")
(setq dired-use-ls-dired t
insert-directory-program (executable-find "gls")
dired-listing-switches "-aBhl --group-directories-first"))
(general-def 'dired-mode-map
"K" 'dired-kill-subdir
"<mouse-2>" 'dired-mouse-find-file
"C-c '" 'dired-toggle-read-only
"/" 'dired-goto-file)
dired-x
(require 'dired-x)
(put 'dired-jump 'repeat-map nil)
(add-hook 'dired-mode-hook
#'(lambda ()
(setq dired-clean-confirm-killing-deleted-buffers nil)))
;; dired-x will help to remove buffers that were associated with deleted
;; files/directories
;; to not get y-or-no question for killing buffers when deliting files go here for
;; inspiration on how to do it
;; https://stackoverflow.com/questions/11546639/dired-x-how-to-set-kill-buffer-of-too-to-yes-without-confirmation
;; https://emacs.stackexchange.com/questions/30676/how-to-always-kill-dired-buffer-when-deleting-a-folder
;; https://www.reddit.com/r/emacs/comments/91xnv9/noob_delete_buffer_automatically_after_removing/
(use-package all-the-icons-dired
:config
(when (display-graphic-p)
(add-hook 'dired-mode-hook #'(lambda () (interactive)
(unless (file-remote-p default-directory)
(all-the-icons-dired-mode))))))
(use-package dired-subtree
:config
(general-def dired-mode-map
"TAB" 'dired-subtree-toggle)
(advice-add 'dired-subtree-toggle
:after #'(lambda ()
(interactive)
(call-interactively #'revert-buffer))))
(use-package dired-rainbow
:config
(require 'dired-rainbow)
(dired-rainbow-define-chmod directory "#6cb2eb" "d.*")
(dired-rainbow-define html "#eb5286" ("css" "less" "sass" "scss" "htm" "html" "jhtm" "mht" "eml" "mustache" "xhtml"))
(dired-rainbow-define xml "#f2d024" ("xml" "xsd" "xsl" "xslt" "wsdl" "bib" "json" "msg" "pgn" "rss" "yaml" "yml" "rdata"))
(dired-rainbow-define document "#9561e2" ("docm" "doc" "docx" "odb" "odt" "pdb" "pdf" "ps" "rtf" "djvu" "epub" "odp" "ppt" "pptx"))
(dired-rainbow-define markdown "#ffed4a" ("org" "etx" "info" "markdown" "md" "mkd" "nfo" "pod" "rst" "tex" "textfile" "txt"))
(dired-rainbow-define database "#6574cd" ("xlsx" "xls" "csv" "accdb" "db" "mdb" "sqlite" "nc"))
(dired-rainbow-define media "#de751f" ("mp3" "mp4" "MP3" "MP4" "avi" "mpeg" "mpg" "flv" "ogg" "mov" "mid" "midi" "wav" "aiff" "flac"))
(dired-rainbow-define image "#f66d9b" ("tiff" "tif" "cdr" "gif" "ico" "jpeg" "jpg" "png" "psd" "eps" "svg"))
(dired-rainbow-define log "#c17d11" ("log"))
(dired-rainbow-define shell "#f6993f" ("awk" "bash" "bat" "sed" "sh" "zsh" "vim"))
(dired-rainbow-define interpreted "#38c172" ("py" "ipynb" "rb" "pl" "t" "msql" "mysql" "pgsql" "sql" "r" "clj" "cljs" "scala" "js"))
(dired-rainbow-define compiled "#4dc0b5" ("asm" "cl" "lisp" "el" "c" "h" "c++" "h++" "hpp" "hxx" "m" "cc" "cs" "cp" "cpp" "go" "f" "for" "ftn" "f90" "f95" "f03" "f08" "s" "rs" "hi" "hs" "pyc" ".java"))
(dired-rainbow-define executable "#8cc4ff" ("exe" "msi"))
(dired-rainbow-define compressed "#51d88a" ("7z" "zip" "bz2" "tgz" "txz" "gz" "xz" "z" "Z" "jar" "war" "ear" "rar" "sar" "xpi" "apk" "xz" "tar"))
(dired-rainbow-define packaged "#faad63" ("deb" "rpm" "apk" "jad" "jar" "cab" "pak" "pk3" "vdf" "vpk" "bsp"))
(dired-rainbow-define encrypted "#ffed4a" ("gpg" "pgp" "asc" "bfe" "enc" "signature" "sig" "p12" "pem"))
(dired-rainbow-define fonts "#6cb2eb" ("afm" "fon" "fnt" "pfb" "pfm" "ttf" "otf"))
(dired-rainbow-define partition "#e3342f" ("dmg" "iso" "bin" "nrg" "qcow" "toast" "vcd" "vmdk" "bak"))
(dired-rainbow-define vc "#0074d9" ("git" "gitignore" "gitattributes" "gitmodules"))
(dired-rainbow-define-chmod executable-unix "#38c172" "-.*x.*"))
Git client in emacs
(use-package transient
:config
(setq transient-display-buffer-action
'(display-buffer-below-selected
(dedicated . t)
(inhibit-same-window . t))))
(use-package magit
:config
(add-hook 'git-commit-setup-hook #'flyspell-mode)
(add-hook 'after-save-hook 'magit-after-save-refresh-status t)
(setq git-commit-fill-column 72)
(setq magit-process-finish-apply-ansi-colors t)
(setq magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
(setq magit-save-repository-buffers 'dontask)
(dolist (face '(magit-diff-added
magit-diff-added-highlight
magit-diff-removed
magit-diff-removed-highlight))
(set-face-background face (face-attribute 'magit-diff-context-highlight :background)))
(set-face-background 'magit-diff-context-highlight
(face-attribute 'default :background))
(general-def mode-specific-map
"v f" 'magit-find-file
"v F" 'magit-find-file-other-window
"v v" 'magit-status
"v V" 'magit-status-here)
(general-def 'magit-status-mode-map
"S-<tab>" 'magit-section-cycle
"C-<tab>" 'tab-next)
(with-eval-after-load 'meow
(add-hook 'git-commit-setup-hook
(defun kr-git-commit-start-insert-maybe ()
(when (and (bound-and-true-p meow-mode)
(bobp) (eolp))
(meow-insert)))))
(with-eval-after-load 'project
(general-def 'project-prefix-map
"v" 'magit-project-status)
(remove-hook 'project-switch-commands '(project-vc-dir "VC-Dir"))
(add-hook 'project-switch-commands '(magit-project-status "Magit") 100)))
Display funciton to open magit additional buffers bellow current status one.
(defun kr-magit-display-buffer-same-window-except-diff-v1 (buffer)
"Display BUFFER in the selected window except for some modes.
If a buffer's `major-mode' derives from `magit-diff-mode' or
`magit-process-mode', display it in another window bellow the current one. Display all
other buffers in the selected window."
(display-buffer
buffer (if (with-current-buffer buffer
(derived-mode-p 'magit-diff-mode 'magit-process-mode))
'(display-buffer-below-selected
(window-height . 0.75)
(inhibit-same-window . t))
'(display-buffer-same-window))))
If I ever need to change to margin I can use this to setup diff-hl in margin https://github.com/jimeh/.emacs.d/blob/master/modules/version-control/siren-diff-hl.el
(use-package git-gutter-fringe
:config
(setq git-gutter:update-interval 0.02)
(require 'git-gutter-fringe) ; don't delete, must be here to style fringe
(add-hook 'emacs-startup-hook #'global-git-gutter-mode)
;; how git-gutter looks in the fringe of the window
(define-fringe-bitmap 'git-gutter-fr:added [#b11100000] nil nil '(center repeated))
(define-fringe-bitmap 'git-gutter-fr:modified [#b11100000] nil nil '(center repeated))
(define-fringe-bitmap 'git-gutter-fr:deleted
[#b10000000
#b11000000
#b11100000
#b11110000] nil nil 'bottom)
(with-eval-after-load 'git-gutter
(blackout 'git-gutter-mode))
;; setup repeat map for git-gutter
(defvar kr-git-gutter-map
(let ((keymap (make-sparse-keymap)))
(define-key keymap (kbd "p") 'git-gutter:previous-hunk)
(define-key keymap (kbd "n") 'git-gutter:next-hunk)
keymap))
(put 'git-gutter:next-hunk 'repeat-map 'kr-git-gutter-map)
(put 'git-gutter:previous-hunk 'repeat-map 'kr-git-gutter-map)
(general-def
"C-z g" kr-git-gutter-map
"<left-fringe> <mouse-3>" 'git-gutter:popup-hunk))
(use-package git-timemachine
:config
(setq git-timemachine-show-minibuffer-details t)
(general-def 'git-timemachine-mode-map
"C-k" 'git-timemachine-show-previous-revision
"C-j" 'git-timemachine-show-next-revision
"q" 'git-timemachine-quit))
(use-package browse-at-remote
:config
(general-def 'mode-specific-map
"v W" 'browse-at-remote)
)
(use-package kubernetes
:config
(setq kubernetes-overview-custom-views-alist
'((custom-overview . (context statefulsets deployments))))
(setq kubernetes-default-overview-view 'custom-overview)
(add-hook 'kubernetes-logs-mode-hook #'visual-line-mode)
(add-hook 'kubernetes-logs-mode-hook #'display-line-numbers-mode)
(add-hook 'kubernetes-logs-mode-hook #'ansi-color-mode)
(general-def 'kubernetes-overview-mode-map
"S-<tab>" 'magit-section-cycle
"C-<tab>" 'tab-next))
;; ;; https://orgmode.org/manual/Labels-and-captions-in-ODT-export.html
;; (setq org-odt-category-map-alist
;; '(("__Figure__" "Slika" "value" "Figure" org-odt--enumerable-image-p)))
(require 'org-tempo)
(add-to-list 'org-modules 'org-tempo t)
(add-to-list 'org-structure-template-alist
'("el" . "src emacs-lisp"))
(setq org-startup-indented t)
(setq org-image-actual-width 700)
(setq org-M-RET-may-split-line nil)
(setq org-return-follows-link t)
(setq org-src-window-setup 'current-window)
(with-eval-after-load 'org-indent
(blackout 'org-indent-mode))
(add-hook 'org-mode-hook #'abbrev-mode)
Closely related to org-mode
but not really so it goes here with org mode
(use-package olivetti
:config
(setq olivetti-body-width 90))
(use-package devdocs
:config
(add-hook 'devdocs-mode-hook #'olivetti-mode)
(add-hook 'dart-mode-hook
#'(lambda () (setq-local devdocs-current-docs '("dart~2")))))
(general-def 'Man-mode-map
"d" 'View-scroll-half-page-forward
"u" 'View-scroll-half-page-backward)
(general-def
[remap list-buffers] 'ibuffer)
(use-package wgrep
:config
(require 'wgrep)
(set-face-background 'wgrep-face "#B6268"))
(use-package project
:ensure nil
:config
(setq project-vc-extra-root-markers '("go.mod" "requirements.txt"))
(defun kr-project-grep ()
(interactive)
(if mark-active
(progn
(meow-save)
(meow-cancel-selection)))
(let ((vertico-buffer-mode t))
(if (or (eql (cadr (project-current)) 'Git) (eql (car (project-current)) 'go-module))
(call-interactively #'consult-git-grep)
(call-interactively #'consult-ripgrep))))
(with-eval-after-load 'consult
(require 'vertico-buffer)
(define-key project-prefix-map (kbd "g") 'consult-ripgrep)))
(add-hook 'special-mode-hook 'visual-line-mode)
(use-package eglot
:hook ((go-ts-mode typescript-mode js-mode) . eglot-ensure)
:config
(general-def 'eglot-mode-map
"C-z l r r" 'eglot-rename
"C-z h" 'eldoc-box-help-at-point)
(set-face-attribute 'eglot-highlight-symbol-face nil :background nil :underline "#f8f8f8")
(general-def 'eglot-mode-map
"C-M-." 'eglot-find-implementation)
(add-hook 'eglot-managed-mode-hook
(defun kr-eglot-switch-eldoc-functions ()
(remove-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function t)
(add-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function nil t)))
(add-hook 'go-ts-mode-hook #'eglot-ensure)
(add-hook 'rust-mode-hook #'eglot-ensure))
(unless (package-installed-p 'dape)
(package-vc-install "https://github.com/svaante/dape"))
(use-package dape
:after meow
:init
(setq dape-debug t)
:commands (dape)
:config
(dolist (cmd dape-global-map)
(unless (eq cmd 'keymap)
(put (cdr cmd) 'repeat-map nil)))
(setq dape-inlay-hints t)
(setf (alist-get 'go-test dape-configs)
`(modes (go-mode go-ts-mode)
ensure dape-ensure-command
fn (dape-config-autoport dape-config-tramp)
command "dlv"
command-args ("dap" "--listen" "127.0.0.1::autoport")
command-cwd (lambda()(if (string-suffix-p "_test.go" (buffer-name))
default-directory (dape-cwd)))
port :autoport
:type "debug"
:request "launch"
:mode (lambda() (if (string-suffix-p "_test.go" (buffer-name)) "test" "debug"))
:program "."
:cwd "."
:args (lambda()
(require 'which-func)
(if (string-suffix-p "_test.go" (buffer-name))
(when-let* ((test-name (which-function))
(test-regexp (concat "^" test-name "$")))
(if test-name `["-test.run" ,test-regexp]
(error "No test selected")))
[]))))
(defvar meow-dape-state-keymap (make-sparse-keymap))
(meow-define-state dape
"meow for dape repl context"
:lighter " [D]"
:keymap meow-dape-state-keymap)
(meow-define-keys 'dape
'("<" . dape-stack-select-up)
'(">" . dape-stack-select-down)
'("B" . dape-breakpoint-remove-all)
'("D" . dape-disconnect-quit)
'("R" . dape-repl)
'("S" . dape-select-stack)
'("b" . dape-breakpoint-toggle)
'("c" . dape-continue)
'("d" . dape)
'("e" . dape-breakpoint-expression)
'("h" . dape-breakpoint-hits)
'("I" . dape-info)
'("i" . meow-insert)
'("l" . dape-breakpoint-log)
'("m" . dape-read-memory)
'("n" . dape-next)
'("o" . dape-step-out)
'("p" . dape-pause)
'("q" . dape-quit)
'("r" . dape-restart)
'("s" . dape-step-in)
'("t" . dape-select-thread)
'("w" . dape-watch-dwim)
'("x" . dape-evaluate-expression))
(add-to-list 'meow-mode-state-list '(dape-repl-mode . dape)))
(use-package treesit-auto
:custom
(treesit-auto-install 'prompt)
:config
(setq treesit-font-lock-level 4)
(setq treesit-auto-langs
'(bash c cpp cmake go gomod dockerfile markdown tsx typescript html css javascript json yaml))
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
Formating code buffers on save.
(use-package apheleia
:hook (js-mode go-ts-mode)
:init
(add-hook 'go-ts-mode-hook
(defun kr-go-format-buffer ()
(setq-local apheleia-formatter '(goimports gofmt))))
:config
(setf (alist-get 'goimports apheleia-formatters)
'("goimports" "-srcdir" filepath)))
Seting sbcl
to be default interpreter for lisp.
(if (executable-find "ros")
(setq inferior-lisp-program "ros -Q run")
(setq inferior-lisp-program "sbcl"))
(use-package sly
:config
(setq sly-mrepl-prevent-duplicate-history t)
;; (setq sly-contribs '(sly-fancy sly-mrepl))
(general-def 'sly-mode-map
"C-z h" 'sly-describe-symbol)
(with-eval-after-load 'meow
(add-to-list 'meow-mode-state-list '(sly-mrepl-mode . normal))
(add-to-list 'meow-mode-state-list '(sly-db-mode . motion))
(add-to-list 'meow-mode-state-list '(sly-xref-mode . motion))
(add-to-list 'meow-mode-state-list '(sly-stickers--replay-mode . motion))
(add-to-list 'meow-mode-state-list '(sly-inspector-mode . motion)))
;; switch bufers REPL - DB - Source
(general-def '(lisp-mode-map sly-mrepl-mode-map)
"C-c d" #'(lambda () (interactive) (switch-to-buffer "*sly-db for sbcl (thread 1)*")))
(general-def '(lisp-mode-map sly-db-mode-map sly-db-frame-map)
"C-c '" #'(lambda ()
(interactive)
(call-interactively #'sly-mrepl)
(end-of-buffer)))
(general-def '(sly-db-mode-map sly-db-frame-map)
"C-c d" #'sly-switch-to-most-recent)
(general-def 'sly-mrepl-mode-map
"C-j" 'sly-mrepl-next-prompt
"C-k" 'sly-mrepl-previous-prompt
"C-p" 'sly-mrepl-previous-input-or-button
"C-n" 'sly-mrepl-next-input-or-button
"C-c '" #'sly-switch-to-most-recent)
(general-def 'sly-stickers--replay-mode-map
"/" 'sly-stickers-replay-jump))
(use-package sly-repl-ansi-color
:config
(push 'sly-repl-ansi-color sly-contribs))
(setq js-indent-level 2)
(use-package typescript-mode
:config
(add-hook 'typescript-mode-hook #'apheleia-mode)
(setq typescript-indent-level 2))
(use-package jsonian
:config
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
`(jsonian-mode . ,(eglot-alternatives '(("vscode-json-language-server" "--stdio") ("json-languageserver" "--stdio")))))))
(use-package terraform-mode)
(use-package go-ts-mode
:ensure-system-package
((goimports . "go install golang.org/x/tools/cmd/goimports@latest"))
:config
(setq go-ts-mode-indent-offset 4))
(use-package yaml-mode
:config
(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))
(add-hook 'yaml-mode-hook #'toggle-truncate-lines)
(add-hook 'yaml-mode-hook #'display-line-numbers-mode))
(use-package yasnippet
:config
(defun kr-is-corfu-active ()
(when corfu--candidates t))
(add-hook 'yas-keymap-disable-hook #'kr-is-corfu-active)
(setq yas-alias-to-yas/prefix-p nil) ; don't make yas/prefix commands
(add-hook 'prog-mode-hook #'yas-minor-mode))
(use-package jenkinsfile-mode)
(use-package dockerfile-mode)
(add-hook 'prog-mode-hook #'toggle-truncate-lines)
Meow is a mode for modal edditing inpired by VIM.
(defun kr-puni-kill-dwim ()
(interactive)
(if (use-region-p)
(puni-kill-region)
(puni-kill-line)))
(defun meow-setup ()
"My meow setup thats similar to evil/vim"
(meow-motion-overwrite-define-key
'("j" . meow-next)
'("k" . meow-prev)
'("M-j" . scroll-up-line)
'("M-k" . scroll-down-line)
'("`" . kr-meow-last-buffer)
'("<escape>" . keyboard-quit))
(meow-leader-define-key
;; SPC j/k will run the original command in MOTION state.
'("j" . "H-j")
'("k" . "H-k")
'("`" . "H-`")
'("?" . meow-cheatsheet)
'("/" . meow-keypad-describe-key))
(meow-normal-define-key
'("0" . meow-expand-0)
'("9" . meow-expand-9)
'("8" . meow-expand-8)
'("7" . meow-expand-7)
'("6" . meow-expand-6)
'("5" . meow-expand-5)
'("4" . meow-expand-4)
'("3" . meow-expand-3)
'("2" . meow-expand-2)
'("1" . meow-expand-1)
'("=". scroll-lock-mode)
'("-" . negative-argument)
'("`" . kr-meow-last-buffer)
'("<escape>" . keyboard-quit)
;; thing
'("." . meow-inner-of-thing)
'("," . meow-bounds-of-thing)
;; '("[" . meow-beginning-of-thing)
;; '("]" . meow-end-of-thing)
'("u" . meow-undo)
'("U" . undo-tree-redo)
'("y" . meow-save)
'("p" . meow-yank)
'("i" . meow-insert)
'("a" . meow-append)
'("j" . next-line)
'("k" . previous-line)
'("h" . backward-char)
'("l" . forward-char)
'("M-j" . scroll-up-line)
'("M-k" . scroll-down-line)
'("H" . beginning-of-line-text)
'("L" . move-end-of-line)
'("J" . meow-next-expand)
'("K" . meow-prev-expand)
'("c" . meow-change)
'("n" . meow-search)
'("/" . meow-visit)
'("D" . puni-kill-line)
'("d" . kr-puni-kill-dwim)
'("x" . puni-backward-delete-char)
'("X" . puni-forward-delete-char)
'("Z" . puni-force-delete)
'("e" . meow-next-word)
'("E" . puni-forward-sexp)
'(";" . meow-reverse)
'("b" . meow-back-word)
'("B" . puni-backward-sexp)
'("v" . set-mark-command)
'("V" . meow-line)
'("f" . find-char)
'("t" . meow-till)
'("G" . meow-grab)
'("m" . meow-join)
;; need to think about these bindings
'("r" . meow-replace)
'("R" . meow-swap-grab)
'("P" . meow-sync-grab)
'("@" . goto-line)
'("z" . meow-pop-selection)
'("o" . meow-open-below)
'("O" . meow-open-above)
'("q" . meow-quit)
'("Q" . kill-current-buffer))
(meow-normal-define-key
'("{" . backward-paragraph)
'("}" . forward-paragraph))
;; help
(meow-normal-define-key
'("M-h" . "C-z h"))
(meow-motion-overwrite-define-key
'("M-h" . "C-z h"))
;; commands that are not from meow
(meow-normal-define-key
'("M" . set-mark-command)
'("'" . pop-to-mark-command)
'("\"" . pop-global-mark))
(meow-leader-define-key
(cons "p" project-prefix-map)))
(use-package meow
:config
(require 'meow)
(meow-setup)
(meow-global-mode 1)
(setq meow-use-clipboard t)
(setq meow-keypad-leader-dispatch "C-c")
(add-hook 'ghelp-page-mode-hook 'meow-motion-mode)
(add-to-list 'meow-mode-state-list '(helpful-mode . motion))
(add-to-list 'meow-mode-state-list '(ghelp . motion))
(add-to-list 'meow-mode-state-list '(fundamental-mode . normal))
(add-to-list 'meow-mode-state-list '(eshell-mode . normal))
(general-def 'meow-normal-state-keymap
"Z" 'meow-cancel-selection))
(with-eval-after-load 'corfu
(add-hook 'meow-insert-exit-hook #'corfu-quit))
(defun kr-meow-last-buffer ()
(interactive)
(let ((switch-to-buffer-obey-display-actions nil))
(call-interactively #'meow-last-buffer)))
For some comands meow-find
, meow-till
, meow-line
… you can press - (negative-argument)
to go in reverse. We already have a meow command to go in reverse meow-reverse
but it only works if we have a selection so I aviced it to enter negative-argument
when there is no selection so that it can be used when there is no selection active.
(defun kr-meow-reverse (fun)
"Attemt to reverse command when there is no selection."
(if (region-active-p)
(funcall fun)
(call-interactively #'negative-argument)))
(advice-add 'meow-reverse :around #'kr-meow-reverse)
Normally when in normal-state
the number keys 0..9 are bount to meow-expand-[0..9]
. This command doesn’t do anything if there is no selection so I made an advice so it calls digit-argument
if there is no seleciton, so you can press 9 meow-line
or meow-line 9
and you will do the same thing.
(defun kr-meow-maybe-digit (fun n)
"Advice so that I can get digit arguments if there is no
selection active and expand selestion if the selection is active."
(if (region-active-p)
(funcall fun n)
(call-interactively #'digit-argument)))
(advice-add 'meow-expand :around #'kr-meow-maybe-digit)
(defun kr-meow-yank ()
(save-excursion
(exchange-point-and-mark t)
(indent-according-to-mode))
(indent-according-to-mode))
(advice-add 'meow-yank :after #'kr-meow-yank)
(defun kr-meow-motion-normal ()
(interactive)
(cond ((meow-motion-mode-p)
(meow-normal-mode 1)(meow-motion-mode -1))
(t
(meow-normal-mode -1)(meow-motion-mode 1))))
(general-def '(meow-motion-state-keymap meow-normal-state-keymap)
"|" 'kr-meow-motion-normal)
Insert or append on line.
(defun kr-meow-append-to-line ()
"Append to line."
(interactive)
(if (region-active-p)
(progn
(unless (= (point) (region-end))
(meow-reverse))
(embrace-add))
(progn
(end-of-line)
(call-interactively #'meow-append))))
(defun kr-meow-insert-to-line ()
"Insert to line."
(interactive)
(if (region-active-p)
(progn
(unless (= (point) (region-beginning))
(meow-reverse))
(embrace-add)
(forward-char))
(progn
(beginning-of-line-text)
(call-interactively #'meow-insert))))
(general-def 'meow-normal-state-keymap
"I" 'kr-meow-insert-to-line
"A" 'kr-meow-append-to-line)
This makes it work with smartparens
surround feature.
;; Smartparens integraion
(defun kr-meow-append-mark ()
"Move to end of selection and switch to insert state.
Keep mark active."
(interactive)
(call-interactively #'meow-append)
(activate-mark))
(defun kr-meow-insert-mark ()
"Move to beginign of selection and switch to insert state.
Keep mark active."
(interactive)
(call-interactively #'meow-insert)
(activate-mark))
extend meow-kill
so that it kills the whole line if mark is not active
(defun kr-meow-kill-whole-line (old-fun)
"Delete line if there is no selection but delete selection if there
is active selection."
(if (region-active-p)
(meow-kill)
(funcall old-fun)))
(advice-add 'meow-kill-whole-line :around 'kr-meow-kill-whole-line)
copy line on selection
(defun kr-meow-save-line ()
(interactive)
(meow-line 1)
(call-interactively #'meow-save))
(defun kr-meow-copy-line-or-selection (fun)
"Copy region if active. Copy line if no region is active."
(if (region-active-p)
(funcall fun)
(kr-meow-save-line)))
(advice-add 'meow-save :around #'kr-meow-copy-line-or-selection)
Binding for other packages
(with-eval-after-load 'git-gutter
(general-def
"C-z g n" 'git-gutter:next-hunk
"C-z g p" 'git-gutter:previous-hunk)
(meow-define-keys 'normal
'("]g" . "C-z g n")
'("[g" . "C-z g p")))
(with-eval-after-load 'flycheck
(meow-define-keys 'normal
'("[e" . "C-z [e")
'("]e" . "C-z ]e")))
(meow-define-keys 'normal
'("gg" . magit-file-dispatch))
(meow-define-keys 'normal
'("gr" . "C-z l r r")
'("gl" . "C-z l"))
(with-eval-after-load 'meow
(defun kr-expand-with-meow ()
"Hellper command so that meow can work with expand region."
(interactive)
(call-interactively #'er/expand-region)
(let* ((beg (region-beginning))
(end (region-end))
(search (format "\\_<%s\\_>" (regexp-quote (buffer-substring-no-properties beg end)))))
(setq meow--selection (list '(expand . word) beg end))
(meow--push-search search)
(meow--highlight-regexp-in-buffer search)))
(meow-define-keys 'normal
'("w" . kr-expand-with-meow)
'("W" . er/contract-region)
'("s" . kr-expand-with-meow)
'("S" . er/contract-region)))
(use-package expreg
:config
(meow-define-keys 'normal
'("s" . expreg-expand)
'("S" . expreg-contract)))
(setq truncate-partial-width-windows 200)
(general-def
"C-`" 'next-error
"C-~" 'previous-error)
(advice-add #'meow-kill :after #'cycle-spacing)
To start emacs with different configuration run:
emacs --init-directory=directory