Emacs changes... lots of them

This commit is contained in:
2025-06-08 14:06:10 +01:00
parent 4f025811bc
commit 64808681e3
7 changed files with 213 additions and 157 deletions

View File

@@ -84,22 +84,26 @@ Let's setup a few absolute essentials:
:demand t
:init
(setq auth-sources '("~/.authinfo.gpg")
auto-revert-stop-on-user-input nil
auto-revert-use-notify nil
auto-revert-verbose nil
backup-directory-alist `(("." . ,(no-littering-expand-var-file-name "saves/")))
buffer-file-coding-system 'utf-8-unix
delete-by-moving-to-trash t
global-auto-revert-non-file-buffers t
read-answer-short t
read-extended-command-predicate #'command-completion-default-include-p
remote-file-name-inhibit-delete-by-moving-to-trash t
revert-without-query '(".")
save-buffer-coding-system 'utf-8-unix
select-enable-clipboard t
use-dialog-box nil
use-file-dialog nil
use-short-answers t
user-full-name "Aryadev Chavali"
user-mail-address "aryadev@aryadevchavali.com"
warning-minimum-level :error)
:config
(fset 'yes-or-no-p 'y-or-n-p)
(global-auto-revert-mode))
#+end_src
* Custom functionality and libraries
@@ -546,6 +550,12 @@ Setup the evil package, with some opinionated settings:
evil-respect-visual-line-mode nil)
:config
(evil-mode)
(defun +evil/select-pasted ()
(interactive)
(evil-goto-mark 91)
(evil-visual-char)
(evil-goto-mark 93))
:general
(leader
"w" #'evil-window-map
@@ -569,6 +579,7 @@ Setup the evil package, with some opinionated settings:
:keymaps 'override
"gu" #'evil-upcase
"gU" #'evil-downcase
"g C-v" #'+evil/select-pasted
"M-y" #'yank-pop
"T" 'nil)
@@ -634,6 +645,8 @@ in it.
completion-category-overrides
'((file (styles flex partial-completion substring)))
completion-ignore-case t
minibuffer-prompt-properties
'(read-only t intangible t cursor-intangible t face minibuffer-prompt)
read-file-name-completion-ignore-case t
read-buffer-completion-ignore-case t)
:general
@@ -753,7 +766,7 @@ embark act more like how you wish, which I've barely touch on here.
:straight t
:general
(:keymaps 'override
"M-m" #'embark-act)
"M-/" #'embark-act)
:display
("\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
@@ -798,14 +811,13 @@ search system.
([remap imenu] #'consult-imenu
[remap switch-to-buffer] #'consult-buffer
[remap info] #'consult-info)
(leader
"'" #'consult-register)
(search-leader
"s" #'consult-line
"r" #'consult-ripgrep
"f" #'consult-fd
"o" #'consult-org-agenda
"e" #'consult-compile-error)
"e" #'consult-compile-error
"m" #'consult-register)
:config
(with-eval-after-load "vertico-multiform"
(add-multiple-to-list vertico-multiform-commands
@@ -853,7 +865,7 @@ setup some evil binds for company.
:defer t
:straight t
:hook
((prog-mode-hook eshell-mode-hook) . company-mode)
(prog-mode-hook . company-mode)
:init
(setq company-idle-delay nil
company-minimum-prefix-length 3
@@ -1011,7 +1023,7 @@ fundamental mode and call it a day.
(format "Emacs v%s - %s\n" emacs-version)
(insert))))))
#+end_src
** Blinking cursor
** Cursor and the highlighted line
Configure the blinking cursor.
#+begin_src emacs-lisp
@@ -1020,9 +1032,10 @@ Configure the blinking cursor.
:init
(setq blink-cursor-delay 0.2)
:config
(blink-cursor-mode))
(blink-cursor-mode -1)
(global-hl-line-mode))
#+end_src
** Mode line
** Better Mode line
The mode line is the little bar at the bottom of the buffer, just
above the minibuffer. It can store essentially any text, but
generally details about the current buffer (such as name, major mode,
@@ -1435,6 +1448,7 @@ to the kill ring and bind it to "Y".
(when date
(setq date (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))
(kill-new (format-time-string "%Y-%m-%d" date))))))
(with-eval-after-load "evil-collection"
(evil-collection-calendar-setup)))
#+end_src
@@ -1464,6 +1478,9 @@ from the remote server.
(nmap
:keymaps 'notmuch-search-mode-map
"f" #'+mail/flag-thread)
(nmmap
:keymaps 'notmuch-hello-mode-map
"t" #'notmuch-search-by-tag)
:init
(defconst +mail/local-dir (no-littering-expand-var-file-name "mail/"))
(setq notmuch-show-logo nil
@@ -1555,7 +1572,9 @@ Here I setup dired with a few niceties
dired-omit-files "^\\." ; dotfiles
dired-omit-verbose nil
dired-dwim-target t
dired-recursive-copies 'always
dired-kill-when-opening-new-dired-buffer t
dired-deletion-confirmer 'y-or-n-p
dired-auto-revert-buffer t)
:general
(nmmap
@@ -1825,6 +1844,8 @@ them.
("\\*eshell\\*"
(display-buffer-same-window)
(reusable-frames . t))
:hook
(eshell-mode-hook . completion-preview-mode)
:init
(defun +eshell/banner-message ()
(concat (shell-command-to-string "fortune") "\n"))
@@ -1855,14 +1876,14 @@ them.
(local-leader
:keymaps 'eshell-mode-map
"g" (proc-int
(let ((buffer (current-buffer)))
(eshell/goto)
(with-current-buffer buffer
(eshell-send-input))))
(let ((buffer (current-buffer)))
(eshell/goto)
(with-current-buffer buffer
(eshell-send-input))))
"l" (proc-int
(eshell-return-to-prompt)
(insert "ls")
(eshell-send-input))
(eshell-return-to-prompt)
(insert "ls")
(eshell-send-input))
"c" #'+eshell/good-clear
"k" #'eshell-kill-process))))
#+end_src
@@ -1883,7 +1904,7 @@ internals without autoloading.
(use-package eshell-prompt
:load-path "elisp/"
:config
(setq eshell-prompt-function #'+eshell-prompt/make-prompt))
(setq eshell-prompt-function #'eshell-prompt/make-prompt))
#+end_src
*** EShell additions
Using my external library
@@ -2118,6 +2139,13 @@ IBuffer is the dired of buffers. Nothing much else to be said.
:general
(buffer-leader
"i" #'ibuffer)
:init
(setq ibuffer-formats
'((mark modified read-only locked
" " (name 40 40 :left :elide)
" " (size 8 -1 :right)
" " (mode 18 18 :left :elide) " " filename-and-process)
(mark " " (name 16 -1) " " filename)))
:config
(with-eval-after-load "evil-collection"
(evil-collection-ibuffer-setup)))
@@ -2396,12 +2424,15 @@ in an Emacs-only map.
:straight (:host github :repo "unmonoqueteclea/jira.el")
:init
(setq jira-base-url "https://reframe.atlassian.net")
(with-eval-after-load "evil"
(evil-set-initial-state 'jira-detail-mode 'motion)
(evil-set-initial-state 'jira-issues-mode 'motion))
:general
(app-leader
"j" #'jira-issues)
(nmmap
(mmap
:keymaps 'jira-issues-mode-map
"M-RET" #'jira-issues-actions-menu))
"@" #'jira-issues-actions-menu))
#+end_src
* Text packages
Standard packages and configurations for dealing with text, usually
@@ -2416,6 +2447,9 @@ into text-mode.
(use-package flyspell
:defer t
:hook ((org-mode-hook text-mode-hook) . flyspell-mode)
:init
(setq flyspell-issue-message-flag nil
flyspell-issue-welcome-flag nil)
:general
(nmmap
:keymaps 'text-mode-map
@@ -2713,7 +2747,7 @@ description I give won't do it justice.
:hook ((scheme-mode-hook lisp-mode-hook emacs-lisp-mode-hook)
. aggressive-indent-mode))
#+end_src
** compile-mode
** Compilation
Compilation mode is an incredibly useful subsystem of Emacs which
allows one to run arbitrary commands. If those commands produce
errors (particularly errors that have a filename, column and line)
@@ -2757,8 +2791,21 @@ so you can actually read the text.
:init
(setq compilation-scroll-output 'first-error
compilation-context-lines nil
compilation-always-kill t
compilation-ask-about-save nil
next-error-recenter '(4)
next-error-highlight 'fringe-arrow)
:config
(require 'notifications)
(defun +compilation/notify (buffer str)
(with-current-buffer buffer
(let ((cwd default-directory)
(command compile-command))
(notifications-notify
:title (format "%s\n%s" command cwd)
:body str))))
(add-to-list 'compilation-finish-functions #'+compilation/notify)
(add-hook 'compilation-filter-hook #'ansi-color-compilation-filter))
#+end_src
** xref
@@ -3006,6 +3053,7 @@ write the code.
(org-leader
"l" #'org-store-link
"a" #'org-agenda
"d" #'org-babel-detangle
"i" #'org-insert-last-stored-link
"o" #'org-open-at-point)
@@ -3015,18 +3063,18 @@ write the code.
"TAB" #'org-cycle)
(local-leader
:states '(normal motion)
:keymaps 'org-mode-map
"r" #'org-list-repair
"d" #'org-date-from-calendar
"d" #'org-deadline
"s" #'org-schedule
"t" #'org-todo
"r" #'org-list-repair
"," #'org-priority
"T" #'org-babel-tangle
"i" #'org-insert-structure-template
"p" #'org-latex-preview
"s" #'org-property-action
"e" #'org-export-dispatch
"o" #'org-edit-special
"T" #'org-babel-tangle
"S" #'org-property-action
"R" #'org-refile
"O" #'org-open-at-point)
@@ -3076,18 +3124,21 @@ a very tidy way to manage your time.
(find-file it))))
(nmmap
:keymaps 'org-agenda-mode-map
"zd" #'org-agenda-day-view
"zw" #'org-agenda-week-view
"zm" #'org-agenda-month-view
"gd" #'org-agenda-goto-date
"RET" #'org-agenda-switch-to
"," #'org-agenda-goto-date
"." #'org-agenda-goto-today
"J" #'org-agenda-later
"K" #'org-agenda-earlier
"t" #'org-agenda-todo
"." #'org-agenda-goto-today
"," #'org-agenda-goto-date
"RET" #'org-agenda-switch-to
"d" #'org-agenda-deadline
"gd" #'org-agenda-goto-date
"q" #'org-agenda-quit
"r" #'org-agenda-redo))
"r" #'org-agenda-redo
"s" #'org-agenda-schedule
"t" #'org-agenda-todo
"zd" #'org-agenda-day-view
"zm" #'org-agenda-month-view
"zw" #'org-agenda-week-view
"f" #'org-agenda-filter-by-tag))
#+end_src
*** Org Capture
Org capture provides a system for quickly "capturing" some information
@@ -4129,11 +4180,7 @@ I may disagree with some. So I use it in a mode to mode basis.
#+begin_src emacs-lisp
(use-package evil-collection
:after evil
:straight t
:init
;; (setq evil-collection-mode-list '(eww flycheck magit calendar notmuch
;; ibuffer proced calc image))
)
:straight t)
#+end_src
*** Evil number
Increment/decrement a number at point like Vim does, but use bindings
@@ -4222,27 +4269,6 @@ but I prefer Emacs' hence the configuration here.
#+begin_src emacs-lisp
(use-package register
:config
(defvar +register/--choice 0)
(defconst +register/quick-registers
(list ?a ?s ?d ?f ?g ?h ?j ?k ?l))
(defun +register/--quick-jump ()
(let ((choice (nth +register/--choice +register/quick-registers)))
(if (assoc choice register-alist)
(jump-to-register choice))))
(defun +register/jump-prev ()
(interactive)
(setq +register/--choice (mod (- +register/--choice 1)
(length +register/quick-registers)))
(+register/--quick-jump))
(defun +register/jump-next ()
(interactive)
(setq +register/--choice (mod (+ 1 +register/--choice)
(length +register/quick-registers)))
(+register/--quick-jump))
:general
(leader
"," #'+register/jump-prev
"." #'+register/jump-next)
(nmmap
"m" #'point-to-register
"'" #'jump-to-register))

View File

@@ -67,8 +67,8 @@ extreme end to CENTRE-SEGMENT."
(:eval (bml/--generate-padding
bml/left-segment))
,bml/centre-segment
(:eval (bml/--generate-padding
bml/right-segment))
;; NOTE: Emacs 30!
mode-line-format-right-align
,bml/right-segment)))
(provide 'better-mode-line)

View File

@@ -55,9 +55,7 @@ Uses tramp to figure out if we're in sudo mode or not. "
(let ((wrapped-dir (concat "/sudo::" default-directory)))
(eshell/cd wrapped-dir)))
((string= user "root")
(thread-last 'localname
(file-remote-p default-directory)
eshell/cd)))))
(eshell/cd (file-remote-p default-directory 'localname))))))
;; Additional functions
(defun +eshell/at-cwd (&optional arg)
@@ -80,6 +78,19 @@ Pass argument to `+eshell/open'."
collect
(cons (buffer-name buffer) buffer)))
(defun +eshell/--choose-instance ()
(let* ((current-instances (+eshell/--current-instances))
(answer (completing-read "Enter name: " (mapcar #'car current-instances)))
(result (assoc answer current-instances)))
(cond
(result (switch-to-buffer (cdr result))
(cdr result))
((not (string= answer ""))
(let ((eshell-buffer-name (format "*%s-eshell*" answer)))
(eshell nil)))
(t
(eshell)))))
(defun +eshell/open (&optional arg)
"Open an instance of EShell, displaying it.
@@ -89,35 +100,28 @@ Otherwise, create an instance with the name given.
If `arg' is non nil, then always prompt user to select an instance."
(interactive "P")
(let ((current-instances (+eshell/--current-instances))
(buffer nil))
(cond
((and (null current-instances)
(null arg))
(setq buffer (eshell)))
((and (= (length current-instances) 1)
(null arg))
(setq buffer (cdar current-instances))
(switch-to-buffer (cdar current-instances)))
(t
(let* ((answer (completing-read "Enter name: " (mapcar #'car current-instances)))
(result (assoc answer current-instances)))
(cond
(result (switch-to-buffer (cdr result))
(setq buffer (cdr result)))
((not (string= answer ""))
(let ((eshell-buffer-name (format "*%s-eshell*" answer)))
(setq buffer (eshell nil))))
(t
(setq buffer (eshell)))))))
(if (and (consp arg) (> (car arg) 4))
(with-current-buffer buffer
(thread-last (read-file-name "Enter directory: ")
file-name-directory
list
eshell/cd)
(eshell-send-input)))
buffer))
(cond
((null arg)
;; No arg => Choose a default instance
(let* ((candidates (+eshell/--current-instances))
(default-cand (assoc "*eshell*" candidates #'string=))
(vacuous-cand (car candidates)))
(if-let ((cand (or default-cand vacuous-cand)))
(switch-to-buffer (cdr cand))
(eshell))))
((= (car arg) 4)
;; Arg => Choose an instance
(+eshell/--choose-instance))
(t
;; Double arg => Choose an instance then choose the directory
(let ((instance (+eshell/--choose-instance)))
(with-current-buffer instance
(thread-last (read-file-name "Enter directory: ")
file-name-directory
list
eshell/cd)
(eshell-send-input))
instance))))
(provide 'eshell-additions)
;;; eshell-additions.el ends here

View File

@@ -28,13 +28,41 @@
"Prompt for user to input.")
(defvar ep/dir-colour "deepskyblue")
(defvar ep/success-colour "forestgreen")
(defvar ep/success-colour "green2")
(defvar ep/failure-colour "red")
(defvar ep/branch-name-colour "LightSalmon")
(defvar ep/pipe-colour "green2")
(defvar ep/pipe-colour "green4")
(defvar ep/ahead-colour "dodger blue")
(defvar ep/remote-colour "DarkGoldenrod")
(defun ep/make-prompt ()
(let ((git (ep/--git-status)))
(thread-last
`(("┌──" :foreground ,ep/pipe-colour)
"["
(,(ep/--user-and-remote) :foreground ,ep/remote-colour)
(,(abbreviate-file-name (tramp-file-local-name (eshell/pwd)))
:foreground ,ep/dir-colour)
,(if (string= git "")
""
(concat "]─[" git))
"]"
"\n"
("└─>" :foreground ,ep/pipe-colour)
(,ep/user-prompt :foreground ,(ep/--colour-on-last-command)))
(mapconcat
#'(lambda (item)
(if (listp item)
(propertize (car item)
'font-lock-face (cdr item)
'front-sticky '(font-lock-face read-only)
'rear-nonsticky '(font-lock-face read-only))
item))))))
(defun ep/--with-fg-colour (s colour)
"Helper which propertises a string `s' with foreground colour `colour'"
(propertize s 'font-lock-face `(:foreground ,colour)))
(defun ep/--colour-on-last-command ()
"Returns an Emacs colour based on ESHELL-LAST-COMMAND-STATUS."
(if (zerop eshell-last-command-status)
@@ -57,38 +85,58 @@ behind or ahead the local repository is."
(status (nth 3 branch-status))
(diff (cl-position "by" branch-status :test #'string=)))
(if (null diff)
(propertize "=" 'font-lock-face `(:foreground ,ep/success-colour))
(ep/--with-fg-colour "=" ep/success-colour)
(let ((n (nth (+ 1 diff) branch-status)))
(concat
(cond
((string= status "ahead")
(propertize "" 'font-lock-face `(:foreground ,ep/ahead-colour)))
(ep/--with-fg-colour "" ep/ahead-colour))
((string= status "behind")
(propertize "" 'font-lock-face `(:foreground ,ep/failure-colour))))
(ep/--with-fg-colour "" ep/failure-colour)))
n)))))
(defun ep/--git-change-status ()
"Returns a propertized string for the condition of the worktree in
a repository. If there are no changes i.e. the worktree is clean
then a green tick is returned, but if there are changes then the
number of files affected are returned in red."
a repository.
If there are no changes i.e. the worktree is clean then a green tick is
returned.
If there are changes then we characterise it by the following parameters:
- staged changes in green
- unstaged but tracked changes in blue
- untracked files in red
"
(let* ((git-cmd "git status -s")
(command-output (split-string (shell-command-to-string git-cmd) "\n"))
(changed-files (- (length command-output) 1)))
(if (= changed-files 0)
(propertize ""
'font-lock-face
`(:foreground ,ep/success-colour))
(propertize (number-to-string changed-files)
'font-lock-face
`(:foreground ,ep/failure-colour)))))
(command-output
(thread-first (shell-command-to-string git-cmd)
(split-string "\n")
butlast))
(status-codes (mapcar #'(lambda (s) (cons (substring s 0 1) (substring s 1 2)))
command-output))
(filter-f (lambda (x) (not (or (string= x "?") (string= x " ")))))
(total (length status-codes))
(staged (cl-count-if (lambda (x) (funcall filter-f (car x))) status-codes))
(modified (cl-count-if (lambda (x) (funcall filter-f (cdr x))) status-codes))
(not-tracked (cl-count-if (lambda (x) (string= (cdr x) "?")) status-codes)))
(if (= total 0)
(ep/--with-fg-colour "" ep/success-colour)
(thread-last
(list
(ep/--with-fg-colour (number-to-string staged) ep/success-colour)
(ep/--with-fg-colour (number-to-string modified) ep/ahead-colour)
(ep/--with-fg-colour (number-to-string not-tracked) ep/failure-colour))
(cl-remove-if #'(lambda (s) (string= s "0")))
(mapconcat #'(lambda (s) (concat s "/")))))))
(defun ep/--git-branch-name ()
"Get the branch name of the current working directory. W"
"Get the branch name of the current working directory.
If a deteached head, return the SHA."
(let* ((branch-name (thread-last
(split-string (shell-command-to-string "git branch") "\n")
(cl-remove-if (lambda (s) (= (length s) 0)))
(cl-find-if (lambda (s) (string= "*" (substring s 0 1))))))
(cl-remove-if #'(lambda (s) (= (length s) 0)))
(cl-find-if #'(lambda (s) (string= "*" (substring s 0 1))))))
(branch-name (if (null branch-name) nil
(substring branch-name 2))))
(cond
@@ -100,57 +148,33 @@ number of files affected are returned in red."
(t branch-name))))
(defun ep/--git-status ()
"Returns a completely formatted string of
form (BRANCH-NAME<CHANGES>[REMOTE-STATUS])."
"Returns a completely formatted string of form
BRANCH-NAME(REMOTE-STATUS)(CHANGES)."
(let ((git-branch (ep/--git-branch-name)))
(if (null git-branch)
""
(format
"%s(%s)(%s)"
(propertize git-branch 'font-lock-face `(:foreground ,ep/branch-name-colour))
(ep/--with-fg-colour git-branch ep/branch-name-colour)
(ep/--git-remote-status)
(ep/--git-change-status)))))
(defun ep/--user-and-remote ()
"If in a remote directory, return a string representing that host,
otherwise empty string."
(if (file-remote-p default-directory)
(let ((user (file-remote-p default-directory 'user))
(host (file-remote-p default-directory 'host)))
(if user
(format "%s@%s " user host)
(concat host " ")))
(concat
(if user
(format "%s@%s" user host)
host)
":"))
""))
(defun ep/make-prompt ()
(let ((git (ep/--git-status)))
(mapconcat
(lambda (item)
(if (listp item)
(propertize (car item)
'font-lock-face (cdr item)
'front-sticky '(font-lock-face read-only)
'rear-nonsticky '(font-lock-face read-only))
item))
(list
`("┌──"
:foreground ,ep/pipe-colour)
"["
`(,(ep/--user-and-remote)
:foreground ,ep/remote-colour)
`(,(abbreviate-file-name (tramp-file-local-name (eshell/pwd)))
:foreground ,ep/dir-colour)
(if (string= git "")
""
(concat "]─[" git))
"]"
"\n"
`("└─>"
:foreground ,ep/pipe-colour)
(list ep/user-prompt ':foreground (ep/--colour-on-last-command))))))
(provide 'eshell-prompt)
;;; eshell-prompt.el ends here
;; Local Variables:
;; read-symbol-shorthands: (("ep" . "+eshell-prompt"))
;; read-symbol-shorthands: (("ep" . "eshell-prompt"))
;; End:

View File

@@ -12,6 +12,7 @@
'(child-frame-border ((t (:background "white"))))
'(company-preview ((t (:foreground "wheat" :background "blue4"))))
'(company-preview-common ((t (:inherit company-preview :foreground "grey"))))
'(company-template-field ((t (:inherit company-preview :foreground "grey" :slant italic))))
'(company-tooltip ((t (:background "black" :foreground "white"))))
'(company-tooltip-annotation ((t (:foreground "grey"))))
'(company-tooltip-selection ((t (:background "grey31"))))

View File

@@ -53,7 +53,7 @@ Returns a list of files with the directory preprended to them."
(thread-last (+search/get-all-candidates)
(cl-remove-if #'directory-name-p)
(mapcar #'(lambda (x) (concat "\"" x "\" ")))
(string-join)))
string-join))
(defun +search/search-all ()
(interactive)
@@ -61,7 +61,7 @@ Returns a list of files with the directory preprended to them."
(candidates (+search/-format-grep-candidates)))
(thread-last candidates
(format "grep --color=auto -nIHZe \"%s\" -- %s" term)
(grep))
grep)
(next-error)))
(provide 'search)

View File

@@ -45,10 +45,10 @@
(load bootstrap-file nil 'nomessage))
;; Setup benchmark to get current statistics - enable only if profiling.
;; (straight-use-package 'benchmark-init)
;; (require 'benchmark-init)
;; (add-hook 'after-init-hook 'benchmark-init/deactivate)
;; (benchmark-init/activate)
(straight-use-package 'benchmark-init)
(require 'benchmark-init)
(add-hook 'after-init-hook 'benchmark-init/deactivate)
(benchmark-init/activate)
(setq use-package-enable-imenu-support t
use-package-always-demand nil
@@ -77,6 +77,7 @@
(+literate/load-config)
(when (daemonp)
;; No need to lazy load this stuff
(require 'general)
(require 'evil)
(require 'dired)
@@ -86,7 +87,6 @@
(require 'org)
(require 'company)
(require 'eshell)
(require 'org)
(require 'eglot))
(setq gc-cons-threshold (* 100 1024 1024) ; ~100MiB
@@ -95,7 +95,8 @@
;; FIXME: Problem with memory-report after running Emacs for a
;; bit, causes a Lisp nesting error, so I just set it up really
;; high so it doesn't reach that.
max-lisp-eval-depth 999999)
max-lisp-eval-depth 999999
garbage-collection-messages t)
(provide 'init)
;;; init.el ends here