emacs: Track required *.el files
So the language breakdown of my dotfiles as a repo doesn't look like I have that little elisp files :') Regardless of my recent activity in the neovim space I still love emacs, especially consult.el and org mode.
This commit is contained in:
parent
237637c653
commit
39b5aae9f5
|
@ -0,0 +1,99 @@
|
||||||
|
;;; init-highlight.el --- Highlighting stuff
|
||||||
|
;;; Commentary:
|
||||||
|
;; Highlighting symbols, indentation, brackets, TODO/REVIEW/FIXME/HACK/XXX
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; TODO: do I need hl-line package??
|
||||||
|
|
||||||
|
;; Highlight indentions
|
||||||
|
(use-package highlight-indent-guides
|
||||||
|
:diminish
|
||||||
|
:hook ((prog-mode yaml-mode) . highlight-indent-guides-mode)
|
||||||
|
:init (setq highlight-indent-guides-method 'character
|
||||||
|
highlight-indent-guides-responsive 'top
|
||||||
|
highlight-indent-guides-suppress-auto-error t)
|
||||||
|
:custom-face
|
||||||
|
(highlight-indent-guides-character-face ((t (:foreground "dim gray"))))
|
||||||
|
:config
|
||||||
|
(with-no-warnings
|
||||||
|
;; Don't display first level of indentation
|
||||||
|
(defun my-indent-guides-for-all-but-first-column (level responsive display)
|
||||||
|
(unless (< level 1)
|
||||||
|
(highlight-indent-guides--highlighter-default level responsive display)))
|
||||||
|
(setq highlight-indent-guides-highlighter-function
|
||||||
|
#'my-indent-guides-for-all-but-first-column)
|
||||||
|
|
||||||
|
;; Disable in `macrostep' expanding
|
||||||
|
(with-eval-after-load 'macrostep
|
||||||
|
(advice-add #'macrostep-expand
|
||||||
|
:after (lambda (&rest _)
|
||||||
|
(when highlight-indent-guides-mode
|
||||||
|
(highlight-indent-guides-mode -1))))
|
||||||
|
(advice-add #'macrostep-collapse
|
||||||
|
:after (lambda (&rest _)
|
||||||
|
(when (derived-mode-p 'prog-mode 'yaml-mode)
|
||||||
|
(highlight-indent-guides-mode 1)))))
|
||||||
|
|
||||||
|
;; Don't display indentations in `swiper'
|
||||||
|
;; https://github.com/DarthFennec/highlight-indent-guides/issues/40
|
||||||
|
(with-eval-after-load 'ivy
|
||||||
|
(defun my-ivy-cleanup-indentation (str)
|
||||||
|
"Clean up indentation highlighting in ivy minibuffer."
|
||||||
|
(let ((pos 0)
|
||||||
|
(next 0)
|
||||||
|
(limit (length str))
|
||||||
|
(prop 'highlight-indent-guides-prop))
|
||||||
|
(while (and pos next)
|
||||||
|
(setq next (text-property-not-all pos limit prop nil str))
|
||||||
|
(when next
|
||||||
|
(setq pos (text-property-any next limit prop nil str))
|
||||||
|
(ignore-errors
|
||||||
|
(remove-text-properties next pos '(display nil face nil) str))))))
|
||||||
|
(advice-add #'ivy-cleanup-string :after #'my-ivy-cleanup-indentation))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Colorize color names in buffers
|
||||||
|
(use-package rainbow-mode
|
||||||
|
:diminish
|
||||||
|
:bind (:map special-mode-map
|
||||||
|
("w" . rainbow-mode))
|
||||||
|
:hook ((html-mode php-mode) . rainbow-mode)
|
||||||
|
:config
|
||||||
|
(with-no-warnings
|
||||||
|
;; HACK: Use overlay instead of text properties to override `hl-line' faces.
|
||||||
|
;; @see https://emacs.stackexchange.com/questions/36420
|
||||||
|
(defun my-rainbow-colorize-match (color &optional match)
|
||||||
|
(let* ((match (or match 0))
|
||||||
|
(ov (make-overlay (match-beginning match) (match-end match))))
|
||||||
|
(overlay-put ov 'ovrainbow t)
|
||||||
|
(overlay-put ov 'face `((:foreground ,(if (> 0.5 (rainbow-x-color-luminance color))
|
||||||
|
"white" "black"))
|
||||||
|
(:background ,color)))))
|
||||||
|
(advice-add #'rainbow-colorize-match :override #'my-rainbow-colorize-match)
|
||||||
|
|
||||||
|
(defun my-rainbow-clear-overlays ()
|
||||||
|
"Clear all rainbow overlays."
|
||||||
|
(remove-overlays (point-min) (point-max) 'ovrainbow t))
|
||||||
|
(advice-add #'rainbow-turn-off :after #'my-rainbow-clear-overlays)))
|
||||||
|
|
||||||
|
;; Highlight brackets according to their depth
|
||||||
|
(use-package rainbow-delimiters
|
||||||
|
:hook (prog-mode . rainbow-delimiters-mode))
|
||||||
|
|
||||||
|
;; Highlight TODO and similar keywords in comments and strings
|
||||||
|
(use-package hl-todo
|
||||||
|
:demand t
|
||||||
|
:config
|
||||||
|
(global-hl-todo-mode 1)
|
||||||
|
(dolist (keyword '("REVIEW" "HACK"))
|
||||||
|
(cl-pushnew `(,keyword . ,(face-foreground 'warning)) hl-todo-keyword-faces))
|
||||||
|
:bind (:map hl-todo-mode-map
|
||||||
|
([C-f3] . hl-todo-occur)
|
||||||
|
("C-c t p" . hl-todo-previous)
|
||||||
|
("C-c t n" . hl-todo-next)
|
||||||
|
("C-c t o" . hl-todo-occur))
|
||||||
|
;;:hook (after-init . global-hl-todo-mode)
|
||||||
|
)
|
||||||
|
(provide 'init-highlight)
|
||||||
|
;;; init-highlight.el ends here
|
|
@ -0,0 +1,778 @@
|
||||||
|
;; NOTE:
|
||||||
|
;; This file is generated from packages.org
|
||||||
|
|
||||||
|
(defconst IS-MAC (eq system-type 'darwin))
|
||||||
|
(defconst IS-LINUX (memq system-type '(gnu gnu/linux gnu/kfreebsd berkeley-unix)))
|
||||||
|
(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos)))
|
||||||
|
(defconst IS-BSD (memq system-type '(darwin berkeley-unix gnu/kfreebsd)))
|
||||||
|
(defconst HAS-EMACS28+ (> emacs-major-version 27))
|
||||||
|
(defconst HAS-EMACS29+ (> emacs-major-version 28))
|
||||||
|
(defconst HAS-DYNMODULES (featurep 'dynamic-modules))
|
||||||
|
(defconst HAS-NATIVECOMP (featurep 'native-compile))
|
||||||
|
|
||||||
|
(set-face-attribute 'completions-first-difference nil :weight 'normal)
|
||||||
|
|
||||||
|
(defvar ./corfu-bar-color "gray20" ;; Default value is for dark themes
|
||||||
|
"Color for the corfu scroll bar.")
|
||||||
|
(defvar ./cursor-color "white"
|
||||||
|
"Color for cursor")
|
||||||
|
(defvar ./theme-type "dark"
|
||||||
|
"Dark or light")
|
||||||
|
|
||||||
|
(use-package ef-themes
|
||||||
|
:config
|
||||||
|
(load-theme 'ef-elea-dark t)
|
||||||
|
(set-face-attribute 'cursor nil :background "white")
|
||||||
|
(set-face-attribute 'font-lock-builtin-face nil :weight 'normal)
|
||||||
|
(set-face-attribute 'font-lock-keyword-face nil :weight 'normal)
|
||||||
|
(set-face-attribute 'font-lock-variable-name-face nil :foreground "white")
|
||||||
|
(set-face-attribute 'font-lock-property-name-face nil :foreground "white")
|
||||||
|
(set-face-attribute 'font-lock-constant-face nil :foreground "white")
|
||||||
|
|
||||||
|
(set-face-attribute 'window-divider nil :foreground "gray20")
|
||||||
|
(set-face-attribute 'window-divider-first-pixel nil :foreground "black")
|
||||||
|
(set-face-attribute 'window-divider-last-pixel nil :foreground "black")
|
||||||
|
)
|
||||||
|
|
||||||
|
(setq ./theme-type (symbol-name (frame-parameter nil 'background-mode)))
|
||||||
|
(setq ./cursor-color (if (string= ./theme-type "dark") "white" "black"))
|
||||||
|
(set-face-attribute 'cursor nil :background ./cursor-color)
|
||||||
|
;; TODO: Do this for window divider and corfu UI items, and magit diff backgrounds.
|
||||||
|
;; and org-link
|
||||||
|
|
||||||
|
(setq tab-bar-auto-width-max nil)
|
||||||
|
|
||||||
|
(setq tab-bar-new-tab-choice "*scratch*")
|
||||||
|
|
||||||
|
;; FIXME: Doesn't work
|
||||||
|
(set-face-attribute 'tab-bar-tab-inactive nil :background "textBackgroundColor")
|
||||||
|
|
||||||
|
(use-package evil
|
||||||
|
:demand t
|
||||||
|
:init
|
||||||
|
(setq evil-search-module 'evil-search
|
||||||
|
evil-ex-search-vim-style-regexp t)
|
||||||
|
(setq evil-ex-visual-char-range t ; column range for ex commands
|
||||||
|
evil-mode-line-format 'nil
|
||||||
|
;; more vim-like behavior
|
||||||
|
evil-symbol-word-search t)
|
||||||
|
(setq evil-default-cursor 'box
|
||||||
|
evil-normal-state-cursor 'box
|
||||||
|
evil-emacs-state-cursor 'bar
|
||||||
|
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.
|
||||||
|
(setq evil-ex-interactive-search-highlight 'selected-window
|
||||||
|
;; It's infuriating that innocuous "beginning of line" or "end of line"
|
||||||
|
;; errors will abort macros, so suppress them:
|
||||||
|
evil-kbd-macro-suppress-motion-error t)
|
||||||
|
(setq evil-want-C-u-scroll t) ; must be set in :init
|
||||||
|
;; REVIEW: Is this needed if evil-redo-function is set?
|
||||||
|
(setq evil-undo-system 'undo-redo) ;; 'undo-redo from Emacs 28
|
||||||
|
(setq evil-undo-function 'undo)
|
||||||
|
(setq evil-redo-function 'undo-redo)
|
||||||
|
|
||||||
|
:config
|
||||||
|
(setq evil-visual-update-x-selection-p nil)
|
||||||
|
(setq evil-shift-width 2)
|
||||||
|
(setq evil-cross-lines t)
|
||||||
|
|
||||||
|
;; Emacs keybindings in evil insert state - must be set in :config
|
||||||
|
(setq evil-insert-state-map (make-sparse-keymap))
|
||||||
|
(define-key evil-insert-state-map (kbd "<escape>") 'evil-normal-state)
|
||||||
|
(define-key evil-emacs-state-map (kbd "<escape>") 'evil-normal-state)
|
||||||
|
(define-key evil-insert-state-map (kbd "S-C-e") 'evil-scroll-line-down)
|
||||||
|
(define-key evil-emacs-state-map (kbd "S-C-e") 'evil-scroll-line-down)
|
||||||
|
(define-key evil-insert-state-map (kbd "S-C-y") 'evil-scroll-line-up)
|
||||||
|
(define-key evil-emacs-state-map (kbd "S-C-y") 'evil-scroll-line-up)
|
||||||
|
;; Don't put vim yanks into system clipboard
|
||||||
|
;; But use shift C-v / C-c to paste/copy from system clipboard instead
|
||||||
|
(setq select-enable-clipboard nil)
|
||||||
|
(global-set-key (kbd "S-C-c") #'clipboard-kill-ring-save)
|
||||||
|
(global-set-key (kbd "S-C-v") #'clipboard-yank)
|
||||||
|
|
||||||
|
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
|
||||||
|
;; FIXME
|
||||||
|
(evil-set-leader nil (kbd "S-C-SPC")) ;; C-SPC is mark set
|
||||||
|
(evil-set-leader 'normal (kbd "SPC"))
|
||||||
|
|
||||||
|
(define-key evil-command-line-map "\C-a" 'move-beginning-of-line)
|
||||||
|
(define-key evil-command-line-map "\C-e" 'move-end-of-line)
|
||||||
|
;; (define-key evil-command-line-map "\C-d" nil t)
|
||||||
|
;; (define-key evil-command-line-map "\C-l" nil t)
|
||||||
|
|
||||||
|
(global-set-key (kbd "s-<left>") #'previous-buffer)
|
||||||
|
(global-set-key (kbd "s-<right>") #'next-buffer)
|
||||||
|
(global-set-key (kbd "S-s-<down>") #'evil-window-down)
|
||||||
|
(global-set-key (kbd "S-s-<up>") #'evil-window-up)
|
||||||
|
(global-set-key (kbd "S-s-<left>") #'evil-window-left)
|
||||||
|
(global-set-key (kbd "S-s-<right>") #'evil-window-right)
|
||||||
|
(defvar ./leader-map (make-sparse-keymap)
|
||||||
|
"Keymap for leader shortcuts")
|
||||||
|
(define-key evil-normal-state-map (kbd "SPC") ./leader-map)
|
||||||
|
(define-key ./leader-map "q" #'evil-quit)
|
||||||
|
(define-key ./leader-map "w" #'save-buffer)
|
||||||
|
(define-key ./leader-map "x" #'evil-save-modified-and-close)
|
||||||
|
(define-key ./leader-map "1" #'delete-other-windows)
|
||||||
|
|
||||||
|
(defvar ./leader-buffer-map (make-sparse-keymap)
|
||||||
|
"Keymap for leader shortcuts for buffers")
|
||||||
|
(define-key ./leader-map "b" ./leader-buffer-map)
|
||||||
|
(define-key ./leader-buffer-map "b" #'consult-buffer)
|
||||||
|
(define-key ./leader-buffer-map "s" #'save-buffer)
|
||||||
|
(define-key ./leader-buffer-map "d" #'evil-delete-buffer)
|
||||||
|
|
||||||
|
(defvar ./leader-file-map (make-sparse-keymap)
|
||||||
|
"Keymap for leader shortcuts for files")
|
||||||
|
(define-key ./leader-map "f" ./leader-file-map)
|
||||||
|
(define-key ./leader-file-map "f" #'find-file)
|
||||||
|
(define-key ./leader-file-map "r" #'consult-recent-file)
|
||||||
|
(define-key ./leader-file-map "p" #'project-find-file)
|
||||||
|
|
||||||
|
(defvar ./leader-frame-map (make-sparse-keymap)
|
||||||
|
"Keymap for leader shortcuts for frames")
|
||||||
|
(define-key ./leader-map "F" ./leader-frame-map)
|
||||||
|
(define-key ./leader-frame-map "q" #'delete-frame)
|
||||||
|
(define-key ./leader-frame-map "d" #'delete-frame)
|
||||||
|
(define-key ./leader-frame-map "u" #'undelete-frame)
|
||||||
|
(define-key ./leader-frame-map "R" #'rename-frame)
|
||||||
|
(define-key ./leader-frame-map "o" #'other-frame)
|
||||||
|
(define-key ./leader-frame-map "c" #'clone-frame)
|
||||||
|
|
||||||
|
(defun ./evil-off ()
|
||||||
|
"Call `turn-off-evil-mode' and show a message"
|
||||||
|
(interactive)
|
||||||
|
(turn-off-evil-mode)
|
||||||
|
(message "Evil mode is turned off"))
|
||||||
|
|
||||||
|
;; Disable evil in some modes
|
||||||
|
(dolist (mode '(elpaca-ui-mode
|
||||||
|
dired-mode
|
||||||
|
magit-mode))
|
||||||
|
(evil-set-initial-state mode 'emacs))
|
||||||
|
|
||||||
|
(evil-mode 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package elpher)
|
||||||
|
;; eww is part of emacs now?!!
|
||||||
|
;;(use-package eww)
|
||||||
|
|
||||||
|
(use-package visual-fill-column
|
||||||
|
:init
|
||||||
|
(setq-default visual-fill-column-center-text t))
|
||||||
|
|
||||||
|
(use-package imenu-list
|
||||||
|
:config
|
||||||
|
(setq imenu-list-auto-resize t)
|
||||||
|
;; Auto-update Ilist buffer
|
||||||
|
:hook (imenu-list-major-mode . (lambda ()
|
||||||
|
(imenu-list-minor-mode 1)
|
||||||
|
(visual-line-mode 1) ;; REVIEW
|
||||||
|
(display-line-numbers-mode -1)
|
||||||
|
(evil-insert-state 1))))
|
||||||
|
|
||||||
|
(use-package math-symbol-lists
|
||||||
|
:after cape
|
||||||
|
:config
|
||||||
|
;; This is actually for C-\, then select input "math",
|
||||||
|
;; then the Ω will show in the status bar.
|
||||||
|
(quail-define-package "math" "UTF-8" "Ω" t)
|
||||||
|
;; (quail-define-rules ; add whatever extra rules you want to define here...
|
||||||
|
;; ("\\from" #X2190)
|
||||||
|
;; ("\\to" #X2192)
|
||||||
|
;; ("\\lhd" #X22B2)
|
||||||
|
;; ("\\rhd" #X22B3)
|
||||||
|
;; ("\\unlhd" #X22B4)
|
||||||
|
;; ("\\unrhd" #X22B5))
|
||||||
|
(mapc (lambda (x)
|
||||||
|
(if (cddr x)
|
||||||
|
(quail-defrule (cadr x) (car (cddr x)))))
|
||||||
|
(append math-symbol-list-basic math-symbol-list-extended))
|
||||||
|
)
|
||||||
|
|
||||||
|
;; (use-package dired
|
||||||
|
;; :elpaca nil
|
||||||
|
;; :config
|
||||||
|
(setq delete-by-moving-to-trash t
|
||||||
|
;; Emacs 29
|
||||||
|
dired-make-directory-clickable t
|
||||||
|
dired-mouse-drag-files t
|
||||||
|
)
|
||||||
|
|
||||||
|
;;:hook
|
||||||
|
;; FIXME: replicate evil state cursor style switching here
|
||||||
|
(defun ./cursor-toggle-readonly ()
|
||||||
|
(if buffer-read-only
|
||||||
|
(progn
|
||||||
|
(setq cursor-type 'box)
|
||||||
|
(set-cursor-color "orange"))
|
||||||
|
(setq cursor-type 'bar)
|
||||||
|
(set-cursor-color ./cursor-color)))
|
||||||
|
|
||||||
|
(add-hook 'read-only-mode-hook #'./cursor-toggle-readonly)
|
||||||
|
(add-hook 'dired-mode-hook (lambda () (hl-line-mode) (./cursor-toggle-readonly)))
|
||||||
|
;; )
|
||||||
|
|
||||||
|
(add-hook 'minibuffer-setup-hook (lambda () (setq cursor-type 'bar)))
|
||||||
|
(add-hook 'minibuffer-exit-hook (lambda () (setq cursor-type 'box)))
|
||||||
|
|
||||||
|
(use-package wrap-region
|
||||||
|
:config
|
||||||
|
(wrap-region-add-wrappers
|
||||||
|
'(("/* " " */" "#" (java-mode javascript-mode css-mode))
|
||||||
|
("`" "`" nil (markdown-mode org-mode))
|
||||||
|
("=" "=" nil (org-mode))
|
||||||
|
("~" "~" nil (org-mode))
|
||||||
|
("*" "*" nil (markdown-mode org-mode))))
|
||||||
|
:hook
|
||||||
|
((org-mode markdown-mode) . wrap-region-mode)
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package magit)
|
||||||
|
|
||||||
|
(use-package breadcrumb
|
||||||
|
:diminish breadcrumb-mode
|
||||||
|
:init
|
||||||
|
(breadcrumb-mode 1))
|
||||||
|
|
||||||
|
(use-package vertico
|
||||||
|
:init
|
||||||
|
(vertico-mode)
|
||||||
|
;; Grow and shrink the Vertico minibuffer
|
||||||
|
(setq vertico-resize t)
|
||||||
|
;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
|
||||||
|
(setq vertico-cycle t)
|
||||||
|
:hook
|
||||||
|
;; For find-file, remove old file path if I start typing a new one
|
||||||
|
('rfn-eshadow-update-overlay-hook . #'vertico-directory-tidy)
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package orderless
|
||||||
|
:init
|
||||||
|
(setq completion-styles '(orderless)
|
||||||
|
completion-category-defaults nil
|
||||||
|
completion-category-overrides '((file (styles partial-completion)))))
|
||||||
|
;; Persist history over Emacs restarts. Vertico sorts by history position.
|
||||||
|
(use-package savehist
|
||||||
|
:elpaca nil
|
||||||
|
:init
|
||||||
|
(savehist-mode))
|
||||||
|
;; Pasted from vertico
|
||||||
|
(use-package emacs
|
||||||
|
:elpaca nil
|
||||||
|
:init
|
||||||
|
;; Add prompt indicator to `completing-read-multiple'.
|
||||||
|
;; Alternatively try `consult-completing-read-multiple'.
|
||||||
|
(defun crm-indicator (args)
|
||||||
|
(cons (concat "[CRM] " (car args)) (cdr args)))
|
||||||
|
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
|
||||||
|
;; Do not allow the cursor in the minibuffer prompt
|
||||||
|
(setq minibuffer-prompt-properties
|
||||||
|
'(read-only t cursor-intangible t face minibuffer-prompt))
|
||||||
|
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
|
||||||
|
;; Emacs 28: Hide commands in M-x which do not work in the current mode.
|
||||||
|
;; Vertico commands are hidden in normal buffers.
|
||||||
|
;; (setq read-extended-command-predicate
|
||||||
|
;; #'command-completion-default-include-p)
|
||||||
|
;; Enable recursive minibuffers
|
||||||
|
(setq enable-recursive-minibuffers t)
|
||||||
|
;; From corfu
|
||||||
|
;; TAB cycle if there are only few candidates
|
||||||
|
(setq completion-cycle-threshold 3)
|
||||||
|
|
||||||
|
;; Emacs 28: Hide commands in M-x which do not apply to the current mode.
|
||||||
|
;; Corfu commands are hidden, since they are not supposed to be used via M-x.
|
||||||
|
;; (setq read-extended-command-predicate
|
||||||
|
;; #'command-completion-default-include-p)
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package marginalia
|
||||||
|
:diminish
|
||||||
|
:config
|
||||||
|
(setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
|
||||||
|
(marginalia-mode 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package consult
|
||||||
|
:config
|
||||||
|
(global-set-key (kbd "C-s") 'consult-line)
|
||||||
|
(define-key evil-insert-state-map (kbd "C-s") 'isearch-forward)
|
||||||
|
(define-key evil-emacs-state-map (kbd "C-s") 'isearch-forward)
|
||||||
|
(global-set-key (kbd "C-c g") 'consult-org-heading)
|
||||||
|
(global-set-key (kbd "C-x C-b") 'consult-buffer)
|
||||||
|
;; Doesn't work?
|
||||||
|
(global-set-key [?\C-\t] 'consult-buffer)
|
||||||
|
(define-key minibuffer-local-map (kbd "C-r") 'consult-history)
|
||||||
|
|
||||||
|
(setq completion-in-region-function #'consult-completion-in-region)
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package corfu
|
||||||
|
:custom
|
||||||
|
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
|
||||||
|
;; Default is M-SPC, if M-SPC is bound like I have on my Mac (Alfred) S-M-SPC also works
|
||||||
|
;;(corfu-separator ?\s) ;; Orderless separator
|
||||||
|
;; separator: Quit at boundary if no `corfu-separator' inserted
|
||||||
|
(corfu-quit-at-boundary 'separator)
|
||||||
|
;; separator: only stay alive if no match and `corfu-separator' inserted
|
||||||
|
(corfu-quit-no-match 'separator)
|
||||||
|
;; Don't change what I typed to what I selected when previewing completions
|
||||||
|
(corfu-preview-current nil)
|
||||||
|
(corfu-preselect 'first)
|
||||||
|
;; Default = #'insert. Options: quit, nil
|
||||||
|
;;(corfu-on-exact-match nil)
|
||||||
|
;; Prevent last/first item being hidden behind windows
|
||||||
|
;; FIXME: Doesn't work
|
||||||
|
(corfu-scroll-margin 2)
|
||||||
|
(corfu-right-margin-width 2)
|
||||||
|
|
||||||
|
;; Enable Corfu only for certain modes.
|
||||||
|
;; :hook ((prog-mode . corfu-mode)
|
||||||
|
;; (shell-mode . corfu-mode)
|
||||||
|
;; (eshell-mode . corfu-mode))
|
||||||
|
|
||||||
|
;; FIXME: doesn't work: evil insert/emacs keybinds takes higher precendence it seems
|
||||||
|
(define-key corfu-map (kbd "<escape>") 'corfu-quit)
|
||||||
|
|
||||||
|
:custom-face
|
||||||
|
(corfu-border ((t (:background "gray20" :weight bold))))
|
||||||
|
(corfu-default ((t (:inherit fixed-pitch))))
|
||||||
|
|
||||||
|
:init
|
||||||
|
;; Recommended: Enable Corfu globally.
|
||||||
|
;; This is recommended since Dabbrev can be used globally (M-/).
|
||||||
|
;; See also `global-corfu-modes'.
|
||||||
|
(global-corfu-mode)
|
||||||
|
(corfu-popupinfo-mode 1)
|
||||||
|
|
||||||
|
:config
|
||||||
|
(setq corfu-bar-width 0.8)
|
||||||
|
(set-face-attribute 'corfu-bar nil :background ./corfu-bar-color)
|
||||||
|
(defun corfu-enable-always-in-minibuffer ()
|
||||||
|
"Enable Corfu in the minibuffer if Vertico/Mct are not active."
|
||||||
|
(unless (or (bound-and-true-p mct--active)
|
||||||
|
(bound-and-true-p vertico--input)
|
||||||
|
(eq (current-local-map) read-passwd-map))
|
||||||
|
;; (setq-local corfu-auto nil) ;; Enable/disable auto completion
|
||||||
|
(setq-local corfu-echo-delay nil ;; Disable automatic echo and popup
|
||||||
|
corfu-popupinfo-delay '(0 . 0)) ;; Use popupinfo in minibuffer too, why not?
|
||||||
|
(corfu-mode 1)))
|
||||||
|
(add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1)
|
||||||
|
|
||||||
|
(setq corfu-popupinfo-delay '(0 . 0))
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package kind-icon
|
||||||
|
:after corfu
|
||||||
|
:custom
|
||||||
|
(kind-icon-mapping ;; These are fetched (and cached) from pictogrammers.com/library/mdi
|
||||||
|
'((array "ar" :icon "code-brackets" :face font-lock-type-face)
|
||||||
|
(boolean "b" :face font-lock-builtin-face)
|
||||||
|
(class "C" :face font-lock-type-face) ;; family-tree could be used. but too dense
|
||||||
|
(color "#" :icon "palette" :face success)
|
||||||
|
(command ">_" :face default)
|
||||||
|
(constant "cn" :icon "lock-remove-outline" :face font-lock-constant-face)
|
||||||
|
(constructor "C+" :icon "plus-circle-multiple" :face font-lock-function-name-face)
|
||||||
|
(enummember "em" :icon "order-bool-ascending-variant" :face font-lock-builtin-face)
|
||||||
|
(enum-member "em" :icon "order-bool-ascending-variant" :face font-lock-builtin-face)
|
||||||
|
(enum "e" :icon "format-list-bulleted-square" :face font-lock-builtin-face)
|
||||||
|
(event "ev" :icon "lightning-bolt-outline" :face font-lock-warning-face)
|
||||||
|
(field "fd" :face font-lock-variable-name-face)
|
||||||
|
(file "F" :icon "file-document-outline" :face font-lock-string-face)
|
||||||
|
(folder "D" :icon "folder" :face font-lock-doc-face)
|
||||||
|
(interface "if" :icon "application-brackets-outline" :face font-lock-type-face)
|
||||||
|
(keyword "kw" :face font-lock-keyword-face)
|
||||||
|
(macro "mc" :icon "lambda" :face font-lock-keyword-face)
|
||||||
|
(magic "ma" :icon "shimmer" :face font-lock-builtin-face)
|
||||||
|
(method "me" :face font-lock-function-name-face)
|
||||||
|
(function "f" :icon "function" :face font-lock-function-name-face)
|
||||||
|
(module "mo" :icon "package-variant-closed" :face font-lock-preprocessor-face)
|
||||||
|
(numeric "0" :icon "numeric" :face font-lock-builtin-face)
|
||||||
|
(operator "÷" :icon "division" :face font-lock-comment-delimiter-face)
|
||||||
|
(param "pa" :icon "cog-outline" :face default)
|
||||||
|
(property "pr" :icon "wrench" :face font-lock-variable-name-face)
|
||||||
|
(reference "rf" :icon "library" :face font-lock-variable-name-face)
|
||||||
|
(snippet "S" :face font-lock-string-face)
|
||||||
|
(string "\"" :icon "text-box" :face font-lock-string-face)
|
||||||
|
(struct "{}" :icon "code-braces" :face font-lock-variable-name-face)
|
||||||
|
(text " " :face font-lock-doc-face) ; text-short could be used
|
||||||
|
(typeparameter "tp" :icon "format-list-bulleted-type" :face font-lock-type-face)
|
||||||
|
(type-parameter "tp" :icon "format-list-bulleted-type" :face font-lock-type-face)
|
||||||
|
(unit "u" :icon "square-rounded-outline" :face font-lock-constant-face)
|
||||||
|
(value "vl" :icon "plus-circle-outline" :face font-lock-builtin-face)
|
||||||
|
(variable "v" :face font-lock-variable-name-face)
|
||||||
|
(t "?" :face font-lock-warning-face)))
|
||||||
|
(kind-icon-blend-background nil)
|
||||||
|
:custom-face
|
||||||
|
(kind-icon-default-face ((t (:background nil))))
|
||||||
|
|
||||||
|
:config
|
||||||
|
;;(setq kind-icon-default-face 'corfu-default) ; to compute blended backgrounds correctly
|
||||||
|
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
|
||||||
|
|
||||||
|
(use-package cape
|
||||||
|
;;:after math-symbol-lists
|
||||||
|
:config
|
||||||
|
;; Add useful defaults completion sources from cape
|
||||||
|
;; (add-to-list 'completion-at-point-functions #'cape-file)
|
||||||
|
;; ;;(add-to-list 'completion-at-point-functions #'cape-dabbrev)
|
||||||
|
;;(add-to-list 'completion-at-point-functions #'cape-tex)
|
||||||
|
(add-to-list 'completion-at-point-functions #'cape-emoji)
|
||||||
|
|
||||||
|
;; Silence the pcomplete capf, no errors or messages!
|
||||||
|
;; Important for corfu
|
||||||
|
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
|
||||||
|
|
||||||
|
;; Ensure that pcomplete does not write to the buffer
|
||||||
|
;; and behaves as a pure `completion-at-point-function'.
|
||||||
|
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)
|
||||||
|
|
||||||
|
(define-key evil-insert-state-map (kbd "C-x C-f") 'cape-file)
|
||||||
|
(define-key evil-insert-state-map (kbd "C-x C-d") 'cape-dict)
|
||||||
|
(define-key evil-insert-state-map (kbd "C-x C-w") 'cape-dabbrev)
|
||||||
|
(define-key evil-insert-state-map (kbd "C-x C-:") 'cape-emoji)
|
||||||
|
|
||||||
|
(cape-char--define math "math" ?\\)
|
||||||
|
(add-to-list 'completion-at-point-functions #'cape-math)
|
||||||
|
(define-key evil-insert-state-map (kbd "C-x C-$") 'cape-math)
|
||||||
|
|
||||||
|
:hook (eshell-mode-hook . (lambda () (setq-local corfu-quit-at-boundary t
|
||||||
|
corfu-quit-no-match t
|
||||||
|
corfu-auto nil)
|
||||||
|
(corfu-mode)))
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package corfu-candidate-overlay
|
||||||
|
:config
|
||||||
|
(corfu-candidate-overlay-mode 1) ;; This is global
|
||||||
|
(set-face-attribute 'corfu-candidate-overlay-face nil :foreground "dim grey")
|
||||||
|
;; Use TAB to accept a completion, how cool is that!
|
||||||
|
(defun ./insert-state-tab ()
|
||||||
|
"Handle TAB key in insert state.
|
||||||
|
|
||||||
|
If corfu-candidate-overlay's overlay is active, calls
|
||||||
|
`corfu-candidate-overlay--get-overlay-property', otherwise
|
||||||
|
`evil-toggle-fold'. See my packages.org for this section for why I
|
||||||
|
didn't use `org-cycle' here."
|
||||||
|
(interactive)
|
||||||
|
(if (overlayp corfu-candidate-overlay--overlay)
|
||||||
|
(progn
|
||||||
|
;; This check is taken exactly from the implementation of
|
||||||
|
;; `corfu-candidate-overlay-complete-at-point's (as of
|
||||||
|
;; writing).
|
||||||
|
(corfu-candidate-overlay--show)
|
||||||
|
(if (and (overlayp corfu-candidate-overlay--overlay)
|
||||||
|
(not (string= (corfu-candidate-overlay--get-overlay-property 'after-string) "")))
|
||||||
|
(corfu-candidate-overlay-complete-at-point)
|
||||||
|
(if (string-match-p
|
||||||
|
"^\*+ "
|
||||||
|
(buffer-substring-no-properties
|
||||||
|
(line-beginning-position)
|
||||||
|
(line-end-position)))
|
||||||
|
(evil-toggle-fold)
|
||||||
|
(indent)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
(if (string-match-p
|
||||||
|
"^\*+ "
|
||||||
|
(buffer-substring-no-properties
|
||||||
|
(line-beginning-position)
|
||||||
|
(line-end-position)))
|
||||||
|
(evil-toggle-fold)
|
||||||
|
(indent-for-tab-command)
|
||||||
|
)))
|
||||||
|
(define-key evil-insert-state-map (kbd "TAB") './insert-state-tab)
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package which-key
|
||||||
|
:diminish
|
||||||
|
:config
|
||||||
|
(which-key-setup-side-window-right)
|
||||||
|
(which-key-mode 1))
|
||||||
|
|
||||||
|
(use-package org
|
||||||
|
:elpaca nil
|
||||||
|
:config
|
||||||
|
(setq org-startup-indented t)
|
||||||
|
(setq org-edit-src-content-indentation 0)
|
||||||
|
(setq org-list-indent-offset 2)
|
||||||
|
|
||||||
|
;; (dolist (item '( ;; Newline used to add prefix to tangled file
|
||||||
|
;; '(org-block ((t (:inherit fixed-pitch))))
|
||||||
|
;; '(org-code ((t (:inherit (shadow fixed-pitch)))))
|
||||||
|
;; '(org-document-info ((t (:foreground "dark orange"))))
|
||||||
|
;; '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch)))))
|
||||||
|
;; '(org-indent ((t (:inherit (org-hide fixed-pitch)))))
|
||||||
|
;; '(org-link ((t (:foreground "deep sky blue" :underline t))))
|
||||||
|
;; '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch)))))
|
||||||
|
;; '(org-property-value ((t (:inherit fixed-pitch))) t)
|
||||||
|
;; '(org-block-begin-line ((t (:inherit (font-lock-comment-face fixed-pitch)))) t)
|
||||||
|
;; '(org-block-end-line ((t (:inherit (font-lock-comment-face fixed-pitch)))) t)
|
||||||
|
;; '(org-drawer ((t (:inherit fixed-pitch))) t)
|
||||||
|
;; '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch)))))
|
||||||
|
;; '(org-table ((t (:inherit fixed-pitch))))
|
||||||
|
;; '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8))))
|
||||||
|
;; '(org-verbatim ((t (:inherit (shadow fixed-pitch)))))))
|
||||||
|
;; (apply #'set-face-attribute item))
|
||||||
|
(custom-theme-set-faces
|
||||||
|
'user
|
||||||
|
'(org-block ((t (:inherit fixed-pitch))))
|
||||||
|
'(org-code ((t (:inherit (shadow fixed-pitch)))))
|
||||||
|
'(org-document-info ((t (:foreground "dark orange"))))
|
||||||
|
'(org-document-info-keyword ((t (:inherit (shadow fixed-pitch)))))
|
||||||
|
'(org-indent ((t (:inherit (org-hide fixed-pitch)))))
|
||||||
|
'(org-link ((t (:foreground "deep sky blue" :underline t))))
|
||||||
|
'(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch)))))
|
||||||
|
'(org-property-value ((t (:inherit fixed-pitch))) t)
|
||||||
|
'(org-block-begin-line ((t (:inherit (font-lock-comment-face fixed-pitch)))) t)
|
||||||
|
'(org-block-end-line ((t (:inherit (font-lock-comment-face fixed-pitch)))) t)
|
||||||
|
'(org-drawer ((t (:inherit fixed-pitch))) t)
|
||||||
|
'(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch)))))
|
||||||
|
'(org-table ((t (:inherit fixed-pitch))))
|
||||||
|
'(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8))))
|
||||||
|
'(org-verbatim ((t (:inherit (shadow fixed-pitch)))))
|
||||||
|
)
|
||||||
|
|
||||||
|
(org-babel-do-load-languages
|
||||||
|
'org-babel-load-languages
|
||||||
|
'((emacs-lisp . t)
|
||||||
|
(python . t)
|
||||||
|
(lua . t)
|
||||||
|
(js . t)))
|
||||||
|
|
||||||
|
(defun org-babel-execute:nim (body params)
|
||||||
|
"Execute a block of Nim code with org-babel."
|
||||||
|
(let ((in-file (org-babel-temp-file "n" ".nim"))
|
||||||
|
(verbosity (or (cdr (assq :verbosity params)) 0)))
|
||||||
|
(with-temp-file in-file
|
||||||
|
(insert body))
|
||||||
|
(org-babel-eval
|
||||||
|
(format "nim compile --verbosity=%d --run %s" verbosity
|
||||||
|
(org-babel-process-file-name in-file))
|
||||||
|
"")))
|
||||||
|
|
||||||
|
(defun org-babel-execute:moonscript (body params)
|
||||||
|
"Execute a block of MoonScript code with org-babel."
|
||||||
|
(let ((in-file (org-babel-temp-file "m" ".moon")))
|
||||||
|
(with-temp-file in-file
|
||||||
|
(insert body))
|
||||||
|
(org-babel-eval
|
||||||
|
(format "moon %s" (org-babel-process-file-name in-file)) "")))
|
||||||
|
|
||||||
|
:hook
|
||||||
|
(org-mode . (lambda () (visual-line-mode 1)
|
||||||
|
(variable-pitch-mode)
|
||||||
|
(display-line-numbers-mode -1)))
|
||||||
|
)
|
||||||
|
|
||||||
|
(use-package org-superstar
|
||||||
|
:config
|
||||||
|
(setq org-superstar-configure-like-org-bullets t)
|
||||||
|
:hook
|
||||||
|
(org-mode . (lambda () (org-superstar-mode 1))))
|
||||||
|
|
||||||
|
(use-package org-auto-tangle
|
||||||
|
:defer t
|
||||||
|
:hook (org-mode . org-auto-tangle-mode)
|
||||||
|
:config
|
||||||
|
(setq org-auto-tangle-babel-safelist '(
|
||||||
|
"~/.config/emacs/packages.org"
|
||||||
|
"~/.config/emacs/init.org")))
|
||||||
|
|
||||||
|
(use-package lua-mode)
|
||||||
|
(use-package moonscript)
|
||||||
|
(use-package nim-mode)
|
||||||
|
|
||||||
|
(use-package eglot
|
||||||
|
:elpaca nil
|
||||||
|
:defer t
|
||||||
|
:hook
|
||||||
|
((python-ts-mode go-ts-mode lua-mode) . eglot-ensure)
|
||||||
|
)
|
||||||
|
|
||||||
|
;; Open python files in tree-sitter mode.
|
||||||
|
(add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))
|
||||||
|
(add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode))
|
||||||
|
(add-to-list 'auto-mode-alist
|
||||||
|
'("\\.go\\'" . (lambda ()
|
||||||
|
(go-ts-mode)
|
||||||
|
)))
|
||||||
|
(add-to-list 'auto-mode-alist
|
||||||
|
'("go.mod\\'" . (lambda ()
|
||||||
|
(go-mod-ts-mode)
|
||||||
|
)))
|
||||||
|
|
||||||
|
;; FIXME
|
||||||
|
(use-package diminish
|
||||||
|
:config
|
||||||
|
(diminish 'buffer-face-mode)
|
||||||
|
(diminish 'org-auto-tangle-mode)
|
||||||
|
(diminish 'eldoc-mode)
|
||||||
|
(diminish 'auto-revert-mode)
|
||||||
|
(diminish 'visual-line-mode)
|
||||||
|
(diminish 'org-indent-mode)
|
||||||
|
(diminish 'subword-mode)
|
||||||
|
)
|
||||||
|
|
||||||
|
(defun ./eshell-fn-on-files (fun1 fun2 args)
|
||||||
|
"Call FUN1 on the first element in list, ARGS.
|
||||||
|
Call FUN2 on all the rest of the elements in ARGS."
|
||||||
|
(unless (null args)
|
||||||
|
(let ((filenames (flatten-list args)))
|
||||||
|
(funcall fun1 (car filenames))
|
||||||
|
(when (cdr filenames)
|
||||||
|
(mapcar fun2 (cdr filenames))))
|
||||||
|
;; Return an empty string, as the return value from `fun1'
|
||||||
|
;; probably isn't helpful to display in the `eshell' window.
|
||||||
|
""))
|
||||||
|
|
||||||
|
(defun eshell/ff (&rest files)
|
||||||
|
"find-file on first arg, find-file-other-window on rest"
|
||||||
|
(./eshell-fn-on-files 'find-file 'find-file-other-window files))
|
||||||
|
|
||||||
|
(defun eshell/f (&rest files)
|
||||||
|
"Edit one or more files in another window."
|
||||||
|
(./eshell-fn-on-files 'find-file-other-window 'find-file-other-window files))
|
||||||
|
|
||||||
|
(defalias 'eshell/emacs 'eshell/ff)
|
||||||
|
(defalias 'eshell/vi 'eshell/ff)
|
||||||
|
(defalias 'eshell/vim 'eshell/ff)
|
||||||
|
(defalias 'eshell/nv 'eshell/ff)
|
||||||
|
(defalias 'eshell/nvim 'eshell/ff)
|
||||||
|
|
||||||
|
(defun eshell/less (&rest files)
|
||||||
|
"view-file-other-window"
|
||||||
|
(view-file-other-window files))
|
||||||
|
|
||||||
|
(defalias 'eshell/more 'eshell/less)
|
||||||
|
|
||||||
|
(defun ./eshell-exit-with-window ()
|
||||||
|
(when (not (one-window-p))
|
||||||
|
(delete-window)))
|
||||||
|
|
||||||
|
(advice-add 'eshell-life-is-too-much :after './eshell-exit-with-window)
|
||||||
|
|
||||||
|
(defun eshell/do (&rest args)
|
||||||
|
"Execute a command sequence over a collection of file elements.
|
||||||
|
Separate the sequence and the elements with a `::' string.
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
do chown _ angela :: *.org(u'oscar')
|
||||||
|
|
||||||
|
The function substitutes the `_' sequence to a single filename
|
||||||
|
element, and if not specified, it appends the file name to the
|
||||||
|
command. So the following works as expected:
|
||||||
|
|
||||||
|
do chmod a+x :: *.org"
|
||||||
|
(seq-let (forms elements) (-split-on "::" args)
|
||||||
|
(dolist (element (-flatten (-concat elements)))
|
||||||
|
(message "Working on %s ... %s" element forms)
|
||||||
|
(let* ((form (if (-contains? forms "_")
|
||||||
|
(-replace "_" element forms)
|
||||||
|
(-snoc forms element)))
|
||||||
|
(cmd (car form))
|
||||||
|
(args (cdr form)))
|
||||||
|
(eshell-named-command cmd args)))))
|
||||||
|
|
||||||
|
(defun ./eshell--buffer-from-dir (dir)
|
||||||
|
"Return buffer name of an Eshell based on DIR."
|
||||||
|
(format "*eshell: %s*"
|
||||||
|
(thread-first dir
|
||||||
|
(split-string "/" t)
|
||||||
|
(last)
|
||||||
|
(car))))
|
||||||
|
|
||||||
|
(defun ./eshell-there (parent)
|
||||||
|
"Open an eshell session in a PARENT directory.
|
||||||
|
The window is smaller and named after this directory.
|
||||||
|
If an Eshell is already present that has been named
|
||||||
|
after PARENT, pop to that buffer instead."
|
||||||
|
(if-let* ((term-name (./eshell--buffer-from-dir parent))
|
||||||
|
(buf-name (seq-contains (buffer-list) term-name
|
||||||
|
(lambda (a b) (string-equal (buffer-name b) a)))))
|
||||||
|
(pop-to-buffer buf-name)
|
||||||
|
|
||||||
|
(let* ((default-directory parent)
|
||||||
|
(height (/ (window-total-height) 3)))
|
||||||
|
(split-window-vertically (- height))
|
||||||
|
(other-window 1)
|
||||||
|
(setq eshell-buffer-name term-name)
|
||||||
|
(eshell))))
|
||||||
|
|
||||||
|
(defun ./eshell-here ()
|
||||||
|
"Opens a new shell in the directory of the current buffer.
|
||||||
|
Renames the eshell buffer to match that directory to allow more
|
||||||
|
than one eshell window."
|
||||||
|
(interactive)
|
||||||
|
(./eshell-there (if (buffer-file-name)
|
||||||
|
(file-name-directory (buffer-file-name))
|
||||||
|
default-directory)))
|
||||||
|
|
||||||
|
(bind-key "C-`" './eshell-here)
|
||||||
|
|
||||||
|
(defun ./eshell-send (command &optional dir)
|
||||||
|
"Send COMMAND to the Eshell buffer named with DIR.
|
||||||
|
The Eshell may have moved away from the directory originally
|
||||||
|
opened with DIR, but it should have the name of the buffer.
|
||||||
|
See `eshell--buffer-from-dir'."
|
||||||
|
(interactive "sCommand to Send: ")
|
||||||
|
(unless dir
|
||||||
|
(setq dir (projectile-project-root)))
|
||||||
|
(save-window-excursion
|
||||||
|
(eshell-there dir)
|
||||||
|
(goto-char (point-max))
|
||||||
|
(insert command)
|
||||||
|
(eshell-send-input)))
|
||||||
|
|
||||||
|
(defun ./execute-command-on-file-buffer (cmd)
|
||||||
|
"Executes a shell command, CMD, on the current buffer's file.
|
||||||
|
Appends the filename to the command if not specified, so:
|
||||||
|
|
||||||
|
chmod a+x
|
||||||
|
|
||||||
|
Works as expected. We replace the special variable `$$' with the
|
||||||
|
filename of the buffer. Note that `eshell-command' executes this
|
||||||
|
command, so eshell modifiers are available, for instance:
|
||||||
|
|
||||||
|
mv $$ $$(:r).txt
|
||||||
|
|
||||||
|
Will rename the current file to now have a .txt extension.
|
||||||
|
See `eshell-display-modifier-help' for details on that."
|
||||||
|
(interactive "sExecute command on File Buffer: ")
|
||||||
|
(let* ((file-name (buffer-file-name))
|
||||||
|
(full-cmd (cond ((string-match (rx "$$") cmd)
|
||||||
|
(replace-regexp-in-string (rx "$$") file-name cmd))
|
||||||
|
((and file-name (string-match (rx (literal file-name)) cmd))
|
||||||
|
cmd)
|
||||||
|
(t
|
||||||
|
(concat cmd " " file-name)))))
|
||||||
|
(message "Executing: %s" full-cmd)
|
||||||
|
(eshell-command full-cmd)))
|
||||||
|
|
||||||
|
(use-package eshell
|
||||||
|
:elpaca nil
|
||||||
|
:init
|
||||||
|
(setq eshell-error-if-no-glob t
|
||||||
|
;; This jumps back to the prompt:
|
||||||
|
eshell-scroll-to-bottom-on-input 'all
|
||||||
|
eshell-hist-ignoredups t
|
||||||
|
eshell-save-history-on-exit t
|
||||||
|
|
||||||
|
;; Since eshell starts fast, let's dismiss it on exit:
|
||||||
|
eshell-kill-on-exit t
|
||||||
|
eshell-destroy-buffer-when-process-dies t
|
||||||
|
|
||||||
|
;; Parameter differences could be hard to remember. Maybe next time
|
||||||
|
eshell-prefer-lisp-functions nil))
|
||||||
|
|
||||||
|
(use-package eat
|
||||||
|
:config
|
||||||
|
(define-key eat-mode-map (kbd "C-c C-d") #'eat-self-input)
|
||||||
|
;; :hook
|
||||||
|
;; (eshell-mode . #'eat-eshell-mode)
|
||||||
|
)
|
||||||
|
|
||||||
|
(provide 'packages)
|
|
@ -0,0 +1,287 @@
|
||||||
|
;; NOTE:
|
||||||
|
;; This file is generated from init.org
|
||||||
|
|
||||||
|
(defvar ./variable-pitch-display-font
|
||||||
|
"Fira Sans"
|
||||||
|
"Font used for titles")
|
||||||
|
|
||||||
|
(defvar ./face-fixed-pitch
|
||||||
|
'(:foundry "apple" :family "Fira Code" :height 160)
|
||||||
|
"Contents to be passed to (`set-face-attribute' 'fixed-pitch nil [...]) ")
|
||||||
|
(defvar ./face-variable-pitch
|
||||||
|
'(:foundry "apple" :family "Inter" :height 170)
|
||||||
|
"Contents to be passed to (`set-face-attribute' 'variable-pitch nil [...]) ")
|
||||||
|
|
||||||
|
(load (locate-user-emacs-file "dotslash-local-pre.el") :no-error :no-message)
|
||||||
|
|
||||||
|
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
|
||||||
|
(defun display-startup-echo-area-message ()
|
||||||
|
(message (format "Emacs %s loaded from %s in %s"
|
||||||
|
emacs-version user-emacs-directory (emacs-init-time))))
|
||||||
|
|
||||||
|
(setq initial-scratch-message
|
||||||
|
(concat ";; *SCRATCH*\n"
|
||||||
|
";; C-c C-b (eval-buffer) C-c C-r (eval-region)\n"
|
||||||
|
";; C-x C-s will let you choose where to save\n\n; "))
|
||||||
|
|
||||||
|
;; Setting this in early-init doesn't seem to work
|
||||||
|
(set-frame-position (selected-frame) 100 10)
|
||||||
|
(set-face-attribute 'default nil :height 160)
|
||||||
|
|
||||||
|
(add-to-list 'bdf-directory-list "~/Library/Fonts")
|
||||||
|
|
||||||
|
;; (custom-theme-set-faces
|
||||||
|
;; 'user
|
||||||
|
;; '(variable-pitch ((t (:inherit ./face-variable-pitch))))
|
||||||
|
;; '(fixed-pitch ((t (:inherit ./face-fixed-pitch)))))
|
||||||
|
|
||||||
|
(apply #'set-face-attribute 'variable-pitch nil ./face-variable-pitch)
|
||||||
|
(apply #'set-face-attribute 'fixed-pitch nil ./face-fixed-pitch)
|
||||||
|
(apply #'set-face-attribute 'default nil ./face-fixed-pitch)
|
||||||
|
|
||||||
|
;;(global-display-line-numbers-mode 1)
|
||||||
|
(add-hook 'prog-mode-hook (lambda () (display-line-numbers-mode 1)))
|
||||||
|
(add-hook 'text-mode-hook (lambda () (display-line-numbers-mode 1)))
|
||||||
|
|
||||||
|
;; I think this saves the last cursor pos or something
|
||||||
|
;; FIXME: doesn't work
|
||||||
|
(require 'saveplace)
|
||||||
|
(setq-default save-place t)
|
||||||
|
(setq save-place-file (expand-file-name ".places" user-emacs-directory))
|
||||||
|
|
||||||
|
(setq make-backup-files nil)
|
||||||
|
(setq auto-save-default nil)
|
||||||
|
(setq-default major-mode 'text-mode)
|
||||||
|
(setq sentence-end-double-space nil)
|
||||||
|
|
||||||
|
;; Always tabs except for *.go?
|
||||||
|
;; TODO: set up language mode packages
|
||||||
|
(setq-default c-basic-offset 4
|
||||||
|
tab-width 4
|
||||||
|
indent-tabs-mode nil)
|
||||||
|
;; Some modes
|
||||||
|
(recentf-mode 1)
|
||||||
|
(show-paren-mode 1)
|
||||||
|
(setq electric-pair-inhibit-predicate 'electric-pair-conservative-inhibit)
|
||||||
|
(electric-pair-mode 1)
|
||||||
|
(winner-mode 1)
|
||||||
|
(delete-selection-mode 1) ;; Select and type would replace the selected text
|
||||||
|
|
||||||
|
;; IDK
|
||||||
|
(add-hook 'prog-mode-hook #'subword-mode)
|
||||||
|
(add-hook 'minibuffer-setup-hook #'subword-mode)
|
||||||
|
|
||||||
|
(add-hook 'elisp-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
;; These are never used...
|
||||||
|
;; (local-set-key (kbd "C-c C-x") #'ielm)
|
||||||
|
;; (local-set-key (kbd "C-c C-c") #'eval-defun)
|
||||||
|
(local-set-key (kbd "C-c C-r") 'eval-region)
|
||||||
|
(local-set-key (kbd "C-c C-b") #'eval-buffer)))
|
||||||
|
|
||||||
|
(setq window-divider-default-right-width 8)
|
||||||
|
(setq window-divider-default-places 'right-only)
|
||||||
|
(window-divider-mode 1)
|
||||||
|
|
||||||
|
(defun ./org-insert-src (beg end)
|
||||||
|
"Insert (or wrap region with, or cancel) src block.
|
||||||
|
|
||||||
|
If cursor currently on an empty line, it is wrapped in src block, with
|
||||||
|
no other content in the src block other than the empty line, then the
|
||||||
|
src block together with the line after it (if empty) is deleted. This
|
||||||
|
undoes the effect of ./org-insert-src without active region, and
|
||||||
|
cancelling org-edit-src with C-c C-k.
|
||||||
|
|
||||||
|
Code type is prompted and `org-edit-src-code' called only for insert,
|
||||||
|
not for wrap.
|
||||||
|
|
||||||
|
Uses 'elisp' if currently in user-emacs-directory."
|
||||||
|
(interactive (if (use-region-p)
|
||||||
|
(list (region-beginning) (region-end))
|
||||||
|
(list (point-min) (point-min))))
|
||||||
|
(let ((selection (buffer-substring-no-properties beg end))
|
||||||
|
(code-type '(if (string=
|
||||||
|
(file-truename user-emacs-directory)
|
||||||
|
(file-name-directory (buffer-file-name)))
|
||||||
|
"elisp"
|
||||||
|
(read-from-minibuffer "#+BEGIN_SRC "))))
|
||||||
|
(if (< (length selection) 2)
|
||||||
|
(if (./org-empty-src-p)
|
||||||
|
;; Delete empty src block and exit
|
||||||
|
(progn
|
||||||
|
(previous-line)
|
||||||
|
(delete-line) ;; Newline also deleted
|
||||||
|
(delete-line)
|
||||||
|
(delete-line)
|
||||||
|
;; Delete empty line inserted by ./org-insert-src itself
|
||||||
|
(if (./match-line-p "")
|
||||||
|
(delete-line)))
|
||||||
|
;; Otherwise:
|
||||||
|
;; Insert src block with given code type and edit
|
||||||
|
(progn
|
||||||
|
(setq code-type (eval code-type))
|
||||||
|
(deactivate-mark)
|
||||||
|
(beginning-of-line)
|
||||||
|
(newline)
|
||||||
|
(insert (format "#+BEGIN_SRC %s\n" code-type))
|
||||||
|
(newline)
|
||||||
|
(insert "#+END_SRC\n")
|
||||||
|
(previous-line 2)
|
||||||
|
(org-edit-src-code)))
|
||||||
|
;; Wrap selected region
|
||||||
|
;;(setq code-type (eval code-type))
|
||||||
|
(goto-char beg)
|
||||||
|
(previous-line) (end-of-line)
|
||||||
|
(newline)
|
||||||
|
(insert "#+BEGIN_SRC ")
|
||||||
|
;; save-excursion doesn't seem to work here
|
||||||
|
(goto-char (+ end 11)) (end-of-line)
|
||||||
|
(newline)
|
||||||
|
(insert "#+END_SRC")
|
||||||
|
;; FIXME: putting cursor at the begin src part afterwards doesn't work
|
||||||
|
(re-search-backward "^\\s-*#\\+BEGIN_SRC")
|
||||||
|
(end-of-line))))
|
||||||
|
|
||||||
|
(defun ./match-line-p (regexp &optional move keep-pos start)
|
||||||
|
"Wrapper around string-match-p to use contents of current line.
|
||||||
|
|
||||||
|
Returns whether current line, after moving down by MOVE lines, can be
|
||||||
|
matched with REGEXP.
|
||||||
|
|
||||||
|
If REGEXP is an empty string, return t for empty line, nil otherwise.
|
||||||
|
MOVE argument is passed to `next-line'.
|
||||||
|
|
||||||
|
If REGEXP and is non-nil, REGEXP and START is passed to
|
||||||
|
`string-match-p' with no changes, and its return-value is returned
|
||||||
|
as-is.
|
||||||
|
|
||||||
|
MOVE argument is passed as-is to `next-line' immediately.
|
||||||
|
|
||||||
|
If KEEP-POS is non-nil, pass MOVE argument to `previous-line' after obtaining
|
||||||
|
contents of the required line."
|
||||||
|
(next-line move)
|
||||||
|
(let ((line (buffer-substring-no-properties (line-beginning-position) (line-end-position))))
|
||||||
|
(if keep-pos
|
||||||
|
(previous-line move))
|
||||||
|
(if (= (length regexp) 0)
|
||||||
|
(if (= (length line) 0)
|
||||||
|
t nil)
|
||||||
|
(string-match-p regexp line start))))
|
||||||
|
|
||||||
|
(defun ./org-empty-src-p ()
|
||||||
|
"Return whether point is within a org src block with a single empty line."
|
||||||
|
(let ((line))
|
||||||
|
(save-excursion
|
||||||
|
(if (./match-line-p "^\\s-*#\\+begin_src" -1)
|
||||||
|
(if (./match-line-p "" +1)
|
||||||
|
(if (./match-line-p "^\\s-*#\\+end_src" +1)
|
||||||
|
t nil) nil) nil))))
|
||||||
|
|
||||||
|
(defun ./org-split-src ()
|
||||||
|
"Split current src block into two blocks at point.
|
||||||
|
|
||||||
|
Retains src properties."
|
||||||
|
(interactive)
|
||||||
|
(insert "#+END_SRC\n\n")
|
||||||
|
(save-excursion
|
||||||
|
(re-search-backward "^\\s-*#\\+begin_src")
|
||||||
|
(defvar beginsrc (buffer-substring-no-properties (line-beginning-position) (line-end-position))))
|
||||||
|
(insert beginsrc)
|
||||||
|
(previous-line))
|
||||||
|
|
||||||
|
(defun ./load-directory (dir)
|
||||||
|
"Load *.el files in a given directory"
|
||||||
|
(let ((load-it (lambda (f)
|
||||||
|
(load-file (concat (file-name-as-directory dir) f)))))
|
||||||
|
(mapc load-it (directory-files dir nil "\\.el$"))))
|
||||||
|
|
||||||
|
(defun ./load-file-if-exists (file)
|
||||||
|
"Same as load-file but NOP if file does not exist"
|
||||||
|
(if (file-exists-p file)
|
||||||
|
(load-file file)))
|
||||||
|
|
||||||
|
(defun toggle-window-split ()
|
||||||
|
(interactive)
|
||||||
|
(if (= (count-windows) 2)
|
||||||
|
(let* ((this-win-buffer (window-buffer))
|
||||||
|
(next-win-buffer (window-buffer (next-window)))
|
||||||
|
(this-win-edges (window-edges (selected-window)))
|
||||||
|
(next-win-edges (window-edges (next-window)))
|
||||||
|
(this-win-2nd (not (and (<= (car this-win-edges)
|
||||||
|
(car next-win-edges))
|
||||||
|
(<= (cadr this-win-edges)
|
||||||
|
(cadr next-win-edges)))))
|
||||||
|
(splitter
|
||||||
|
(if (= (car this-win-edges)
|
||||||
|
(car (window-edges (next-window))))
|
||||||
|
'split-window-horizontally
|
||||||
|
'split-window-vertically)))
|
||||||
|
(delete-other-windows)
|
||||||
|
(let ((first-win (selected-window)))
|
||||||
|
(funcall splitter)
|
||||||
|
(if this-win-2nd (other-window 1))
|
||||||
|
(set-window-buffer (selected-window) this-win-buffer)
|
||||||
|
(set-window-buffer (next-window) next-win-buffer)
|
||||||
|
(select-window first-win)
|
||||||
|
(if this-win-2nd (other-window 1))))))
|
||||||
|
|
||||||
|
(defvar elpaca-installer-version 0.5)
|
||||||
|
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
|
||||||
|
(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
|
||||||
|
:files (:defaults (: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 (call-process "git" nil buffer t "clone"
|
||||||
|
(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)
|
||||||
|
(load "./elpaca-autoloads")))
|
||||||
|
(add-hook 'after-init-hook #'elpaca-process-queues)
|
||||||
|
(elpaca `(,@elpaca-order))
|
||||||
|
|
||||||
|
;; Install use-package support
|
||||||
|
(elpaca elpaca-use-package
|
||||||
|
;; Enable :elpaca use-package keyword.
|
||||||
|
(elpaca-use-package-mode)
|
||||||
|
;; Assume :elpaca t unless otherwise specified.
|
||||||
|
(setq elpaca-use-package-by-default t))
|
||||||
|
|
||||||
|
;; Block until current queue processed.
|
||||||
|
(elpaca-wait)
|
||||||
|
|
||||||
|
;;When installing a package which modifies a form used at the top-level
|
||||||
|
;;(e.g. a package which adds a use-package key word),
|
||||||
|
;;use `elpaca-wait' to block until that package has been installed/configured.
|
||||||
|
;;For example:
|
||||||
|
;;(use-package general :demand t)
|
||||||
|
;;(elpaca-wait)
|
||||||
|
|
||||||
|
(dolist (path '("dotslash-lisp" "dotslash-modules"))
|
||||||
|
(add-to-list 'load-path (locate-user-emacs-file path)))
|
||||||
|
(require 'packages)
|
||||||
|
(require 'init-highlight)
|
||||||
|
|
||||||
|
(load (locate-user-emacs-file "dotslash-local-post.el") :no-error :no-message)
|
|
@ -2,6 +2,11 @@
|
||||||
#+PROPERTY: header-args:elisp :tangle ~/.config/emacs/init.el
|
#+PROPERTY: header-args:elisp :tangle ~/.config/emacs/init.el
|
||||||
#+auto_tangle: t
|
#+auto_tangle: t
|
||||||
|
|
||||||
|
#+BEGIN_SRC elisp
|
||||||
|
;; NOTE:
|
||||||
|
;; This file is generated from init.org
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
* Variables
|
* Variables
|
||||||
|
|
||||||
#+BEGIN_SRC elisp
|
#+BEGIN_SRC elisp
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
#+PROPERTY: header-args:elisp :tangle ~/.config/emacs/dotslash-modules/packages.el
|
#+PROPERTY: header-args:elisp :tangle ~/.config/emacs/dotslash-modules/packages.el
|
||||||
#+auto_tangle: t
|
#+auto_tangle: t
|
||||||
|
|
||||||
|
|
||||||
|
#+BEGIN_SRC elisp
|
||||||
|
;; NOTE:
|
||||||
|
;; This file is generated from packages.org
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
* Helpers
|
* Helpers
|
||||||
|
|
||||||
Helper variables adopted from Doom Emacs I'm not sure if I'll ever use.
|
Helper variables adopted from Doom Emacs I'm not sure if I'll ever use.
|
||||||
|
|
Loading…
Reference in New Issue