wip: new emacs
This commit is contained in:
@@ -154,10 +154,12 @@
|
|||||||
"https://cache.deertopia.net"
|
"https://cache.deertopia.net"
|
||||||
"https://nix-community.cachix.org"
|
"https://nix-community.cachix.org"
|
||||||
"https://cache.nixos.org"
|
"https://cache.nixos.org"
|
||||||
|
"https://cache.iog.io"
|
||||||
];
|
];
|
||||||
trusted-public-keys = [
|
trusted-public-keys = [
|
||||||
(builtins.readFile ../../public-keys/deertopia-cache.pub.pem)
|
(builtins.readFile ../../public-keys/deertopia-cache.pub.pem)
|
||||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ in {
|
|||||||
type = lib.types.listOf lib.types.package;
|
type = lib.types.listOf lib.types.package;
|
||||||
default = [];
|
default = [];
|
||||||
};
|
};
|
||||||
files = [
|
|
||||||
];
|
|
||||||
tex = {
|
tex = {
|
||||||
enable = lib.mkEnableOption "TexLive";
|
enable = lib.mkEnableOption "TexLive";
|
||||||
extraTexPackages = lib.mkOption {
|
extraTexPackages = lib.mkOption {
|
||||||
@@ -88,7 +86,7 @@ in {
|
|||||||
my-texlive = pkgs.texlive.combine
|
my-texlive = pkgs.texlive.combine
|
||||||
(essentialTexPackages ++ cfg.tex.extraTexPackages);
|
(essentialTexPackages ++ cfg.tex.extraTexPackages);
|
||||||
|
|
||||||
emacs-final =
|
sydmacs =
|
||||||
let ewp = (pkgs.emacsPackagesFor cfg.package).emacsWithPackages
|
let ewp = (pkgs.emacsPackagesFor cfg.package).emacsWithPackages
|
||||||
cfg.emacsPackages;
|
cfg.emacsPackages;
|
||||||
in pkgs.symlinkJoin {
|
in pkgs.symlinkJoin {
|
||||||
@@ -114,7 +112,7 @@ in {
|
|||||||
in {
|
in {
|
||||||
programs.emacs = {
|
programs.emacs = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = emacs-final;
|
package = sydmacs;
|
||||||
};
|
};
|
||||||
|
|
||||||
sydnix.impermanence.cache.directories = [
|
sydnix.impermanence.cache.directories = [
|
||||||
|
|||||||
18
modules/home/openutau.nix
Normal file
18
modules/home/openutau.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let cfg = config.sydnix.openutau;
|
||||||
|
in {
|
||||||
|
options.sydnix.openutau = {
|
||||||
|
enable = lib.mkEnableOption "OpenUTAU";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
home.packages = [
|
||||||
|
pkgs.openutau
|
||||||
|
];
|
||||||
|
|
||||||
|
sydnix.impermanence.directories = [
|
||||||
|
".local/share/OpenUtau"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -19,6 +19,12 @@ in {
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
sydnix.emacs = {
|
sydnix.emacs = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
inherit (cfg) userDir;
|
||||||
|
fontPackages = [
|
||||||
|
pkgs.julia-mono
|
||||||
|
pkgs.nerd-fonts.victor-mono
|
||||||
|
pkgs.ibm-plex
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
16
modules/home/users/msyds/emacs/early-init.el
Normal file
16
modules/home/users/msyds/emacs/early-init.el
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
;;; early-init.el -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
(add-to-list 'load-path
|
||||||
|
(file-name-concat user-emacs-directory "lisp"))
|
||||||
|
|
||||||
|
(defun syd-load-directory (dir)
|
||||||
|
"Load each file matching DIR/*.el in lexicographical order."
|
||||||
|
(dolist (file
|
||||||
|
;; The returned list is sorted, which is what we want. The files are
|
||||||
|
;; named with a two-digit prefix defining its load order.
|
||||||
|
(directory-files dir 'full "\\.el$"))
|
||||||
|
(load file)))
|
||||||
|
|
||||||
|
;; Load each file matching lisp/syd/early-init/*.el.
|
||||||
|
(syd-load-directory
|
||||||
|
(file-name-concat user-emacs-directory "lisp/syd/early-init"))
|
||||||
5
modules/home/users/msyds/emacs/init.el
Normal file
5
modules/home/users/msyds/emacs/init.el
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
;;; init.el -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Load each file matching lisp/syd/init/*.el.
|
||||||
|
(syd-load-directory
|
||||||
|
(file-name-concat user-emacs-directory "lisp/syd/init"))
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
;;; -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
(defvar syd-data-dir
|
||||||
|
(or (getenv "EMACS_DATA_DIR")
|
||||||
|
(file-name-concat (or (getenv "XDG_DATA_HOME")
|
||||||
|
(expand-file-name "~/.local/share"))
|
||||||
|
"emacs")))
|
||||||
|
|
||||||
|
(defvar syd-cache-dir
|
||||||
|
(or (getenv "EMACS_CACHE_DIR")
|
||||||
|
(file-name-concat (or (getenv "XDG_CACHE_HOME")
|
||||||
|
(expand-file-name "~/.cache"))
|
||||||
|
"emacs")))
|
||||||
|
|
||||||
|
(provide 'syd/early-init/define-constants)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
;;; -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
(setq package-enable-at-startup nil)
|
||||||
|
|
||||||
|
(provide 'syd/early-init/disable-package)
|
||||||
58
modules/home/users/msyds/emacs/lisp/syd/init/10-elpaca.el
Normal file
58
modules/home/users/msyds/emacs/lisp/syd/init/10-elpaca.el
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
;;; -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
|
||||||
|
;;; Installation
|
||||||
|
|
||||||
|
;; Code per Elpaca's installation instructions available at
|
||||||
|
;; https://github.com/progfolio/elpaca?tab=readme-ov-file#installer.
|
||||||
|
;; Modified to avoid polluting the Emacs user directory.
|
||||||
|
|
||||||
|
(defvar elpaca-installer-version 0.11)
|
||||||
|
(defvar elpaca-directory (expand-file-name "elpaca/" syd-data-dir))
|
||||||
|
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
|
||||||
|
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
|
||||||
|
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
|
||||||
|
:ref nil :depth 1 :inherit ignore
|
||||||
|
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
|
||||||
|
:build (:not elpaca--activate-package)))
|
||||||
|
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
|
||||||
|
(build (expand-file-name "elpaca/" elpaca-builds-directory))
|
||||||
|
(order (cdr elpaca-order))
|
||||||
|
(default-directory repo))
|
||||||
|
(add-to-list 'load-path (if (file-exists-p build) build repo))
|
||||||
|
(unless (file-exists-p repo)
|
||||||
|
(make-directory repo t)
|
||||||
|
(when (<= emacs-major-version 28) (require 'subr-x))
|
||||||
|
(condition-case-unless-debug err
|
||||||
|
(if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
|
||||||
|
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
|
||||||
|
,@(when-let* ((depth (plist-get order :depth)))
|
||||||
|
(list (format "--depth=%d" depth) "--no-single-branch"))
|
||||||
|
,(plist-get order :repo) ,repo))))
|
||||||
|
((zerop (call-process "git" nil buffer t "checkout"
|
||||||
|
(or (plist-get order :ref) "--"))))
|
||||||
|
(emacs (concat invocation-directory invocation-name))
|
||||||
|
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
|
||||||
|
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
|
||||||
|
((require 'elpaca))
|
||||||
|
((elpaca-generate-autoloads "elpaca" repo)))
|
||||||
|
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
|
||||||
|
(error "%s" (with-current-buffer buffer (buffer-string))))
|
||||||
|
((error) (warn "%s" err) (delete-directory repo 'recursive))))
|
||||||
|
(unless (require 'elpaca-autoloads nil t)
|
||||||
|
(require 'elpaca)
|
||||||
|
(elpaca-generate-autoloads "elpaca" repo)
|
||||||
|
(let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
|
||||||
|
(add-hook 'after-init-hook #'elpaca-process-queues)
|
||||||
|
(elpaca `(,@elpaca-order))
|
||||||
|
|
||||||
|
|
||||||
|
;;; Use-package support
|
||||||
|
|
||||||
|
;; Install use-package support.
|
||||||
|
(elpaca elpaca-use-package
|
||||||
|
(elpaca-use-package-mode))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(provide 'syd/init/elpaca)
|
||||||
108
modules/home/users/msyds/emacs/lisp/syd/init/10-use-package.el
Normal file
108
modules/home/users/msyds/emacs/lisp/syd/init/10-use-package.el
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(defvar syd-incremental-idle-timer 0.75
|
||||||
|
"How long (in idle seconds) in between incrementally loading packages.")
|
||||||
|
|
||||||
|
(defvar syd-incremental-first-idle-timer (if (daemonp) 0 2.0)
|
||||||
|
"How long (in idle seconds) until incremental loading starts.
|
||||||
|
|
||||||
|
Set this to nil to disable incremental loading at startup.
|
||||||
|
Set this to 0 to load all incrementally deferred packages immediately at
|
||||||
|
`after-init-hook'.")
|
||||||
|
|
||||||
|
(defvar syd-incremental-packages '(t)
|
||||||
|
"A list of packages to load incrementally after startup. Any large packages
|
||||||
|
here may cause noticeable pauses, so it's recommended you break them up into
|
||||||
|
sub-packages. For example, `org' is comprised of many packages, and might be
|
||||||
|
broken up into:
|
||||||
|
|
||||||
|
(syd-load-packages-incrementally
|
||||||
|
'(calendar find-func format-spec org-macs org-compat
|
||||||
|
org-faces org-entities org-list org-pcomplete org-src
|
||||||
|
org-footnote org-macro ob org org-clock org-agenda
|
||||||
|
org-capture))
|
||||||
|
|
||||||
|
This is already done by the lang/org module, however.
|
||||||
|
|
||||||
|
If you want to disable incremental loading altogether, either remove
|
||||||
|
`syd-load-packages-incrementally-h' from `after-init-hook' or set
|
||||||
|
`syd-incremental-first-idle-timer' to nil. Incremental loading does not occur
|
||||||
|
in daemon sessions (they are loaded immediately at startup).")
|
||||||
|
|
||||||
|
(defun syd-load-packages-incrementally (packages &optional now)
|
||||||
|
"Registers PACKAGES to be loaded incrementally.
|
||||||
|
|
||||||
|
If NOW is non-nil, PACKAGES will be marked for incremental loading next time
|
||||||
|
Emacs is idle for `syd-incremental-first-idle-timer' seconds (falls back to
|
||||||
|
`syd-incremental-idle-timer'), then in `syd-incremental-idle-timer' intervals
|
||||||
|
afterwards."
|
||||||
|
(let* ((gc-cons-threshold most-positive-fixnum)
|
||||||
|
(first-idle-timer (or syd-incremental-first-idle-timer
|
||||||
|
syd-incremental-idle-timer)))
|
||||||
|
(if (not now)
|
||||||
|
(cl-callf append syd-incremental-packages packages)
|
||||||
|
(while packages
|
||||||
|
(let ((req (pop packages))
|
||||||
|
idle-time)
|
||||||
|
(unless (featurep req)
|
||||||
|
(condition-case-unless-debug e
|
||||||
|
(and
|
||||||
|
(or (null (setq idle-time (current-idle-time)))
|
||||||
|
(< (float-time idle-time) first-idle-timer)
|
||||||
|
(not
|
||||||
|
(while-no-input
|
||||||
|
;; If `default-directory' doesn't exist or is
|
||||||
|
;; unreadable, Emacs throws file errors.
|
||||||
|
(let ((default-directory user-emacs-directory)
|
||||||
|
(inhibit-message t)
|
||||||
|
(file-name-handler-alist
|
||||||
|
(list (rassq 'jka-compr-handler file-name-handler-alist))))
|
||||||
|
(message "loading %s" req)
|
||||||
|
(require req nil t)
|
||||||
|
t))))
|
||||||
|
(push req packages))
|
||||||
|
(error
|
||||||
|
(message "Error: failed to incrementally load %S because: %s" req e)
|
||||||
|
(setq packages nil)))
|
||||||
|
(unless (null packages)
|
||||||
|
(run-at-time (if idle-time
|
||||||
|
syd-incremental-idle-timer
|
||||||
|
first-idle-timer)
|
||||||
|
nil #'syd-load-packages-incrementally
|
||||||
|
packages t)
|
||||||
|
(setq packages nil))))))))
|
||||||
|
|
||||||
|
(defun syd-load-packages-incrementally-h ()
|
||||||
|
"Begin incrementally loading packages in `syd-incremental-packages'.
|
||||||
|
|
||||||
|
If this is a daemon session, load them all immediately instead."
|
||||||
|
(when (numberp syd-incremental-first-idle-timer)
|
||||||
|
(if (zerop syd-incremental-first-idle-timer)
|
||||||
|
(mapc #'require (cdr syd-incremental-packages))
|
||||||
|
(run-with-idle-timer syd-incremental-first-idle-timer
|
||||||
|
nil #'syd-load-packages-incrementally
|
||||||
|
(cdr syd-incremental-packages) t))))
|
||||||
|
|
||||||
|
(unless noninteractive
|
||||||
|
(add-hook 'after-init-hook #'syd-load-packages-incrementally-h 100))
|
||||||
|
|
||||||
|
(with-eval-after-load 'use-package-core
|
||||||
|
(push :defer-incrementally use-package-deferring-keywords)
|
||||||
|
(setq use-package-keywords (use-package-list-insert
|
||||||
|
:defer-incrementally use-package-keywords :after))
|
||||||
|
(defalias 'use-package-normalize/:defer-incrementally
|
||||||
|
#'use-package-normalize-symlist)
|
||||||
|
(defun use-package-handler/:defer-incrementally
|
||||||
|
(name _keyword targets rest state)
|
||||||
|
(use-package-concat
|
||||||
|
`((syd-load-packages-incrementally
|
||||||
|
',(if (equal targets '(t))
|
||||||
|
(list name)
|
||||||
|
(append targets (list name)))))
|
||||||
|
(use-package-process-keywords name rest state))))
|
||||||
|
|
||||||
|
;; Set `:ensure t` by default.
|
||||||
|
(require 'use-package-ensure)
|
||||||
|
(setq use-package-always-ensure t)
|
||||||
|
|
||||||
|
(provide 'syd/init/use-package)
|
||||||
111
modules/home/users/msyds/emacs/lisp/syd/init/15-general.el
Normal file
111
modules/home/users/msyds/emacs/lisp/syd/init/15-general.el
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(use-package general
|
||||||
|
:custom (general-use-package-emit-autoloads t)
|
||||||
|
:ensure (:wait t))
|
||||||
|
|
||||||
|
(require 'general)
|
||||||
|
|
||||||
|
(defvar syd-leader-key "SPC"
|
||||||
|
"A prefix key akin to Vim's <Leader>.")
|
||||||
|
|
||||||
|
(defvar syd-localleader-key "SPC m"
|
||||||
|
"A prefix key akin to Vim's <LocalLeader>.")
|
||||||
|
|
||||||
|
(defvar syd-alt-leader-key "M-SPC"
|
||||||
|
"`syd-leader', but for the states specified in `syd-alt-leader-key-states'.
|
||||||
|
|
||||||
|
Often, your \"usual\" leader key will be something unavailable in the Insert
|
||||||
|
state. This key exists as a fallback for when you need your Leader, but must
|
||||||
|
remain in the Insert state. Substitute \"Insert state\" for your states of
|
||||||
|
choice with `syd-alt-leader-key-states'.")
|
||||||
|
|
||||||
|
(defvar syd-alt-localleader-key "M-SPC m"
|
||||||
|
"`syd-localleader', but for the states specified in `syd-alt-leader-key-states'.
|
||||||
|
|
||||||
|
See `syd-alt-leader-key' for rationale.")
|
||||||
|
|
||||||
|
(defvar syd-leader-key-states '(normal visual motion)
|
||||||
|
"States for which the Leader keys (`syd-leader-key', `syd-localleader-key')
|
||||||
|
are active.")
|
||||||
|
|
||||||
|
(defvar syd-alt-leader-key-states '(emacs insert)
|
||||||
|
"States for which the alternative Leader keys are active. See
|
||||||
|
`syd-alt-leader-key' and `syd-alt-localleader-key'.")
|
||||||
|
|
||||||
|
(defvar-keymap syd-leader-map
|
||||||
|
:doc "Leader-prefixed commands")
|
||||||
|
|
||||||
|
(defun syd-initialise-leader ()
|
||||||
|
"Set up the (empty) keymap associated with `syd-leader-key',
|
||||||
|
`syd-localleader-key', `syd-alt-leader-key', and `syd-alt-localleader-key'."
|
||||||
|
(require 'evil)
|
||||||
|
;; Define `syd/leader' as a command corresponding to the prefix map
|
||||||
|
;; `syd-leader-map'.
|
||||||
|
(define-prefix-command 'syd/leader 'syd-leader-map)
|
||||||
|
;; This should help make the Leader key close to universally available.
|
||||||
|
;; Ideally, *nothing* takes precedence over Leader — it's an incredibly
|
||||||
|
;; important key!
|
||||||
|
;; https://github.com/noctuid/evil-guide?tab=readme-ov-file#undoprevent-overridingintercept-maps
|
||||||
|
;; See `evil-make-overriding-map'.
|
||||||
|
(define-key syd-leader-map [override-state] 'all)
|
||||||
|
;; Finally, we shall bind the damned keys. }:)
|
||||||
|
(let ((map general-override-mode-map))
|
||||||
|
(evil-define-key* syd-leader-key-states map (kbd syd-leader-key) 'syd/leader)
|
||||||
|
(evil-define-key* syd-alt-leader-key-states map (kbd syd-alt-leader-key) 'syd/leader))
|
||||||
|
(general-override-mode 1))
|
||||||
|
|
||||||
|
(defvar syd-escape-hook nil
|
||||||
|
"A hook run when C-g is pressed (or ESC in Evil's normal state).
|
||||||
|
|
||||||
|
More specifically, when `syd/escape' is pressed. If any hook returns non-nil,
|
||||||
|
all hooks after it are ignored.")
|
||||||
|
|
||||||
|
;;
|
||||||
|
;;; Universal, non-nuclear escape
|
||||||
|
|
||||||
|
;; `keyboard-quit' is too much of a nuclear option. I want ESC/C-g to
|
||||||
|
;; do-what-I-mean. It serves four purposes (in order):
|
||||||
|
;;
|
||||||
|
;; 1. Quit active states; e.g. highlights, searches, snippets, iedit,
|
||||||
|
;; multiple-cursors, recording macros, etc.
|
||||||
|
;; 2. Close popup windows remotely (if it is allowed to)
|
||||||
|
;; 3. Refresh buffer indicators, like diff-hl and flycheck
|
||||||
|
;; 4. Or fall back to `keyboard-quit'
|
||||||
|
;;
|
||||||
|
;; And it should do these things incrementally, rather than all at once. And it
|
||||||
|
;; shouldn't interfere with recording macros or the minibuffer. This may
|
||||||
|
;; require you press ESC/C-g two or three times on some occasions to reach
|
||||||
|
;; `keyboard-quit', but this is much more intuitive.
|
||||||
|
|
||||||
|
(defun syd/escape (&optional interactive)
|
||||||
|
"Run `syd-escape-hook'."
|
||||||
|
(interactive (list 'interactive))
|
||||||
|
(let ((inhibit-quit t))
|
||||||
|
(cond ((minibuffer-window-active-p (minibuffer-window))
|
||||||
|
;; quit the minibuffer if open.
|
||||||
|
(when interactive
|
||||||
|
(setq this-command 'abort-recursive-edit))
|
||||||
|
(abort-recursive-edit))
|
||||||
|
;; Run all escape hooks. If any returns non-nil, then stop there.
|
||||||
|
((run-hook-with-args-until-success 'syd-escape-hook))
|
||||||
|
;; don't abort macros
|
||||||
|
((or defining-kbd-macro executing-kbd-macro) nil)
|
||||||
|
;; Back to the default
|
||||||
|
((unwind-protect (keyboard-quit)
|
||||||
|
(when interactive
|
||||||
|
(setq this-command 'keyboard-quit)))))))
|
||||||
|
|
||||||
|
(with-eval-after-load 'eldoc
|
||||||
|
(eldoc-add-command 'syd/escape))
|
||||||
|
|
||||||
|
;; In normal state, pressing escape should run `syd-escape-hook'.
|
||||||
|
(with-eval-after-load 'evil
|
||||||
|
(defun evil-syd/escape-a (&rest _)
|
||||||
|
"Call `syd/escape' if `evil-force-normal-state' is called interactively."
|
||||||
|
(when (called-interactively-p 'any)
|
||||||
|
(call-interactively #'syd/escape)))
|
||||||
|
(advice-add #'evil-force-normal-state
|
||||||
|
:after #'evil-syd/escape-a))
|
||||||
|
|
||||||
|
(provide 'syd/init/general)
|
||||||
176
modules/home/users/msyds/emacs/lisp/syd/init/20-prelude.el
Normal file
176
modules/home/users/msyds/emacs/lisp/syd/init/20-prelude.el
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(eval-when-compile (require 'cl-lib))
|
||||||
|
(use-package dash :ensure (:wait t))
|
||||||
|
(require 'dash)
|
||||||
|
|
||||||
|
(cl-defmacro syd-define-stub
|
||||||
|
(name &key (desc "implement me!") interactive)
|
||||||
|
(let ((todo (format "%s: TODO: %s" name desc)))
|
||||||
|
`(defun ,name (&rest _)
|
||||||
|
,@(if interactive (list '(interactive)) nil)
|
||||||
|
,todo
|
||||||
|
(error ,todo))))
|
||||||
|
|
||||||
|
;; FIXME: When `arg-list' contains nils, things break.
|
||||||
|
(cl-defun syd-parse-rest-and-keys (arg-list)
|
||||||
|
"The default behaviour of `cl-defun' makes combining &rest with &keys pretty
|
||||||
|
useless. This function will partition ARG-LIST by returning a pair (REST
|
||||||
|
. KEYS), where REST is the list of ARGS that belong to no key-value pair, and
|
||||||
|
KEYS is an alist of the parsed keywords."
|
||||||
|
;; Ugh.
|
||||||
|
(let (parsed-rest parsed-keys)
|
||||||
|
(cl-loop for (lead lag) on arg-list by (lambda (x) (-drop 2 x))
|
||||||
|
do (if (keywordp lead)
|
||||||
|
(push (cons lead lag) parsed-keys)
|
||||||
|
;; Push in reverse order; we reverse the whole list as a
|
||||||
|
;; post-processing step.
|
||||||
|
(push lead parsed-rest)
|
||||||
|
(when lag
|
||||||
|
(push lag parsed-rest))))
|
||||||
|
(cons (reverse parsed-rest) parsed-keys)))
|
||||||
|
|
||||||
|
(cl-defun syd-lift-lambdas (&key with-each with-all forms)
|
||||||
|
;; Call the continuation if non-nil. Wraps the return value in a singleton
|
||||||
|
;; list for "affine" use with unquote-splicing.
|
||||||
|
(-let ((call-cont (lambda (cont arg)
|
||||||
|
(if cont
|
||||||
|
(list (funcall cont arg))
|
||||||
|
nil)))
|
||||||
|
names)
|
||||||
|
`(progn
|
||||||
|
,@(cl-loop
|
||||||
|
for form in forms
|
||||||
|
appending (cond ((syd-hform-symbol form)
|
||||||
|
(let ((name (nth 1 form)))
|
||||||
|
(push name names)
|
||||||
|
(funcall call-cont with-each name)))
|
||||||
|
((syd-hform-defun form)
|
||||||
|
(let ((name (nth 1 form)))
|
||||||
|
(push name names)
|
||||||
|
`(,form
|
||||||
|
,@(funcall call-cont with-each name))))
|
||||||
|
((syd-hform-lambda form)
|
||||||
|
(let ((name (gensym "lifted-lambda")))
|
||||||
|
(push name names)
|
||||||
|
`((defun ,name (&rest args)
|
||||||
|
(,form args))
|
||||||
|
,@(funcall call-cont with-each name))))
|
||||||
|
(t (error "IDK!"))))
|
||||||
|
,@(funcall call-cont with-all names))))
|
||||||
|
|
||||||
|
(defun syd-hform-symbol (hform)
|
||||||
|
(and (listp hform)
|
||||||
|
(= 2 (length hform))
|
||||||
|
(symbolp (nth 1 hform))
|
||||||
|
(memq (nth 0 hform) '(quote function))))
|
||||||
|
|
||||||
|
(defun syd-hform-defun (hform)
|
||||||
|
"If HFORM is a defun form, return the defun's name. Otherwise, return nil"
|
||||||
|
(when-let* ((sym (car-safe hform)))
|
||||||
|
(and (symbolp sym)
|
||||||
|
(eq sym 'defun)
|
||||||
|
(nth 1 hform))))
|
||||||
|
|
||||||
|
(defun syd-hform-lambda (hform)
|
||||||
|
"If HFORM is a lambda, return non-nil."
|
||||||
|
(when-let* ((sym (car-safe hform)))
|
||||||
|
(and (symbolp sym)
|
||||||
|
(eq sym 'lambda))))
|
||||||
|
|
||||||
|
(defmacro comment (&rest _)
|
||||||
|
"Ignore each argument, and expand to nil."
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(defmacro with-transient-after (hook-or-function &rest forms)
|
||||||
|
(declare (indent defun))
|
||||||
|
(let ((hook-name (gensym "transient-hook"))
|
||||||
|
(hook-or-function* (gensym "hook-or-function")))
|
||||||
|
`(let* ((,hook-or-function* ,hook-or-function))
|
||||||
|
(defun ,hook-name (&rest _)
|
||||||
|
"Transient hook defined by `with-transient-after'."
|
||||||
|
(cond ((functionp ,hook-or-function*)
|
||||||
|
(advice-remove ,hook-or-function* #',hook-name))
|
||||||
|
((symbolp ,hook-or-function*)
|
||||||
|
(remove-hook ,hook-or-function* #',hook-name)))
|
||||||
|
,@forms)
|
||||||
|
(cond ((functionp ,hook-or-function*)
|
||||||
|
(advice-add ,hook-or-function* :before #',hook-name))
|
||||||
|
((symbolp ,hook-or-function*)
|
||||||
|
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Setting-Hooks.html#Setting-Hooks-1
|
||||||
|
(put ',hook-name 'permanent-local-hook t)
|
||||||
|
(add-hook ,hook-or-function* #',hook-name))))))
|
||||||
|
|
||||||
|
(defun syd-plist-put (plist prop new-val)
|
||||||
|
"Immutably update a single property of PLIST. Like `plist-put', but PLIST is
|
||||||
|
not mutated; a new plist is returned."
|
||||||
|
(cl-loop for (prop* old-val) on plist by #'cddr
|
||||||
|
appending (if (eq prop prop*)
|
||||||
|
(list prop* new-val)
|
||||||
|
(list prop* old-val))))
|
||||||
|
|
||||||
|
(defmacro syd-add-hook (hooks &rest hforms)
|
||||||
|
(declare (indent defun))
|
||||||
|
(syd-lift-lambdas
|
||||||
|
:forms hforms
|
||||||
|
:with-all (lambda (fns)
|
||||||
|
(let ((fn* (gensym "fn"))
|
||||||
|
(fns* (gensym "fns"))
|
||||||
|
(hook* (gensym "hook")))
|
||||||
|
`(let ((,fns* (list ,@(--map `(function ,it)
|
||||||
|
fns))))
|
||||||
|
(dolist (,hook* (ensure-list ,hooks))
|
||||||
|
(dolist (,fn* ,fns*)
|
||||||
|
(add-hook ,hook* ,fn*))))))))
|
||||||
|
|
||||||
|
(defmacro syd-silently (&rest body)
|
||||||
|
`(error "TODO: syd-silently"))
|
||||||
|
|
||||||
|
(defmacro syd-quietly (&rest body)
|
||||||
|
"Evaluate BODY without generating any output.
|
||||||
|
|
||||||
|
This silences calls to `message', `load', `write-region' and anything that
|
||||||
|
writes to `standard-output'. In interactive sessions this inhibits output to
|
||||||
|
the echo-area, but not to *Messages*. Return value is that of BODY's final
|
||||||
|
form."
|
||||||
|
`(if init-file-debug
|
||||||
|
(progn ,@body)
|
||||||
|
,(if noninteractive
|
||||||
|
`(syd-silently ,@body)
|
||||||
|
`(let ((inhibit-message t)
|
||||||
|
(save-silently t))
|
||||||
|
(prog1 (progn ,@body)
|
||||||
|
(message ""))))))
|
||||||
|
|
||||||
|
(defun syd--parse-defadvice-args (arg-list)
|
||||||
|
"Parses the docstring and keywords provided to `syd-defadvice'."
|
||||||
|
(let (docstring
|
||||||
|
advice)
|
||||||
|
(when (stringp (car-safe arg-list))
|
||||||
|
(setq docstring (pop arg-list)))
|
||||||
|
(while (and (length> arg-list 2)
|
||||||
|
(keywordp (car arg-list)))
|
||||||
|
(let ((how (pop arg-list))
|
||||||
|
(sym (pop arg-list)))
|
||||||
|
(push (cons how sym) advice)))
|
||||||
|
;; What's left of `arg-list' is the body of the defun.
|
||||||
|
(list docstring advice arg-list)))
|
||||||
|
|
||||||
|
(defmacro syd-defadvice (name params &rest args)
|
||||||
|
"Define a function and add it as advice."
|
||||||
|
(declare (indent defun))
|
||||||
|
(-let (((docstring advice body) (syd--parse-defadvice-args args)))
|
||||||
|
`(progn (defun ,name ,params
|
||||||
|
,@(-some-> docstring list)
|
||||||
|
,@body)
|
||||||
|
,@(-map (lambda (arg)
|
||||||
|
(-let (((how . sym) arg))
|
||||||
|
`(advice-add ,sym ,how #',name)))
|
||||||
|
advice))))
|
||||||
|
|
||||||
|
;; (syd-defadvice syd-lsp-install-server-a ()
|
||||||
|
;; :override #'lsp-install-server
|
||||||
|
;; (user-error (concat "Ignoring a call to `lsp-install-server'"
|
||||||
|
;; " — tell the caller to use Nix!")))
|
||||||
|
|
||||||
|
(provide 'syd/init/prelude)
|
||||||
358
modules/home/users/msyds/emacs/lisp/syd/init/40-evil.el
Normal file
358
modules/home/users/msyds/emacs/lisp/syd/init/40-evil.el
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;;; syd-evil.el -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; More sensible undo functionality. Emacs' default is very weird, not
|
||||||
|
;; maintaining a proper history.
|
||||||
|
;; (use-package undo-fu)
|
||||||
|
|
||||||
|
;; Vim emulation.
|
||||||
|
(use-package evil
|
||||||
|
:preface
|
||||||
|
(setq evil-want-minibuffer t
|
||||||
|
evil-move-beyond-eol t
|
||||||
|
evil-respect-visual-line-mode t
|
||||||
|
evil-vsplit-window-right t
|
||||||
|
evil-ex-search-vim-style-regexp t
|
||||||
|
evil-want-Y-yank-to-eol t
|
||||||
|
evil-want-C-u-scroll t
|
||||||
|
evil-want-C-w-in-emacs-state t
|
||||||
|
;; - If non-nil: When using ex commands on a visual selection, pass the
|
||||||
|
;; precise region selected to the command.
|
||||||
|
;; - If nil: Pass the region of /lines/ spanned by the visual selection.
|
||||||
|
evil-ex-visual-char-range t
|
||||||
|
evil-v$-excludes-newline t
|
||||||
|
;; Don't display the state in the mode line.
|
||||||
|
evil-mode-line-format nil
|
||||||
|
evil-normal-state-cursor 'box
|
||||||
|
evil-emacs-state-cursor 'hbar
|
||||||
|
evil-operator-state-cursor 'evil-half-cursor
|
||||||
|
evil-insert-state-cursor 'bar
|
||||||
|
evil-visual-state-cursor 'hollow
|
||||||
|
;; Only do highlighting in selected window so that Emacs has less work
|
||||||
|
;; to do highlighting them all.
|
||||||
|
evil-ex-interactive-search-highlight 'selected-window
|
||||||
|
;; It's infuriating that innocuous "beginning of line" or "end of line"
|
||||||
|
;; errors will abort macros, so we suppress them:
|
||||||
|
evil-kbd-macro-suppress-motion-error t
|
||||||
|
evil-undo-system (cond ((featurep 'undo-tree) 'undo-tree)
|
||||||
|
((featurep 'undo-fu) 'undo-fu)))
|
||||||
|
;; These two are required for evil-collection.
|
||||||
|
(setq evil-want-keybinding nil
|
||||||
|
evil-want-integration t)
|
||||||
|
|
||||||
|
:config
|
||||||
|
;; 'M-:' starts off in insert mode, yet the normal mode cursor lingers until a
|
||||||
|
;; refresh is forced. Quick fix! }:P
|
||||||
|
(add-hook 'minibuffer-setup-hook #'evil-refresh-cursor)
|
||||||
|
|
||||||
|
;; Unbind 'C-k'. Normally, it inserts digraphs; I have a compose key, and
|
||||||
|
;; it's strictly less useful than Emacs' native input methods. It often gets
|
||||||
|
;; in the way of buffers with navigation, e.g. scrolling through shell/REPL
|
||||||
|
;; history, navigating Vertico completions, etc.
|
||||||
|
(keymap-set evil-insert-state-map "C-k" nil)
|
||||||
|
|
||||||
|
;; In imitation of Vim's :mes[sages] command, define an Evil analogue to show
|
||||||
|
;; the echo area.
|
||||||
|
(defun syd-evil-messages ()
|
||||||
|
(interactive)
|
||||||
|
(view-echo-area-messages)
|
||||||
|
(with-current-buffer messages-buffer-name
|
||||||
|
(evil-motion-state 1)))
|
||||||
|
(evil-ex-define-cmd "mes[sages]" #'syd-evil-messages)
|
||||||
|
|
||||||
|
;; On ESC, remove highlighted search results.
|
||||||
|
(defun syd-evil-nohl-h ()
|
||||||
|
"If any Evil Ex search highlightings are active, remove them and return t.
|
||||||
|
Otherwise, nil."
|
||||||
|
(let ((names '(evil-ex-substitute evil-ex-search)))
|
||||||
|
(when (-any #'evil-ex-hl-active-p names)
|
||||||
|
(prog1 t (evil-ex-nohighlight)))))
|
||||||
|
(add-hook 'syd-escape-hook #'syd-evil-nohl-h)
|
||||||
|
|
||||||
|
(general-def
|
||||||
|
:states 'motion
|
||||||
|
"/" #'evil-ex-search-forward
|
||||||
|
"?" #'evil-ex-search-backward
|
||||||
|
"n" #'evil-ex-search-next
|
||||||
|
"N" #'evil-ex-search-previous
|
||||||
|
"*" #'evil-ex-search-word-forward)
|
||||||
|
|
||||||
|
(evil-mode 1))
|
||||||
|
|
||||||
|
;; A large, community-sourced collection of preconfigured Evil-mode
|
||||||
|
;; integrations.
|
||||||
|
(use-package evil-collection
|
||||||
|
:custom (evil-collection-setup-minibuffer t)
|
||||||
|
:preface
|
||||||
|
(defvar evil-collection-key-blacklist)
|
||||||
|
(unless noninteractive
|
||||||
|
(defvar syd-evil-collection-disabled-list
|
||||||
|
'(anaconda-mode buff-menu calc comint company custom eldoc elisp-mode ert
|
||||||
|
free-keys helm help image indent kmacro kotlin-mode lispy outline
|
||||||
|
replace shortdoc simple slime tab-bar)
|
||||||
|
"A list of `evil-collection' modules to ignore. See
|
||||||
|
`evil-collection-mode-list' for a list of available options.")
|
||||||
|
|
||||||
|
;; We do this ourselves.
|
||||||
|
(defvar evil-collection-want-unimpaired-p nil)
|
||||||
|
;; We binds goto-reference on gD and goto-assignments on gA ourselves
|
||||||
|
(defvar evil-collection-want-find-usages-bindings-p nil)
|
||||||
|
;; Reduces keybind conflicts between outline-mode and org-mode (which is
|
||||||
|
;; derived from outline-mode).
|
||||||
|
(defvar evil-collection-outline-enable-in-minor-mode-p nil)
|
||||||
|
;; We handle loading evil-collection ourselves
|
||||||
|
(defvar evil-collection--supported-modes nil)
|
||||||
|
;; This has to be defined here since evil-collection doesn't autoload its own.
|
||||||
|
;; It must be updated whenever evil-collection updates theirs.
|
||||||
|
(defvar evil-collection-mode-list
|
||||||
|
`(2048-game ag alchemist anaconda-mode apropos arc-mode atomic-chrome
|
||||||
|
auto-package-update beginend bluetooth bm bookmark
|
||||||
|
(buff-menu "buff-menu") bufler calc calendar cider citre cmake-mode
|
||||||
|
color-rg comint company compile consult corfu crdt (csv "csv-mode")
|
||||||
|
(custom cus-edit) cus-theme dape dashboard daemons deadgrep debbugs
|
||||||
|
debug devdocs dictionary diff-hl diff-mode dired dired-sidebar
|
||||||
|
disk-usage distel doc-view docker eat ebib ebuku edbi edebug ediff eglot
|
||||||
|
elpaca ement explain-pause-mode eldoc elfeed elisp-mode elisp-refs
|
||||||
|
elisp-slime-nav embark emms ,@(if (> emacs-major-version 28) '(emoji))
|
||||||
|
epa ert eshell eval-sexp-fu evil-mc eww fanyi finder flycheck flymake
|
||||||
|
forge free-keys geiser ggtags git-timemachine gited gnus go-mode gptel
|
||||||
|
grep guix hackernews helm help helpful hg-histedit hungry-delete hyrolo
|
||||||
|
ibuffer (image image-mode) image-dired image+ imenu imenu-list
|
||||||
|
(indent "indent") indium info ivy js2-mode
|
||||||
|
,@(if (>= emacs-major-version 30) '(kmacro)) leetcode lispy lms log-edit
|
||||||
|
log-view lsp-ui-imenu lua-mode kotlin-mode macrostep man
|
||||||
|
(magit magit-repos magit-submodule) magit-repos magit-section
|
||||||
|
magit-todos markdown-mode monky mpc mpdel mu4e mu4e-conversation neotree
|
||||||
|
newsticker notmuch nov omnisharp org org-present org-roam osx-dictionary
|
||||||
|
outline p4 (package-menu package) pass (pdf pdf-tools) popup proced
|
||||||
|
prodigy profiler p-search python quickrun racer racket-describe realgud
|
||||||
|
reftex replace restclient rg ripgrep rjsx-mode robe rtags ruby-mode
|
||||||
|
scheme scroll-lock selectrum sh-script
|
||||||
|
,@(if (> emacs-major-version 27) '(shortdoc)) simple simple-mpc slime
|
||||||
|
sly smerge-mode snake so-long speedbar tab-bar tablist tar-mode telega
|
||||||
|
(term term ansi-term multi-term) tetris thread tide timer-list
|
||||||
|
transmission trashed tuareg typescript-mode vc-annotate vc-dir vc-git
|
||||||
|
vdiff vertico view vlf vterm vundo w3m wdired wgrep which-key
|
||||||
|
with-editor woman xref xwidget yaml-mode youtube-dl zmusic
|
||||||
|
(ztree ztree-diff)))
|
||||||
|
|
||||||
|
(cl-defun syd-evil-collection-init (module &key disabled-modules)
|
||||||
|
"Initialise evil-collection-MODULE.
|
||||||
|
|
||||||
|
A wrapper for `evil-collection-init' that respects a given list of disabled
|
||||||
|
modules."
|
||||||
|
(let ((module* (or (car-safe module) module)))
|
||||||
|
(unless (memq module* disabled-modules)
|
||||||
|
(message "Loading evil-collection-%s%s"
|
||||||
|
module*
|
||||||
|
(if after-init-time "" " too early! }:("))
|
||||||
|
(with-demoted-errors "error loading evil-collection: %s"
|
||||||
|
(evil-collection-init (list module))))))
|
||||||
|
|
||||||
|
;; Allow binding to ESC.
|
||||||
|
(syd-defadvice syd-evil-collection-disable-blacklist-a (fn)
|
||||||
|
:around #'evil-collection-vterm-toggle-send-escape
|
||||||
|
(let (evil-collection-key-blacklist)
|
||||||
|
(funcall-interactively fn)))
|
||||||
|
|
||||||
|
;; These modes belong to packages that Emacs always loads at startup, causing
|
||||||
|
;; evil-collection and it's co-packages to all load immediately. We avoid
|
||||||
|
;; this by loading them after evil-collection has first loaded...
|
||||||
|
(with-eval-after-load 'evil-collection
|
||||||
|
;; Don't let evil-collection interfere with certain keys
|
||||||
|
(setq evil-collection-key-blacklist
|
||||||
|
(append (list syd-leader-key syd-localleader-key
|
||||||
|
syd-alt-leader-key)
|
||||||
|
evil-collection-key-blacklist
|
||||||
|
;; Reserved for goto definition; lookup docs; eval; eval
|
||||||
|
;; buffer; movement prefix; movement prefix; escaping };).
|
||||||
|
'("gd" "K" "gr" "gR" "[" "]" "<escape>")))
|
||||||
|
|
||||||
|
(mapc #'syd-evil-collection-init '(comint custom))
|
||||||
|
|
||||||
|
(with-eval-after-load 'evil
|
||||||
|
;; Emacs loads these two packages immediately, at startup, which needlessly
|
||||||
|
;; convolutes load order for evil-collection-help.
|
||||||
|
(with-transient-after 'help-mode
|
||||||
|
(syd-evil-collection-init 'help))
|
||||||
|
(with-transient-after 'Buffer-menu-mode
|
||||||
|
(syd-evil-collection-init '(buff-menu "buff-menu")))
|
||||||
|
(with-transient-after 'calc-mode
|
||||||
|
(syd-evil-collection-init 'calc))
|
||||||
|
(with-transient-after 'image-mode
|
||||||
|
(syd-evil-collection-init 'image))
|
||||||
|
(with-transient-after 'emacs-lisp-mode
|
||||||
|
(syd-evil-collection-init 'elisp-mode))
|
||||||
|
(with-transient-after 'occur-mode
|
||||||
|
(syd-evil-collection-init 'replace))
|
||||||
|
(with-transient-after 'indent-rigidly
|
||||||
|
(syd-evil-collection-init '(indent "indent")))
|
||||||
|
(when (>= emacs-major-version 30)
|
||||||
|
(with-transient-after 'kmacro-menu-mode
|
||||||
|
(syd-evil-collection-init 'kmacro)))
|
||||||
|
(with-transient-after 'minibuffer-setup-hook
|
||||||
|
(when evil-collection-setup-minibuffer
|
||||||
|
(syd-evil-collection-init 'minibuffer)
|
||||||
|
(evil-collection-minibuffer-insert)))
|
||||||
|
(with-transient-after 'process-menu-mode
|
||||||
|
(syd-evil-collection-init '(process-menu simple)))
|
||||||
|
(with-transient-after 'shortdoc-mode
|
||||||
|
(syd-evil-collection-init 'shortdoc))
|
||||||
|
(with-transient-after 'tabulated-list-mode
|
||||||
|
(syd-evil-collection-init 'tabulated-list))
|
||||||
|
(with-transient-after 'tab-bar-mode
|
||||||
|
(syd-evil-collection-init 'tab-bar))
|
||||||
|
|
||||||
|
;; HACK: Do this ourselves because evil-collection break's
|
||||||
|
;; `eval-after-load' load order by loading their target plugin before
|
||||||
|
;; applying keys. This makes it hard for end-users to overwrite these
|
||||||
|
;; keybinds with a simple `after!' or `with-eval-after-load'.
|
||||||
|
(dolist (mode evil-collection-mode-list)
|
||||||
|
(dolist (req (or (cdr-safe mode) (list mode)))
|
||||||
|
(with-eval-after-load req
|
||||||
|
(syd-evil-collection-init
|
||||||
|
mode
|
||||||
|
:disabled-modules syd-evil-collection-disabled-list))))))))
|
||||||
|
|
||||||
|
;; Tim Pope's famous `surround.vim' for Evil.
|
||||||
|
(use-package evil-surround
|
||||||
|
:commands (global-evil-surround-mode
|
||||||
|
evil-surround-edit
|
||||||
|
evil-Surround-edit
|
||||||
|
evil-surround-region)
|
||||||
|
:hook (on-first-input . global-evil-surround-mode))
|
||||||
|
|
||||||
|
;; TODO: I'd like JK to escape visual state. evil-escape only allows defining a
|
||||||
|
;; single key sequence. Perhaps key-chord is capable of this?
|
||||||
|
(use-package evil-escape
|
||||||
|
:hook (on-first-input . evil-escape-mode)
|
||||||
|
:custom ((evil-escape-key-sequence "jk")
|
||||||
|
(evil-escape-excluded-states '(normal visual multiedit emacs motion))
|
||||||
|
(evil-escape-delay 0.15)))
|
||||||
|
|
||||||
|
;; `evil-nerd-commenter' has a bunch of cool functions[1]. Here, only the Evil
|
||||||
|
;; operator is used. }:3
|
||||||
|
;; [1]: https://github.com/redguardtoo/evil-nerd-commenter?tab=readme-ov-file#commands-and-hotkeys
|
||||||
|
(use-package evil-nerd-commenter
|
||||||
|
:commands (evilnc-comment-operator
|
||||||
|
evilnc-inner-comment
|
||||||
|
evilnc-outer-commenter)
|
||||||
|
:defer t
|
||||||
|
:bind (:map evil-normal-state-map ("#" . evilnc-comment-operator)
|
||||||
|
:map evil-visual-state-map ("#" . evilnc-comment-operator)
|
||||||
|
:map evil-inner-text-objects-map ("c" . evilnc-inner-comment)
|
||||||
|
:map evil-outer-text-objects-map ("c" . evilnc-outer-comment)))
|
||||||
|
|
||||||
|
;; Enhance `evil-surround' with integration with `embrace'.
|
||||||
|
(use-package evil-embrace
|
||||||
|
:disabled
|
||||||
|
:after evil-surround
|
||||||
|
:config
|
||||||
|
(evil-embrace-enable-evil-surround-integration))
|
||||||
|
|
||||||
|
;; Provides an Evil operator to swap two spans of text.
|
||||||
|
(use-package evil-exchange
|
||||||
|
:bind (:map evil-normal-state-map ("gX" . evil-exchange)
|
||||||
|
:map evil-visual-state-map ("gX" . evil-exchange)))
|
||||||
|
|
||||||
|
;; Evil doesn't ship with support for Vim's 'g-'/'g+'. `evil-numbers'
|
||||||
|
;; implements this.
|
||||||
|
(use-package evil-numbers
|
||||||
|
;; 'g=' is a bit more comfortable than 'g+', whilst preserving the analogy.
|
||||||
|
;; ('=' is '+' modulo shift)
|
||||||
|
:bind (:map evil-normal-state-map ("g=" . 'evil-numbers/inc-at-pt)
|
||||||
|
:map evil-normal-state-map ("g-" . 'evil-numbers/dec-at-pt))
|
||||||
|
:defer t)
|
||||||
|
|
||||||
|
;; Tree-sitter queries → Evil text objects.
|
||||||
|
(use-package evil-textobj-tree-sitter
|
||||||
|
:defer t)
|
||||||
|
|
||||||
|
;; Visually "flash" the region acted upon by Evil-mode operations.
|
||||||
|
(use-package evil-goggles
|
||||||
|
:hook (on-first-input . evil-goggles-mode)
|
||||||
|
;; The flash animation will delay actions, which can be very annoying for some
|
||||||
|
;; operations. Disable `evil-goggles' for those ones.
|
||||||
|
:custom
|
||||||
|
((evil-goggles-enable-delete nil)
|
||||||
|
(evil-goggles-enable-change nil)
|
||||||
|
(evil-goggles-duration 0.1)))
|
||||||
|
|
||||||
|
;; Change cursor shape and color by evil state in terminal.
|
||||||
|
(use-package evil-terminal-cursor-changer
|
||||||
|
;; This package is only useful in the terminal.
|
||||||
|
:if (not (display-graphic-p))
|
||||||
|
:defer t
|
||||||
|
:hook (on-first-input . evil-terminal-cursor-changer-activate))
|
||||||
|
|
||||||
|
;; Automatic alignment in region, by regexp.
|
||||||
|
(use-package evil-lion
|
||||||
|
:hook (on-first-input . evil-lion-mode))
|
||||||
|
|
||||||
|
;; 'g' text object selecting the entire buffer.
|
||||||
|
(with-eval-after-load 'evil
|
||||||
|
(evil-define-text-object
|
||||||
|
evil-entire-buffer (count &optional beg end type)
|
||||||
|
"Select entire buffer"
|
||||||
|
(evil-range (point-min) (point-max) type))
|
||||||
|
(define-key evil-inner-text-objects-map "g" #'evil-entire-buffer)
|
||||||
|
(define-key evil-outer-text-objects-map "g" #'evil-entire-buffer))
|
||||||
|
|
||||||
|
;; 2-character search.
|
||||||
|
(use-package evil-snipe
|
||||||
|
:commands (evil-snipe-local-mode evil-snipe-override-local-mode)
|
||||||
|
:hook ((on-first-input . evil-snipe-override-mode)
|
||||||
|
;; (on-first-input . evil-snipe-mode)
|
||||||
|
)
|
||||||
|
:custom ((evil-snipe-smart-case t)
|
||||||
|
(evil-snipe-scope 'visible)
|
||||||
|
(evil-snipe-repeat-scope 'visible)
|
||||||
|
(evil-snipe-char-fold t)))
|
||||||
|
|
||||||
|
;; Evil's default behaviour for '#'/'*' in visual state will remain in visual
|
||||||
|
;; mode, and jump to the next occurence of the symbol under point. That is, the
|
||||||
|
;; movement is exactly the same as it is in normal state; if the region is over
|
||||||
|
;; the text `two words`, but the point is over `two`, Evil will search for
|
||||||
|
;; `two`. `evil-visualstar' will instead search for `two words`.
|
||||||
|
(use-package evil-visualstar
|
||||||
|
:defer t
|
||||||
|
:bind (:map evil-visual-state-map
|
||||||
|
("*" . evil-visualstar/begin-search-forward)))
|
||||||
|
|
||||||
|
(defvar syd-evil-last-eval-expression-register ?e
|
||||||
|
"An Evil-mode register in which the last expression evaluated with an
|
||||||
|
interactive call to `eval-expression' is stored.")
|
||||||
|
|
||||||
|
(with-eval-after-load 'evil
|
||||||
|
(defun syd-set-eval-expression-register-a (expr &rest _)
|
||||||
|
"If called interactively, set the register
|
||||||
|
`syd-evil-last-eval-expression-register' to a printed form of EXPR."
|
||||||
|
(when (called-interactively-p 'interactive)
|
||||||
|
(->> (pp-to-string expr)
|
||||||
|
(string-remove-suffix "\n")
|
||||||
|
(evil-set-register syd-evil-last-eval-expression-register))))
|
||||||
|
(advice-add #'eval-expression
|
||||||
|
:after #'syd-set-eval-expression-register-a))
|
||||||
|
|
||||||
|
;; HACK: '=' unpredictably moves the cursor when it really doesn't need to.
|
||||||
|
(defun syd-evil-dont-move-point-a (fn &rest args)
|
||||||
|
"Used as :around advice on Evil operators to avoid moving the point."
|
||||||
|
;; We don't use `save-excursion', as we /only/ want to restore the point.
|
||||||
|
(save-excursion (apply fn args)))
|
||||||
|
|
||||||
|
(with-eval-after-load 'evil
|
||||||
|
(advice-add #'evil-indent
|
||||||
|
:around #'syd-evil-dont-move-point-a))
|
||||||
|
|
||||||
|
;(use-package evil-leap
|
||||||
|
; :hook (on-first-input . evil-leap-mode)
|
||||||
|
; :load-path "/home/crumb/src/evil-leap"
|
||||||
|
; :straight nil
|
||||||
|
; ;; :straight (:type git
|
||||||
|
; ;; :host gitlab
|
||||||
|
; ;; :repo "msyds/evil-leap")
|
||||||
|
; :config
|
||||||
|
; (evil-leap-install-default-keybindings))
|
||||||
|
|
||||||
|
(provide 'syd/init/evil)
|
||||||
24
modules/home/users/msyds/emacs/lisp/syd/init/50-comint.el
Normal file
24
modules/home/users/msyds/emacs/lisp/syd/init/50-comint.el
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(with-eval-after-load 'comint
|
||||||
|
(require 'syd/kanagawa)
|
||||||
|
(custom-theme-set-faces
|
||||||
|
'user
|
||||||
|
;; Default prompt face is very ugly. Give it a more subtle look.
|
||||||
|
`(comint-highlight-prompt
|
||||||
|
((t :foreground ,(syd-kanagawa-get 'old-white)
|
||||||
|
:background unspecified
|
||||||
|
:weight bold))))
|
||||||
|
|
||||||
|
(general-def
|
||||||
|
:keymaps 'comint-mode-map
|
||||||
|
:states '(normal insert)
|
||||||
|
"C-k" #'comint-previous-input
|
||||||
|
"C-j" #'comint-next-input
|
||||||
|
"C-s" #'consult-history)
|
||||||
|
(general-def
|
||||||
|
:keymaps 'comint-mode-map
|
||||||
|
:states 'insert
|
||||||
|
"C-d" #'comint-delchar-or-maybe-eof))
|
||||||
|
|
||||||
|
(provide 'syd/init/comint)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(defun syd-configure-default-frame-h ()
|
||||||
|
"Customise the default frame, primarily by adding to `default-frame-alist'."
|
||||||
|
;; Maximise the frame.
|
||||||
|
;; (add-to-list 'default-frame-alist '(fullscreen . maximized))
|
||||||
|
;; Disable the titlebar and borders (decorations).
|
||||||
|
(add-to-list 'default-frame-alist '(undecorated . t)))
|
||||||
|
|
||||||
|
(let ((hook (if (daemonp)
|
||||||
|
'server-after-make-frame-hook
|
||||||
|
'after-init-hook)))
|
||||||
|
(add-hook hook #'syd-configure-default-frame-h))
|
||||||
|
|
||||||
|
(provide 'syd/init/default-frame)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
(with-eval-after-load 'evil-surround
|
||||||
|
;; In Elisp, `' is a much more common pair than ``.
|
||||||
|
(add-hook 'emacs-lisp-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
(push '(?` . ("`" . "'")) evil-surround-pairs-alist))))
|
||||||
35
modules/home/users/msyds/emacs/lisp/syd/init/50-fonts.el
Normal file
35
modules/home/users/msyds/emacs/lisp/syd/init/50-fonts.el
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(defvar syd-fixed-pitch-font
|
||||||
|
(font-spec :family "VictorMono Nerd Font" :size 13)
|
||||||
|
"Default fixed-pitch (monospace) font.")
|
||||||
|
|
||||||
|
(defvar syd-variable-pitch-font
|
||||||
|
(font-spec :family "IBM Plex Serif" :size 15)
|
||||||
|
"Default variable-pitch font.")
|
||||||
|
|
||||||
|
(defvar syd-alt-fixed-pitch-font
|
||||||
|
(font-spec :family "JuliaMono" :size 16)
|
||||||
|
"A monospace font secondary to `syd-fixed-pitch-font'.")
|
||||||
|
|
||||||
|
(defun syd-init-fonts-h ()
|
||||||
|
"Loads `syd-fixed-pitch-font' and `syd-variable-pitch-font'."
|
||||||
|
(dolist (map `((default . ,syd-fixed-pitch-font)
|
||||||
|
(fixed-pitch . ,syd-fixed-pitch-font)
|
||||||
|
(variable-pitch . ,syd-variable-pitch-font)))
|
||||||
|
(pcase-let ((`(,face . ,font) map))
|
||||||
|
(set-face-attribute face nil
|
||||||
|
:width 'normal :weight 'normal
|
||||||
|
:slant 'normal :font font))))
|
||||||
|
|
||||||
|
(let ((hook (if (daemonp)
|
||||||
|
'server-after-make-frame-hook
|
||||||
|
'after-init-hook)))
|
||||||
|
(add-hook hook #'syd-init-fonts-h))
|
||||||
|
|
||||||
|
;; Use JuliaMono as a fallback for some glyphs that VictorMono does not cover.
|
||||||
|
(dolist (char-range '((#x0250 . #x02af) ; IPA extensions
|
||||||
|
(#x2200 . #x22FF))) ; Mathematical operators
|
||||||
|
(set-fontset-font "fontset-default" char-range "JuliaMono"))
|
||||||
|
|
||||||
|
(provide 'syd/init/fonts)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
;;; syd-ui.el -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(use-package kanagawa-themes
|
||||||
|
:config
|
||||||
|
(load-theme 'kanagawa-wave t))
|
||||||
|
|
||||||
|
(provide 'syd/init/kanagawa)
|
||||||
44
modules/home/users/msyds/emacs/lisp/syd/init/50-ui.el
Normal file
44
modules/home/users/msyds/emacs/lisp/syd/init/50-ui.el
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(syd-add-hook 'prog-mode-hook
|
||||||
|
;; Display (relative) line numbers only in prog-mode derivatives.
|
||||||
|
(defun syd-prog-mode-line-numbers-h ()
|
||||||
|
(display-line-numbers-mode 1)))
|
||||||
|
|
||||||
|
(setq display-line-numbers-type 'relative
|
||||||
|
;; Always ask "y/n"; never "yes/no".
|
||||||
|
use-short-answers t
|
||||||
|
;; Scroll compilation buffer to follow output.
|
||||||
|
compilation-scroll-output t
|
||||||
|
;; Allow `fit-window-to-buffer' to make horizontal adjustments.
|
||||||
|
fit-window-to-buffer-horizontally t
|
||||||
|
;; I don't like that `grep' asks me to save unsaved files. It makes
|
||||||
|
;; me think it's about to kill my buffers.
|
||||||
|
grep-save-buffers nil
|
||||||
|
;; The default value is `ask', meaning that Emacs will ask for
|
||||||
|
;; confirmation any time you follow a symlink to a file under version
|
||||||
|
;; control. The documentation claims this is "dangerous, and
|
||||||
|
;; probably not what you want;" I personally don't see it, and it's
|
||||||
|
;; usually what I want.
|
||||||
|
vc-follow-symlinks t
|
||||||
|
;; Log native-compiler warnings, but don't display the
|
||||||
|
;; buffer. Most of the warnings are "`X' is not known to
|
||||||
|
;; be defined" which are typically nothing worth concerning.
|
||||||
|
native-comp-async-report-warnings-errors 'silent
|
||||||
|
;; Don't recenter the view unless >10 lines are scrolled off-screen
|
||||||
|
;; in a single movement.
|
||||||
|
scroll-conservatively 10
|
||||||
|
;; In modes making use of `recenter-top-bottom' (e.g. Comint,
|
||||||
|
;; Eshell), this will make the command behave more like a plain old
|
||||||
|
;; `clear` invocation.
|
||||||
|
recenter-positions '(top))
|
||||||
|
|
||||||
|
;; Disable the menu bar, scroll bar, and tool bar.
|
||||||
|
(menu-bar-mode -1)
|
||||||
|
(scroll-bar-mode -1)
|
||||||
|
(tool-bar-mode -1)
|
||||||
|
|
||||||
|
;; Remember allowed risky variabled.
|
||||||
|
(advice-add 'risky-local-variable-p :override #'ignore)
|
||||||
|
|
||||||
|
(provide 'syd/init/ui)
|
||||||
133
modules/home/users/msyds/emacs/lisp/syd/kanagawa.el
Normal file
133
modules/home/users/msyds/emacs/lisp/syd/kanagawa.el
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
;;; -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;;; Rationale: I need direct access to the Kanagawa palette, which kanagawa.el
|
||||||
|
;;; does not provide.
|
||||||
|
|
||||||
|
(defvar syd-kanagawa-palette (make-hash-table :test 'eq :size 130))
|
||||||
|
|
||||||
|
(defvar syd-kanagawa-palette-list
|
||||||
|
'((sumi-ink-0 "#16161D")
|
||||||
|
(sumi-ink-1 "#181820")
|
||||||
|
(sumi-ink-2 "#1a1a22")
|
||||||
|
(sumi-ink-3 "#1F1F28")
|
||||||
|
(sumi-ink-4 "#2A2A37")
|
||||||
|
(sumi-ink-5 "#363646")
|
||||||
|
(sumi-ink-6 "#54546D") ; fg
|
||||||
|
|
||||||
|
;; Popup and Floats
|
||||||
|
(wave-blue-1 "#223249")
|
||||||
|
(wave-blue-2 "#2D4F67")
|
||||||
|
|
||||||
|
;; Diff and Git
|
||||||
|
(winter-green "#2B3328")
|
||||||
|
(winter-yellow "#49443C")
|
||||||
|
(winter-red "#43242B")
|
||||||
|
(winter-blue "#252535")
|
||||||
|
(autumn-green "#76946A")
|
||||||
|
(autumn-red "#C34043")
|
||||||
|
(autumn-yellow "#DCA561")
|
||||||
|
|
||||||
|
;; Diag
|
||||||
|
(samurai-red "#E82424")
|
||||||
|
(ronin-yellow "#FF9E3B")
|
||||||
|
(wave-aqua-1 "#6A9589")
|
||||||
|
(dragon-blue "#658594")
|
||||||
|
|
||||||
|
;; Fg and Comments
|
||||||
|
(old-white "#C8C093")
|
||||||
|
(fuji-white "#DCD7BA")
|
||||||
|
(fuji-gray "#727169")
|
||||||
|
|
||||||
|
(oni-violet "#957FB8")
|
||||||
|
(oni-violet-2 "#b8b4d0")
|
||||||
|
(crystal-blue "#7E9CD8")
|
||||||
|
(spring-violet-1 "#938AA9")
|
||||||
|
(spring-violet-2 "#9CABCA")
|
||||||
|
(spring-blue "#7FB4CA")
|
||||||
|
(light-blue "#A3D4D5")
|
||||||
|
(wave-aqua-2 "#7AA89F") ;; improve lightness: desaturated greenish Aqua
|
||||||
|
|
||||||
|
(spring-green "#98BB6C")
|
||||||
|
(boat-yellow-1 "#938056")
|
||||||
|
(boat-yellow-2 "#C0A36E")
|
||||||
|
(carp-yellow "#E6C384")
|
||||||
|
|
||||||
|
(sakura-pink "#D27E99")
|
||||||
|
(wave-red "#E46876")
|
||||||
|
(peach-red "#FF5D62")
|
||||||
|
(surimi-orange "#FFA066")
|
||||||
|
(katana-gray "#717C7C")
|
||||||
|
|
||||||
|
(dragon-black-0 "#0d0c0c")
|
||||||
|
(dragon-black-1 "#12120f")
|
||||||
|
(dragon-black-2 "#1D1C19")
|
||||||
|
(dragon-black-3 "#181616")
|
||||||
|
(dragon-black-4 "#282727")
|
||||||
|
(dragon-black-5 "#393836")
|
||||||
|
(dragon-black-6 "#625e5a")
|
||||||
|
|
||||||
|
(dragon-white "#c5c9c5")
|
||||||
|
(dragon-green "#87a987")
|
||||||
|
(dragon-green-2 "#8a9a7b")
|
||||||
|
(dragon-pink "#a292a3")
|
||||||
|
(dragon-orange "#b6927b")
|
||||||
|
(dragon-orange-2 "#b98d7b")
|
||||||
|
(dragon-gray "#a6a69c")
|
||||||
|
(dragon-gray1 "#9e9b93")
|
||||||
|
(dragon-gray-3 "#7a8382")
|
||||||
|
(dragon-blue-2 "#8ba4b0")
|
||||||
|
(dragon-violet "#8992a7")
|
||||||
|
(dragon-red "#c4746e")
|
||||||
|
(dragon-aqua "#8ea4a2")
|
||||||
|
(dragon-ash "#737c73")
|
||||||
|
(dragon-teal "#949fb5")
|
||||||
|
(dragon-yellow "#c4b28a")
|
||||||
|
|
||||||
|
(lotus-ink-1 "#545464")
|
||||||
|
(lotus-ink-2 "#43436c")
|
||||||
|
(lotus-gray "#dcd7ba")
|
||||||
|
(lotus-gray-2 "#716e61")
|
||||||
|
(lotus-gray-3 "#8a8980")
|
||||||
|
(lotus-white-0 "#d5cea3")
|
||||||
|
(lotus-white-1 "#dcd5ac")
|
||||||
|
(lotus-white-2 "#e5ddb0")
|
||||||
|
(lotus-white-3 "#f2ecbc")
|
||||||
|
(lotus-white-4 "#e7dba0")
|
||||||
|
(lotus-white-5 "#e4d794")
|
||||||
|
(lotus-violet-1 "#a09cac")
|
||||||
|
(lotus-violet-2 "#766b90")
|
||||||
|
(lotus-violet-3 "#c9cbd1")
|
||||||
|
(lotus-violet-4 "#624c83")
|
||||||
|
(lotus-blue-1 "#c7d7e0")
|
||||||
|
(lotus-blue-2 "#b5cbd2")
|
||||||
|
(lotus-blue-3 "#9fb5c9")
|
||||||
|
(lotus-blue-4 "#4d699b")
|
||||||
|
(lotus-blue-5 "#5d57a3")
|
||||||
|
(lotus-green "#6f894e")
|
||||||
|
(lotus-green-2 "#6e915f")
|
||||||
|
(lotus-green-3 "#b7d0ae")
|
||||||
|
(lotus-pink "#b35b79")
|
||||||
|
(lotus-orange "#cc6d00")
|
||||||
|
(lotus-orange2 "#e98a00")
|
||||||
|
(lotus-yellow "#77713f")
|
||||||
|
(lotus-yellow-2 "#836f4a")
|
||||||
|
(lotus-yellow-3 "#de9800")
|
||||||
|
(lotus-yellow-4 "#f9d791")
|
||||||
|
(lotus-red "#c84053")
|
||||||
|
(lotus-red-2 "#d7474b")
|
||||||
|
(lotus-red-3 "#e82424")
|
||||||
|
(lotus-red-4 "#d9a594")
|
||||||
|
(lotus-aqua "#597b75")
|
||||||
|
(lotus-aqua-2 "#5e857a")
|
||||||
|
(lotus-teal-1 "#4e8ca2")
|
||||||
|
(lotus-teal-2 "#6693bf")
|
||||||
|
(lotus-teal-3 "#5a7785")
|
||||||
|
(lotus-cyan "#d7e3d8")))
|
||||||
|
|
||||||
|
(cl-loop for (k v) in syd-kanagawa-palette-list
|
||||||
|
do (puthash k v syd-kanagawa-palette))
|
||||||
|
|
||||||
|
(defun syd-kanagawa-get (k)
|
||||||
|
(gethash k syd-kanagawa-palette nil))
|
||||||
|
|
||||||
|
(provide 'syd/kanagawa)
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
gpg.enable = true;
|
gpg.enable = true;
|
||||||
xdg.enable = true;
|
xdg.enable = true;
|
||||||
slippi.enable = true;
|
slippi.enable = true;
|
||||||
|
openutau.enable = true;
|
||||||
sops = {
|
sops = {
|
||||||
enable = true;
|
enable = true;
|
||||||
keyFile = "/persist/private-keys/age/${config.home.username}";
|
keyFile = "/persist/private-keys/age/${config.home.username}";
|
||||||
|
|||||||
Reference in New Issue
Block a user