A lightweight, literate Emacs 29+ ONLY configuration. Recently become slightly less lightweight and slightly more space-faring and evil…
To install, open this file in Emacs 29+ & evaluate the code block below, by
placing the cursor in between the #+begin_src and #+end_src lines and then
pressing C-c C-c.
(org-babel-tangle) (load init-file)This will “tangle” all the code blocks below into ~/.emacs.d/init.el and then
evaluate it.
Be sure to back up your current ~/.emacs.d with something like mv
~/.emacs.d{,.bak}.
This is part of Emacs from version 29 and this configuration depends on it, so turn it on first.
(setq use-package-enable-imenu-support t
use-package-always-defer t
use-package-verbose t)
(require 'use-package)(add-hook 'after-init-hook 'global-auto-revert-mode) ;; reload if file changed on disk(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))
(setq auto-save-timeout 5)
(setq auto-save-visited-mode t)(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq backup-by-copying t) ;; copy files, don't rename them.
(setq delete-old-versions t)
(setq kept-new-versions 12)
(setq kept-old-versions 12)(setq ring-bell-function 'ignore)
(setq visible-bell 1)(setq bookmark-save-flag 1) ;; always save bookmarks to file(setq select-enable-clipboard t)
;; (setq select-enable-primary t) ;; breaks standard yank meaning that following
;; doesn't work as expected:
(delete-selection-mode t)
(setq x-select-enable-clipboard-manager nil)
(setq save-interprogram-paste-before-kill t)(setq c-default-style "bsd")
(setq c-basic-offset 4)
(setq css-indent-offset 2)
(setq js-indent-level 2)
;; If indent-tabs-mode is t, it may use tab, resulting in mixed spaces and tabs
(setq-default indent-tabs-mode nil)
;; make tab key do indent first then completion.
(setq-default tab-always-indent 'complete)(add-hook 'after-init-hook 'column-number-mode)Place point after complilation error
(setq compilation-scroll-output 'first-error);; I'm using icomplete for my completions, and so set this to nil to avoid
;; duplicate completions. Set this to true if not using an alternative for
;; completions. ie) icomplete, ido, vertico, ivy, helm, etc
(setq completion-auto-help nil)
(setq completion-show-help nil) ; refers to the msg at the top of the buffer
(setq completion-auto-wrap t)
(setq completion-auto-select nil) ; means focus doesn't go to the buffer
(setq completions-format 'one-column)
(setq completions-header-format nil) ; remove the rest of the header msg
(setq completions-max-height 22)
(setq completion-styles '(initials flex partial-completion))(setq read-answer-short t)
(setq read-buffer-completion-ignore-case t)
(setq read-file-name-completion-ignore-case t)(setq custom-file (expand-file-name "custom.el" user-emacs-directory))(setq backward-delete-char-untabify-method 'all)(setopt dictionary-server "dict.org");; https://emacs.stackexchange.com/a/31061
(when (equal system-type 'windows-nt)
(if (file-readable-p "C:/Program Files/Emacs/x86_64/bin/emacsclient.exe")
(setq-default with-editor-emacsclient-executable "C:/Program Files/Emacs/x86_64/bin/emacsclient.exe")
(setq-default with-editor-emacsclient-executable nil)))(setq disabled-command-function nil) ;; enable all "advanced" features(setq-default buffer-file-coding-system 'utf-8-unix)
(setq-default default-buffer-file-coding-system 'utf-8-unix)
(setq coding-system-for-read 'utf-8-unix)
(setq coding-system-for-write 'utf-8-unix)
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8-unix)
(prefer-coding-system 'utf-8-unix)(setq epa-file-cache-passphrase-for-symmetric-encryption t)
(setf epg-pinentry-mode 'loopback)(setq require-final-newline t) ;; useful for crontab(setq history-length t) ; no truncation
(setq history-delete-duplicates t)(setq inhibit-startup-screen t)
(setq initial-scratch-message nil)
(setq initial-major-mode 'fundamental-mode)(setq kill-do-not-save-duplicates t)(setq minibuffer-eldef-shorten-default t) ; help at point(setq apropos-do-all t)(setq message-log-max 10000)(setq mouse-yank-at-point t)Compile elc files as needed, in a deferred/async manner.
(when (fboundp 'native-compile-async)
(setq comp-deferred-compilation t
comp-deferred-compilation-black-list '("/mu4e.*\\.el$")))Dealing with system-wide packages:
Some packages like for example mu4e are located in /usr and need root permissions to be compiled, for them you can run
sudo emacs -Q -batch -L . -f batch-native-compile *.el(setq create-lockfiles nil) ;; prevent creation of .#myfile.ext(setq password-cache t) ; enable password caching
(setq password-cache-expiry 3600) ; for one hour (time in secs)(setq set-mark-command-repeat-pop t) ;; repeating C-SPC after popping, pops it(setq load-prefer-newer t) ;; if init.elc is older, use newer init.el;; (when (executable-find "rg") (setq grep-program "rg"))
;; (when (executable-find "fd") (setq find-program "fd"))
(when (executable-find "aspell") (setq ispell-program-name "aspell"))First install GnuWin32 binaries from here.
Or if you want all the GNU tools on your Windows box - use this.
(setq find-program "C:/Program Files (x86)/GnuWin32/bin/find.exe")
(setq grep-program "C:/Program Files (x86)/GnuWin32/bin/grep.exe")
(setq xargs-program "C:/Program Files (x86)/GnuWin32/bin/xargs.exe")(setq repeat-on-final-keystroke t)This variables are added to the end of this file.
(setq safe-local-variable-values
'((eval setq org-confirm-babel-evaluate 'nil)
(eval setq init-file (expand-file-name "init.el" user-emacs-directory))
(eval add-hook 'after-save-hook 'org-html-export-to-html nil t)
(eval add-hook 'after-save-hook 'org-latex-export-to-pdf nil t)
(eval add-hook 'after-save-hook 'org-twbs-export-to-pdf nil t)
(eval add-hook 'after-save-hook 'org-babel-tangle nil t)
(eval add-hook 'after-save-hook (lambda nil (org-export-to-file 'html "index.html") (org-latex-export-to-pdf)) nil t)
(org-html-validation-link)))(setq scroll-step 4)
(setq scroll-margin 2)
(setq scroll-conservatively 4)
(setq scroll-preserve-screen-position t)(pixel-scroll-precision-mode)(setq sentence-end-double-space nil)(setq sort-fold-case t)(set-default 'truncate-lines t)(setq undo-limit 80000000)
(setq undo-strong-limit 90000000)(add-to-list 'desktop-locals-to-save 'buffer-undo-list)(setq uniquify-buffer-name-style 'forward)
(setq uniquify-strip-common-suffix t)
(setq uniquify-after-kill-buffer-p t)(setq user-full-name "Toby Slight")
(setq user-mail-address "tslight@pm.me")(setq view-read-only t) ; scroll with SPC & S-SPChttps://stackoverflow.com/a/7998271 https://emacs.stackexchange.com/a/52721 https://emacs.stackexchange.com/q/39034
;; https://stackoverflow.com/a/43972522
(setq split-width-threshold 0)
(setq split-height-threshold nil)
(setq split-window-preferred-function 'split-window-really-sensibly)
(setq auto-window-vscroll nil)https://www.reddit.com/r/emacs/comments/l42oep/suppress_nativecomp_warnings_buffer/
(setq warning-minimum-level :error)
(setq warning-suppress-types '((comp) (comp) (comp)))
(setq comp-async-report-warnings-errors 'nil)
(setq native-comp-async-report-warnings-errors 'nil)(fset 'yes-or-no-p 'y-or-n-p) ;; never have to type full word
(setq confirm-kill-emacs 'y-or-n-p)(keymap-global-set "C-<" 'beginning-of-buffer) ; makes more sense for spcdt kbd
(keymap-global-set "C->" 'end-of-buffer) ; makes more sense for spcdt kbd
(keymap-global-set "C-x C-b" 'ibuffer)
(keymap-global-set "C-c f r" 'rename-visited-file)
(bind-key "k" (lambda () (interactive) (kill-buffer (current-buffer))) ctl-x-map)(keymap-global-set "C-%" 'query-replace-regexp) ; makes more sense for spcdt kbd
(keymap-global-set "C-z" 'zap-up-to-char) ; suspend is still bound to C-x C-z
(keymap-global-set "M-z" 'zap-to-char)Remap some default to saner options
(bind-key* "C-;" 'comment-line)
(bind-key* "M-;" 'comment-dwim)
(bind-key* "C-M-;" 'comment-box)Always do what I mean!
(global-set-key [remap capitalize-word] 'capitalize-dwim)
(global-set-key [remap downcase-word] 'downcase-dwim)
(global-set-key [remap upcase-word] 'upcase-dwim)(keymap-global-set "C-c f p" 'find-file-at-point)(keymap-global-set "C-<f10>" 'toggle-frame-maximized)
(keymap-global-set "C-<f11>" 'toggle-frame-fullscreen)
(keymap-global-set "C-s-f" 'toggle-frame-fullscreen)
(keymap-global-set "C-s-m" 'toggle-frame-maximized)(keymap-global-set "S-<f10>" 'menu-bar-mode);; for help modes, and simple/special modes
(keymap-set special-mode-map "n" #'forward-button)
(keymap-set special-mode-map "p" #'backward-button)
(keymap-set special-mode-map "f" #'forward-button)
(keymap-set special-mode-map "b" #'backward-button)
(keymap-set special-mode-map "n" #'widget-forward)
(keymap-set special-mode-map "p" #'widget-backward)
(keymap-set special-mode-map "f" #'widget-forward)
(keymap-set special-mode-map "b" #'widget-backward)All of these and the few M- -> C- remaps above make a lot more sense when
using the Space Cadet modifier layout in which the ctrl key is more
accessible than the alt/meta key. Also, I’m not sure why one would ever want
the shell commands to not be asynchronous…
(keymap-global-set "C-!" 'async-shell-command)
(keymap-global-set "C-&" 'async-shell-command)
(keymap-global-set "C-|" 'shell-command-on-region)
(keymap-global-set "C-$" 'ispell-word)
(keymap-global-set "M-m" 'woman) ; to kill daemon
(keymap-global-set "C-x M-c" 'save-buffers-kill-emacs) ; to kill daemon
(setq default-frame-alist '((undecorated . t)
(fullscreen . fullscreen)
(vertical-scroll-bars . nil)))
;; (setq frame-resize-pixelwise t) ;; jwm resize fix(defun ts-after-make-frame (frame)
"Add custom settings after making the FRAME."
(select-frame frame)
(load-theme 'modus-vivendi)
(if (display-graphic-p)
(cond ((eq system-type 'windows-nt) (set-frame-font "Cascadia Mono 11" nil t))
((eq system-type 'darwin) (set-frame-font "Monaco 12" nil t))
((eq system-type 'gnu/linux) (set-frame-font "Monospace 11" nil t))
(t (set-frame-font "Monospace 11" nil t)))))
(if (daemonp)
(add-hook 'after-make-frame-functions #'ts-after-make-frame (selected-frame))
(ts-after-make-frame (selected-frame)))(if (not (eq system-type 'darwin))
(if (fboundp 'menu-bar-mode) (menu-bar-mode -1)))
(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(if (fboundp 'tooltip-mode) (tooltip-mode -1))
(if (fboundp 'set-horizontal-scroll-bar-mode)
(set-horizontal-scroll-bar-mode nil))(setq display-time-format "%H:%M %a %d/%m")
(setq display-time-default-load-average 'nil)
(display-time)
(display-battery-mode)(defun ts-convert-to-unix-coding-system ()
"Change the current buffer's file encoding to unix."
(interactive)
(let ((coding-str (symbol-name buffer-file-coding-system)))
(when (string-match "-\\(?:dos\\|mac\\)$" coding-str)
(set-buffer-file-coding-system 'unix))))
(keymap-global-set "C-x RET u" 'ts-convert-to-unix-coding-system)
(defun ts-hide-dos-eol ()
"Do not show ^M in files containing mixed UNIX and DOS line endings."
(interactive)
(setq buffer-display-table (make-display-table))
(aset buffer-display-table ?\^M []))
(add-hook 'find-file-hook 'ts-hide-dos-eol)(defun ts-indent-buffer ()
"Indent the contents of a buffer."
(interactive)
(indent-region (point-min) (point-max)))
(keymap-global-set "M-i" 'ts-indent-buffer)(defun ts-last-buffer ()
"Switch back and forth between two buffers easily."
(interactive)
(switch-to-buffer (other-buffer (current-buffer) 1)))
(keymap-global-set "C-c b" 'ts-last-buffer)
(keymap-global-set "C-<escape>" 'ts-last-buffer)(defun ts-nuke-buffers ()
"Kill all buffers, leaving *scratch* only."
(interactive)
(mapc
(lambda (buffer)
(kill-buffer buffer))
(buffer-list))
(if current-prefix-arg
(delete-other-windows)))
(keymap-global-set "C-c M-n" 'ts-nuke-buffers)(defun ts-remove-from-buffer (string)
"Remove all occurences of STRING from the whole buffer."
(interactive "sString to remove: ")
(save-match-data
(save-excursion
(let ((count 0))
(goto-char (point-min))
(while (re-search-forward string (point-max) t)
(setq count (+ count 1))
(replace-match "" nil nil))
(message (format "%d %s removed from buffer." count string))))))
(keymap-global-set "C-c k" 'ts-remove-from-buffer)(defun ts-save-buffers-silently ()
"Save all open buffers without prompting."
(interactive)
(save-some-buffers t)
(message "Saved all buffers :-)"))
(keymap-global-set "C-c s" 'ts-save-buffers-silently)Some handy functions to make aligning symbols less painful.
(defun ts-align-symbol (begin end symbol)
"Align any SYMBOL in region (between BEGIN and END)."
(interactive "r\nsEnter align symbol: ")
(align-regexp begin end (concat "\\(\\s-*\\)" symbol) 1 1))
(keymap-global-set "C-c a" 'ts-align-symbol)
(defun ts-align-numbers (begin end)
"Align numbers in region (between BEGIN and END)."
(interactive "r")
(ts-align-symbol begin end "[0-9]+"))
(keymap-global-set "C-c #" 'ts-align-numbers)
(defadvice align-regexp (around align-regexp-with-spaces activate)
"Force alignment commands to use spaces, not tabs."
(let ((indent-tabs-mode nil)) ad-do-it))This function only applies to comment blocks, comments, example blocks and paragraphs. Also, as a special case, re-align table when point is at one.
(defun ts-fill-or-unfill ()
"Like `fill-paragraph', but unfill if used twice."
(interactive)
(let ((fill-column
(if (eq last-command 'ts-fill-or-unfill)
(progn (setq this-command nil)
(point-max))
fill-column)))
(call-interactively #'fill-paragraph)))
(defun ts-unfill-region (beg end)
"Unfill the region from BEG to END.
Joining text paragraphs into a single logical line. This is
useful, e.g., for use with function `visual-line-mode'."
(interactive "*r")
(let ((fill-column (point-max)))
(fill-region beg end)))
(global-set-key [remap fill-paragraph] 'ts-fill-or-unfill)
(keymap-global-set "C-M-q" 'ts-unfill-region)
(setq-default fill-column 79)
(add-hook 'org-mode-hook 'auto-fill-mode)
(add-hook 'text-mode-hook 'auto-fill-mode)(defun ts-move-beginning-of-line ()
"Move point back to indentation.
If there is any non blank characters to the left of the cursor.
Otherwise point moves to beginning of line."
(interactive)
(if (= (point) (save-excursion (back-to-indentation) (point)))
(beginning-of-line)
(back-to-indentation)))
(global-set-key [remap move-beginning-of-line] 'ts-move-beginning-of-line)(defun ts-delete-inside-delimiters (arg)
"Deletes the text within parentheses, brackets or quotes.
With prefix ARG, delete delimiters too."
(interactive "P")
;; Search for a match on the same line, don't delete across lines
(search-backward-regexp "[[{(<\"\']" (line-beginning-position))
(forward-char)
(let ((lstart (point)))
(search-forward-regexp "[]})>\"\']" (line-end-position))
(backward-char)
(if arg
(kill-region (- lstart 1) (+ (point) 1))
(kill-region lstart (point)))))
(keymap-global-set "C-c d" 'ts-delete-inside-delimiters)(defun ts-generate-numbered-list (start end char)
"Create a numbered list from START to END. Using CHAR as punctuation."
(interactive "nStart number:\nnEnd number:\nsCharacter:")
(let ((x start))
(while (<= x end)
(insert (concat (number-to-string x) char))
(newline)
(setq x (+ x 1)))))(defun ts-kill-region (arg)
"Cut region or current ARG lines to kill ring."
(interactive "p")
(let (p1 p2)
(if (use-region-p)
(progn (setq p1 (region-beginning))
(setq p2 (region-end)))
(progn (setq p1 (line-beginning-position))
(setq p2 (line-beginning-position (+ arg 1)))))
(kill-region p1 p2)))
(global-set-key [remap kill-region] 'ts-kill-region)(defun ts-kill-ring-save (arg)
"Copy region or current ARG lines to kill ring."
(interactive "p")
(let (p1 p2)
(if (use-region-p)
(progn (setq p1 (region-beginning))
(setq p2 (region-end)))
(progn (setq p1 (line-beginning-position))
(setq p2 (line-beginning-position (+ arg 1)))))
(kill-ring-save p1 p2)
(goto-char p2)))
(global-set-key [remap kill-ring-save] 'ts-kill-ring-save)(defun ts-kill-ring-save-whole-buffer ()
"Save the entire contents of the buffer to the kill ring."
(interactive)
(kill-ring-save (point-min) (point-max))
(message "Saved whole buffer to kill ring :-)"))
(keymap-global-set "C-c h" 'ts-kill-ring-save-whole-buffer)(defmacro save-column (&rest body)
`(let ((column (current-column)))
(unwind-protect (progn ,@body) (move-to-column column))))
(put 'save-column 'lisp-indent-function 0)
(defun move-line-up ()
(interactive)
(save-column (transpose-lines 1) (forward-line -2)))
(defun move-line-down ()
(interactive)
(save-column (forward-line 1) (transpose-lines 1) (forward-line -1)))
(keymap-global-set "M-p" 'move-line-up)
(keymap-global-set "M-n" 'move-line-down)(defun ts-xml-pretty-print ()
"Reformat and indent XML."
(interactive)
(save-excursion
(sgml-pretty-print (point-min) (point-max))
(indent-region (point-min) (point-max))))(defun ts-delete-this-file ()
"Delete the current file, and kill the buffer."
(interactive)
(or (buffer-file-name) (error "No file is currently being edited"))
(when (yes-or-no-p (format "Really delete '%s'?"
(file-name-nondirectory buffer-file-name)))
(delete-file (buffer-file-name) t)
(kill-this-buffer)))
(keymap-global-set "C-c f d" 'ts-delete-this-file)(defun ts-make-backup ()
"Make a backup copy of current file or dired marked files.
If in dired, backup current file or marked files."
(interactive)
(let (($fname (buffer-file-name)))
(if $fname
(let (($backup-name
(concat $fname "." (format-time-string "%y%m%d%H%M") ".bak")))
(copy-file $fname $backup-name t)
(message (concat "Backup saved at: " $backup-name)))
(if (string-equal major-mode "dired-mode")
(progn
(mapc (lambda ($x)
(let (($backup-name
(concat $x "." (format-time-string "%y%m%d%H%M") ".bak")))
(copy-file $x $backup-name t)))
(dired-get-marked-files))
(message "marked files backed up"))
(user-error "Buffer not file nor dired")))))(defun ts-make-backup-and-save ()
"Backup of current file and save, or backup dired marked files.
For detail, see `ts-make-backup'."
(interactive)
(if (buffer-file-name)
(progn
(ts-make-backup)
(when (buffer-modified-p)
(save-buffer)))
(progn
(ts-make-backup))))
(keymap-global-set "C-c f b" 'ts-make-backup-and-save)(defun ts-sudoedit (&optional arg)
"Open current or ARG file as root."
(interactive "P")
(if (or arg (not buffer-file-name))
(find-file (concat "/sudo:root@localhost:"
(read-file-name "Find file (as root): ")))
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
(keymap-global-set "C-c f s" 'ts-sudoedit)Very useful for copying ssh public keys…
(defun ts-copy-file-contents-to-clipboard (file)
"Copy a file's contents to the clipboard."
(interactive "f")
(with-current-buffer (find-file-noselect file)
(kill-new (buffer-substring-no-properties (point-min) (point-max))))
(message "Copied contents of %s to the clipboard" file))
(keymap-global-set "C-c f h" 'ts-copy-file-contents-to-clipboard)(defun ts-copy-file-name-to-clipboard (arg)
"Copy the current buffer file name to the clipboard.
With prefix ARG, omit path."
(interactive "P")
(let ((filename (if (equal major-mode 'dired-mode)
(if arg
(file-name-nondirectory
(directory-file-name
(file-name-directory default-directory)))
default-directory)
(if arg
(file-name-nondirectory buffer-file-name)
(buffer-file-name)))))
(when filename
(kill-new filename)
(message "Copied '%s' to the clipboard." filename))))
(keymap-global-set "C-c f w" 'ts-copy-file-name-to-clipboard)(defun ts-kill-buffer-other-window ()
"Kill the buffer in the last used window."
(interactive)
;; Window selection is used because point goes to a different window if more
;; than 2 windows are present
(let ((current-window (selected-window))
(other-window (get-mru-window t t t)))
(select-window other-window)
(kill-this-buffer)
(select-window current-window)))
(keymap-global-set "C-c w k" 'ts-kill-buffer-other-window)(defun ts-prev-window ()
"Go the previously used window, excluding other frames."
(interactive)
(other-window -1))
(keymap-global-set "C-x O" 'ts-prev-window)(defun ts-last-window ()
"Switch back and forth between two windows easily."
(interactive)
(let ((win (get-mru-window t t t)))
(unless win (error "Last window not found"))
(let ((frame (window-frame win)))
(raise-frame frame)
(select-frame frame)
(select-window win))))
(keymap-global-set "C-c w w" 'ts-last-window)(defun ts-toggle-maximize-window ()
"Temporarily maximize a window."
(interactive)
(if (= 1 (length (window-list)))
(jump-to-register '_)
(progn
(window-configuration-to-register '_)
(delete-other-windows))))
(keymap-global-set "C-c z" 'ts-toggle-maximize-window)(defun ts-toggle-split ()
"Switch window split from horizontally to vertically.
Or vice versa. Change right window to bottom, or change bottom
window to right."
(interactive)
(autoload 'windmove-find-other-window "windmove" nil t)
(let ((done))
(dolist (dirs '((right . down) (down . right)))
(unless done
(let* ((win (selected-window))
(nextdir (car dirs))
(neighbour-dir (cdr dirs))
(next-win (windmove-find-other-window nextdir win))
(neighbour1 (windmove-find-other-window neighbour-dir win))
(neighbour2 (if next-win
(with-selected-window next-win
(windmove-find-other-window
neighbour-dir next-win)))))
(setq done (and (eq neighbour1 neighbour2)
(not (eq (minibuffer-window) next-win))))
(if done
(let* ((other-buf (window-buffer next-win)))
(delete-window next-win)
(if (eq nextdir 'right)
(split-window-vertically)
(split-window-horizontally))
(set-window-buffer
(windmove-find-other-window neighbour-dir)
other-buf))))))))
(keymap-global-set "C-c w s" 'ts-toggle-split)(add-to-list 'comint-output-filter-functions 'ansi-color-process-output)
(defun colorize-compilation-buffer ()
"ANSI color in compilation buffer."
(ansi-color-apply-on-region compilation-filter-start (point)))
(add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)Make sure we show colors when we run commands with M-!
(defadvice display-message-or-buffer (before ansi-color activate)
"Process ANSI color codes in shell output."
(let ((buf (ad-get-arg 0)))
(and (bufferp buf)
(string= (buffer-name buf) "*Shell Command Output*")
(with-current-buffer buf
(ansi-color-apply-on-region (point-min) (point-max))))))(use-package dabbrev
:config
(setq abbrev-file-name (concat user-emacs-directory "abbrevs"))
(setq save-abbrevs 'silently)
(setq abbrev-suggest t)
(setq dabbrev-check-other-buffers t)
(setq dabbrev-eliminate-newlines t))(use-package dired
:custom
(dired-omit-files "\\`[.]?#\\|\\`[.][.]?\\'\\|^\\..+$")
(dired-dwim-target t)
(delete-by-moving-to-trash t)
(dired-use-ls-dired nil)
(dired-recursive-copies 'always)
(dired-recursive-deletes 'always)
:config
(defun ts-dired-do-delete-skip-trash (&optional arg)
(interactive "P")
(let ((delete-by-moving-to-trash nil))
(dired-do-delete arg)))
(defun ts-dired-get-size ()
"Get cumlative size of marked or current item."
(interactive)
(let ((files (dired-get-marked-files)))
(with-temp-buffer
(apply 'call-process "/usr/bin/du" nil t nil "-sch" files)
(message "Size of all marked files: %s"
(progn
(re-search-backward "\\(^[0-9.,]+[A-Za-z]+\\).*total$")
(match-string 1))))))
(defun ts-dired-beginning-of-buffer ()
"Go to first file in directory."
(interactive)
(goto-char (point-min))
(dired-next-line 2))
(defun ts-dired-end-of-buffer ()
"Go to last file in directory."
(interactive)
(goto-char (point-max))
(dired-next-line -1))
(defun ts-dired-up-directory ()
(interactive)
(find-alternate-file ".."))
(autoload 'dired-omit-mode "dired-x" nil t)
(autoload 'dired-omit-files "dired-x" nil t)
(when (eq system-type 'darwin) (setq dired-listing-switches "-alh"))
(when (eq system-type 'berkeley-unix) (setq dired-listing-switches "-alhpL"))
(when (eq system-type 'gnu/linux) (setq dired-listing-switches "-AGFhlv"))
:bind (:map dired-mode-map
(")" . dired-omit-mode)
("<" . ts-dired-beginning-of-buffer)
(">" . ts-dired-end-of-buffer)
("?" . ts-dired-get-size)
("b" . ts-dired-up-directory)
("c" . dired-do-compress-to)
("f" . 'dired-find-alternate-file)))(use-package dired-aux
:after dired
:config
(setq dired-isearch-filenames 'dwim)
(setq dired-create-destination-dirs 'ask)
(setq dired-vc-rename-file t))(use-package find-dired
:config
(setq find-ls-option '("-ls" . "-AGFhlv"))
(setq find-name-arg "-iname"))(use-package wdired
:config
(setq wdired-allow-to-change-permissions t)
(setq wdired-create-parent-directories t))(use-package doc-view-mode :defer t
:config
(setq doc-view-continuous t)
(setq doc-view-resolution 300))(use-package ediff
:config
(setq ediff-diff-options "-w")
(setq ediff-keep-variants nil)
(setq ediff-make-buffers-readonly-at-startup nil)
(setq ediff-merge-revisions-with-ancestor t)
(setq ediff-show-clashes-only t)
(setq ediff-split-window-function 'split-window-horizontally)
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
;; https://emacs.stackexchange.com/a/24602
(defun disable-y-or-n-p (orig-fun &rest args)
"Advise ORIG-FUN with ARGS so it dynamically rebinds `y-or-n-p'."
(cl-letf (((symbol-function 'y-or-n-p) (lambda () t)))
(apply orig-fun args)))
(advice-add 'ediff-quit :around #'disable-y-or-n-p)
:hook
(ediff-after-quit-hook-internal . winner-undo))Emacs Polyglot: an Emacs LSP client that stays out of your way.
https://github.com/joaotavora/eglot
The Language Server Protocol (LSP) defines the protocol used between an editor or IDE and a language server that provides language features like auto complete, go to definition, find all references etc. The goal of the Language Server Index Format (LSIF, pronounced like “else if”) is to support rich code navigation in development tools or a Web UI without needing a local copy of the source code.
https://microsoft.github.io/language-server-protocol/
sudo apt install golang python3-pip npm python3-pylsp-* clangd
# pip install python-lsp-server
# pip install python-lsp-server
go install \
github.com/rogpeppe/godef@latest \
github.com/tslight/lazygit.go/cmd/github@latest \
golang.org/x/tools/cmd/godoc@latest \
golang.org/x/tools/cmd/goimports@latest \
golang.org/x/tools/gopls@latest \
&& echo "Finished installing Go packages :-)"
sudo npm install -g \
bash-language-server \
dockerfile-language-server-nodejs \
typescript \
typescript-language-server \
vscode-langservers-extracted \
yaml-language-server \
&& echo "Finished installing Node LSP packages :-)"(use-package eglot
:custom
(fset #'jsonrpc--log-event #'ignore)
(eglot-events-buffer-size 0)
(eglot-sync-connect nil)
(eglot-connect-timeout nil)
(eglot-autoshutdown t)
(eglot-send-changes-idle-time 3)
(flymake-no-changes-timeout 5)
(eldoc-echo-area-use-multiline-p nil)
(setq eglot-ignored-server-capabilities '( :documentHighlightProvider))
:hook
(prog-mode . eglot-ensure)
(shell-script-mode . eglot-ensure))(add-hook 'emacs-lisp-mode-hook 'eldoc-mode)
(add-hook 'lisp-interaction-mode-hook 'eldoc-mode)
(add-hook 'lisp-mode-hook 'eldoc-mode)(add-hook 'after-init-hook 'electric-indent-mode)
(add-hook 'after-init-hook 'electric-pair-mode)(use-package erc
:config
(setq erc-autojoin-channels-alist '(("freenode.net" "#emacs")))
(setq erc-fill-column 80)
(setq erc-hide-list '("JOIN" "PART" "QUIT"))
(setq erc-input-line-position -2)
(setq erc-keywords '("knowayback"))
(setq erc-nick "knowayback")
(setq erc-prompt-for-password t)
(setq erc-track-enable-keybindings t)
:commands (erc))(use-package eshell
:custom
(shell-kill-buffer-on-exit t)
:config
(defun ts-eshell-prompt ()
"Custom eshell prompt."
(concat
(propertize (user-login-name) 'face `(:foreground "green" ))
(propertize "@" 'face `(:foreground "yellow"))
(propertize (system-name) `face `(:foreground "green"))
(propertize ":" 'face `(:foreground "yellow"))
(if (string= (eshell/pwd) (getenv "HOME"))
(propertize "~" 'face `(:foreground "magenta"))
(propertize (eshell/basename (eshell/pwd)) 'face `(:foreground "magenta")))
"\n"
(if (= (user-uid) 0)
(propertize "#" 'face `(:foreground "red"))
(propertize "$" 'face `(:foreground "yellow")))
(propertize " " 'face `(:foreground "white"))))
;; https://www.emacswiki.org/emacs/EshellPrompt
(setq eshell-cd-on-directory t
eshell-destroy-buffer-when-process-dies t
eshell-highlight-prompt nil
eshell-hist-ignoredups t
eshell-history-size 4096
eshell-ls-use-colors t
eshell-prefer-lisp-functions t
eshell-prefer-lisp-variables t
eshell-prompt-regexp "^[^#$\n]*[#$] "
eshell-prompt-function 'ts-eshell-prompt
eshell-review-quick-commands nil
eshell-save-history-on-exit t
eshell-smart-space-goes-to-end t
eshell-where-to-jump 'begin)
(add-to-list 'eshell-modules-list 'eshell-tramp)
:bind
("C-c e" . eshell)
:hook
(eshell-preoutput-filter-functions . ansi-color-apply))(use-package flymake-mode
:hook
(prog-mode . flymake-mode)
(json-mode . flymake-mode)
(yaml-mode . flymake-mode)
(shell-script-mode . flymake-mode))Don’t bother using this on Windows as I can’t be bothered to install Aspell for Windows.
(use-package flyspell-mode
:hook
(org-mode . flyspell-mode)
(prog-mode . flyspell-prog-mode)
(text-mode . flyspell-mode)
:bind (:map flyspell-mode-map
("C-#" . flyspell-auto-correct-previous-word)
("M-#" . flyspell-auto-correct-region)))(add-hook 'shell-script-mode-hook 'hs-minor-mode)
(add-hook 'prog-mode-hook 'hs-minor-mode)(add-hook 'dired-mode-hook 'hl-line-mode)
(add-hook 'org-mode-hook 'hl-line-mode)
(add-hook 'prog-mode-hook 'hl-line-mode)
(add-hook 'shell-script-mode-hook 'hl-line-mode)
(add-hook 'text-mode-hook 'hl-line-mode)(defun ts-hippie-expand-completions (&optional hippie-expand-function)
"Return the full list of completions generated by HIPPIE-EXPAND-FUNCTION.
The optional argument can be generated with `make-hippie-expand-function'."
(let ((this-command 'ts-hippie-expand-completions)
(last-command last-command)
(buffer-modified (buffer-modified-p))
(hippie-expand-function (or hippie-expand-function 'hippie-expand)))
(cl-flet ((ding)) ; avoid the (ding) when hippie-expand exhausts its options.
(while (progn
(funcall hippie-expand-function nil)
(setq last-command 'ts-hippie-expand-completions)
(not (equal he-num -1)))))
;; Evaluating the completions modifies the buffer, however we will finish
;; up in the same state that we began.
(set-buffer-modified-p buffer-modified)
;; Provide the options in the order in which they are normally generated.
(delete he-search-string (reverse he-tried-table))))
(defun ts-hippie-complete-with (hippie-expand-function)
"Offer `completing-read' using the specified HIPPIE-EXPAND-FUNCTION."
(let* ((options (ts-hippie-expand-completions hippie-expand-function))
(selection (and options (completing-read "Completions: " options))))
(if selection
(he-substitute-string selection t)
(message "No expansion found"))))
(defun ts-hippie-expand-completing-read ()
"Offer `completing-read' for the word at point."
(interactive)
(ts-hippie-complete-with 'hippie-expand))
(keymap-global-set "C-M-/" 'hippie-expand)
(keymap-global-set "M-/" 'ts-hippie-expand-completing-read)(use-package icomplete
:custom
(fido-vertical-mode t)
(icomplete-compute-delay 0)
:config
(defun ts-icomplete-styles ()
(setq-local completion-styles '(initials flex)))
:hook
(icomplete-minibuffer-setup . ts-icomplete-styles)
:bind (:map icomplete-fido-mode-map
("<tab>" . icomplete-forward-completions)
("<backtab>" . icomplete-backward-completions)
("C-<tab>" . icomplete-force-complete-and-exit)
("M-j" . exit-minibuffer)))(use-package imenu
:config
(setq imenu-auto-rescan t)
(setq imenu-auto-rescan-maxout 600000)
(setq imenu-eager-completion-buffer t)
(setq imenu-level-separator "/")
(setq imenu-max-item-length 100)
(setq imenu-space-replacement " ")
(setq imenu-use-markers t)
(setq imenu-use-popup-menu nil)
:bind
("C-c i" . imenu))(use-package display-line-numbers
:config
(setq display-line-numbers 'relative)
:hook
(prog-mode . display-line-numbers-mode)
(sh-script-mode . display-line-numbers-mode))(add-hook 'occur-mode-hook 'hl-line-mode)
(keymap-set occur-mode-map "t" 'toggle-truncate-lines)(use-package org
:custom
(org-latex-listings 'minted)
(org-latex-pdf-process
'("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
(org-startup-folded t) ; start in overview mode
(org-directory "~")
(org-agenda-files (file-expand-wildcards "~/**/*.org"))
(org-default-notes-file "~/notes.org")
(org-image-actual-width nil) ; try to get width from #+ATTR.* keyword
(setf org-blank-before-new-entry '((heading . nil) (plain-list-item . nil)))
(org-emphasis-regexp-components '(" \t('\"{" "- \t.,:!?;'\")}\\" " \t\r\n,\"'" "." 300))
(org-confirm-babel-evaluate 'nil)
(org-export-with-toc t)
(org-indent-indentation-per-level 1)
(org-list-allow-alphabetical t)
(org-list-indent-offset 1)
(org-return-follows-link t)
(org-startup-indented t)
(org-html-validation-link nil) ; don't add "validate" postamble
(org-use-fast-todo-selection t)
(org-goto-interface 'outline-path-completionp)
(org-outline-path-complete-in-steps nil)
(org-refile-use-outline-path 'file)
(org-refile-allow-creating-parent-nodes 'confirm)
(org-refile-targets '((nil :maxlevel . 9)))
(org-special-ctrl-a/e 'reversed)
(org-special-ctrl-k t)
(org-special-ctrl-o t)
(org-use-speed-commands t)
(org-speed-commands-user '(("N" . org-down-element) ("P" . org-up-element)))
(org-src-fontify-natively t)
(org-src-tab-acts-natively t)
(org-src-window-setup 'current-window)
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((awk . t)
(C . t)
(css . t)
(emacs-lisp . t)
(lisp . t)
(makefile . t)
(perl . t)
(python . t)
(ruby . t)
(sed . t)
(shell . t)
(sql . t)
(sqlite . t)))
(add-to-list 'org-latex-packages-alist '("" "minted"))
(add-to-list 'org-modules 'org-tempo t)
(setq org-structure-template-alist
(append org-structure-template-alist
'(("cl" . "src common-lisp")
("el" . "src emacs-lisp")
("go" . "src go")
("ja" . "src java")
("js" . "src javascript")
("kr" . "src c")
("py" . "src python")
("sh" . "src shell")
("sq" . "src sql")
("tx" . "src text"))))
(defun ts-compile-and-load ()
(interactive)
(when (string-match "emacs" (buffer-file-name (current-buffer)))
(byte-compile-file (buffer-file-name (current-buffer)))
(load (buffer-file-name (current-buffer)))))
:bind (:map org-mode-map ("C-c i" . org-goto))
:hook (org-babel-post-tangle . ts-compile-and-load))(add-hook 'after-init-hook 'pending-delete-mode 1) ;; remove selected region if typing(use-package prettify-symbols
:custom (prettify-symbols-unprettify-at-point 'right-edge)
:hook (after-init . global-prettify-symbols-mode))(use-package project
:custom
(project-switch-commands
'((?b "Buffer" project-switch-to-buffer)
(?c "Compile" project-compile)
(?d "Dired" project-dired)
(?e "Eshell" project-eshell)
(?f "File" project-find-file)
(?g "Grep" project-find-regexp)
(?q "Query replace" project-query-replace-regexp)
(?r "Run command" project-async-shell-command)
(?s "Search" project-search)
(?v "VC dir" project-vc-dir)))
:config
(setq ts-project-roots '("~/src" "~/oe-developers"))
(defun ts-project--git-repo-p (directory)
"Return non-nil if there is a git repository in DIRECTORY."
(and
(file-directory-p (concat directory "/.git"))
(file-directory-p (concat directory "/.git/info"))
(file-directory-p (concat directory "/.git/objects"))
(file-directory-p (concat directory "/.git/refs"))
(file-regular-p (concat directory "/.git/HEAD"))))
(defun ts-project--git-repos-recursive (directory maxdepth)
"List git repos in under DIRECTORY recursively to MAXDEPTH."
(let* ((git-repos '())
(current-directory-list
(directory-files directory t directory-files-no-dot-files-regexp)))
;; while we are in the current directory
(if (ts-project--git-repo-p directory)
(setq git-repos (cons (file-truename (expand-file-name directory)) git-repos)))
(while current-directory-list
(let ((f (car current-directory-list)))
(cond ((and (file-directory-p f)
(file-readable-p f)
(> maxdepth 0)
(not (ts-project--git-repo-p f)))
(setq git-repos
(append git-repos
(ts-project--git-repos-recursive f (- maxdepth 1)))))
((ts-project--git-repo-p f)
(setq git-repos (cons
(file-truename (expand-file-name f)) git-repos))))
(setq current-directory-list (cdr current-directory-list))))
(delete-dups git-repos)))
(defun ts-project--list-projects ()
"Produce list of projects in `ts-project-roots'."
(let ((cands (delete-dups (mapcan (lambda (directory)
(if (file-directory-p directory)
(ts-project--git-repos-recursive
(expand-file-name directory)
10)))
ts-project-roots))))
;; needs to be a list of lists
(mapcar (lambda (d)
(list (abbreviate-file-name d)))
cands)))
(defun ts-project-update-projects ()
"Overwrite `project--list' using `ts-project--list-projects'.
WARNING: This will destroy & replace the contents of `project-list-file'."
(interactive)
(autoload 'project--ensure-read-project-list "project" nil t)
(project--ensure-read-project-list)
(setq project--list (ts-project--list-projects))
(project--write-project-list)
(message "Updated project list in %s" project-list-file))
:bind
("C-x pu" . ts-project-update-projects))(use-package python :custom (python-fill-docstring-style 'django))(use-package recentf
:custom
(recentf-exclude '(".gz"
".xz"
".zip"
"/elpa/"
"/ssh:"
"/sudo:"
"^/var/folders\\.*"
"COMMIT_EDITMSG\\'"
".*-autoloads\\.el\\'"
"[/\\]\\.elpa/"))
(recentf-max-menu-items 128)
(recentf-max-saved-items 256)
:config
(defun ts--recentf-get-paths ()
"Return de-duplicated and abbreviated `recentf-list'."
(delete-dups (mapcar 'abbreviate-file-name recentf-list)))
(defun ts-recentf-find-file ()
"`find-file' using `recentf-list'."
(interactive)
(find-file (completing-read "Find file: " (ts--recentf-get-paths))))
(defun ts-recentf-find-file-other-window ()
"`find-file' using `recentf-list'."
(interactive)
(find-file-other-window
(completing-read "Find file in other window: " (ts--recentf-get-paths))))
(defun ts-recentf-find-file-other-frame ()
"`find-file' using `recentf-list'."
(interactive)
(find-file-other-frame
(completing-read "Find file in other frame: " (ts--recentf-get-paths))))
:bind
("C-c r" . ts-recentf-find-file)
("C-c 4 r" . ts-recentf-find-file-other-window)
("C-c 5 r" . ts-recentf-find-file-other-frame)
("C-c C-r" . recentf-open-files)
:hook
(after-init . recentf-mode))(use-package savehist
:config
(setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring))
(setq savehist-save-minibuffer-history 1)
:hook (after-init . savehist-mode))(use-package save-place
:custom (save-place-file (concat user-emacs-directory "saveplace.el"))
:hook (after-init . save-place-mode));; (add-hook 'prog-mode-hook 'semantic-mode)
;; https://github.com/abo-abo/lispy/issues/473
(advice-add 'semantic-idle-scheduler-function :around #'ignore)(use-package sh-script
:mode
("\\.sh\\'" . shell-script-mode)
("\\.bash.*\\'" . shell-script-mode)
("\\.zsh.*\\'" . shell-script-mode)
("\\.aliases\\'" . shell-script-mode)
("\\.functions\\'" . shell-script-mode)
("\\bashrc\\'" . shell-script-mode)
("\\kshrc\\'" . shell-script-mode)
("\\profile\\'" . shell-script-mode)
("\\zshenv\\'" . shell-script-mode)
("\\zprompt\\'" . shell-script-mode)
("\\zshrc\\'" . shell-script-mode)
("\\prompt_.*_setup\\'" . shell-script-mode)
:interpreter
("bash" . shell-script-mode)
("ksh" . shell-script-mode)
("sh" . shell-script-mode)
("zsh" . shell-script-mode)
:hook
(after-save . executable-make-buffer-file-executable-if-script-p))(use-package paren
:custom
(show-paren-when-point-in-periphery t)
(show-paren-when-point-inside-paren t)
:hook (after-init . show-paren-mode))(add-hook 'after-init-hook 'global-subword-mode) ;; move by camel case, etc(use-package term
:config
(defadvice term-handle-exit (after term-kill-buffer-on-exit activate)
"Kill term when shell exits."
(kill-buffer))
(setq term-buffer-maximum-size 200000)
:bind ("C-c t" . ansi-term))(with-eval-after-load 'tramp
(setq tramp-backup-directory-alist backup-directory-alist)
(setq tramp-default-method "ssh")
(setf tramp-persistency-file-name (concat temporary-file-directory "tramp-" (user-login-name)))
(message "Lazy loaded tramp :-)"))https://www.masteringemacs.org/article/how-to-get-started-tree-sitter
(setq major-mode-remap-alist
'((yaml-mode . yaml-ts-mode)
(bash-mode . bash-ts-mode)
(js2-mode . js-ts-mode)
(go-mode . go-ts-mode)
(typescript-mode . typescript-ts-mode)
(json-mode . json-ts-mode)
(css-mode . css-ts-mode)
(python-mode . python-ts-mode)))
(setq treesit-language-source-alist
'((bash "https://github.com/tree-sitter/tree-sitter-bash")
(cmake "https://github.com/uyha/tree-sitter-cmake")
(css "https://github.com/tree-sitter/tree-sitter-css")
(elisp "https://github.com/Wilfred/tree-sitter-elisp")
(go "https://github.com/tree-sitter/tree-sitter-go")
(html "https://github.com/tree-sitter/tree-sitter-html")
(javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
(json "https://github.com/tree-sitter/tree-sitter-json")
(make "https://github.com/alemuller/tree-sitter-make")
(markdown "https://github.com/ikatyang/tree-sitter-markdown")
(python "https://github.com/tree-sitter/tree-sitter-python")
(toml "https://github.com/tree-sitter/tree-sitter-toml")
(tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")
(typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")
(yaml "https://github.com/ikatyang/tree-sitter-yaml")))Bulk install all the grammars as a one of task, so don’t tangle!
(mapc #'treesit-install-language-grammar
(mapcar #'car treesit-language-source-alist))Protesilaos Stavrou’s VC reference
(use-package vc
:custom
(vc-follow-symlinks t)
(vc-make-backup-files t)
(version-control t)
:bind ("C-x v d" . vc-dir-root))(use-package whitespace
:custom
(whitespace-line-column 120)
(whitespace-style '(face
tabs
spaces
trailing
lines
space-before-tab::space
newline
indentation::space
empty
space-after-tab::space
space-mark
tab-mark
newline-mark)
whitespace-face 'whitespace-trailing)
:bind ("C-c M-w" . whitespace-mode)
:hook (before-save . whitespace-cleanup))(use-package windmove
:custom (windmove-wrap-around t)
:bind
("C-c w b" . windmove-left)
("C-c w f" . windmove-right)
("C-c w p" . windmove-up)
("C-c w n" . windmove-down)
("C-c w C-b" . windmove-swap-states-left)
("C-c w C-f" . windmove-swap-states-right)
("C-c w C-p" . windmove-swap-states-up)
("C-c w C-n" . windmove-swap-states-down))(setq window-divider-default-right-width 1)
(setq window-divider-default-bottom-width 1)
(setq window-divider-default-places 'right-only)
(add-hook 'window-setup-hook 'window-divider-mode)(add-hook 'window-setup-hook 'winner-mode)
(keymap-global-set "C-c w u" 'winner-undo)
(keymap-global-set "C-c w r" 'winner-redo)I like to split up my “vanilla” Emacs configuration and custom functions from the customisations provided by third party libraries.
If you want to go for a more vanilla setup, just prefix the COMMENT keyword
to the tile above (or press C-c ; whilst under this heading).
Then, re-tangle and re-load the file, by simply saving it.
This way it makes it very easy to run a semi-stock Emacs without package.el
or any third party libraries.
Yet still have some saner defaults and some extra functionality.
;; Allow loading from the package cache.
(setq package-quickstart t)
;; Don't write (package-initialize) to my init file!
(setq package--init-file-ensured t)
;; Turn on ahead-of-time native compilation when installing a package.
(setq package-native-compile t)
;; Setup up archives
(setq package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")))(use-package ace-window :ensure
:bind*
("M-o" . ace-window)
:config
(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)))(use-package async :ensure t)
(use-package dired-async :after (dired async)
:hook (dired-mode . dired-async-mode))(use-package blamer :ensure :defer 20
:custom
(blamer-idle-time 0.5)
(blamer-min-offset 20)
(blamer-max-commit-message-length 50)
:config (global-blamer-mode 1))(use-package copilot :ensure)
(use-package copilot-chat :ensure)(use-package corfu :ensure
:custom
(corfu-cycle t)
(corfu-auto t)
:hook
(prog-mode . corfu-mode)
(shell-mode . corfu-mode)
(eshell-mode . corfu-mode))Increase or decrease font size everywhere with C-M-= and C-M--
https://github.com/purcell/default-text-scale
(use-package default-text-scale :ensure :defer 7 :config (default-text-scale-mode))(use-package dockerfile-mode :ensure)Don’t tangle this block if system-type is windows-nt.
(use-package exec-path-from-shell :ensure
:unless (eq system-type 'windows-nt)
:commands exec-path-from-shell-initialize
:init
(setq exec-path-from-shell-check-startup-files 'nil)
:config
(exec-path-from-shell-initialize)
(exec-path-from-shell-copy-env "DEVPATH")
(exec-path-from-shell-copy-env "GOPATH")
(exec-path-from-shell-copy-env "PYTHONPATH")
:hook
(prog-mode . exec-path-from-shell-initialize))(use-package flycheck :ensure
:unless (eq system-type 'windows-nt)
:diminish flycheck-mode
:config
(flycheck-add-mode 'javascript-eslint 'web-mode)
:hook
(prog-mode . flycheck-mode)
(shell-script-mode . flycheck-mode))(use-package git-timemachine :ensure)(use-package magit :ensure
:bind*
("C-x g" . magit-status)
:config
(when (eq system-type 'windows-nt)
(if (file-readable-p "C:/Program Files/Git/bin/git.exe")
(setq magit-git-executable "C:/Program Files/Git/bin/git.exe"))
(when (file-directory-p "C:/Program Files/Git/bin")
(setq exec-path (add-to-list 'exec-path "C:/Program Files/Git/bin"))
(setenv "PATH" (concat "C:\\Program Files\\Git\\bin;" (getenv "PATH")))))
(setq magit-clone-set-remote.pushDefault t)
(setq magit-completing-read-function 'magit-builtin-completing-read))(use-package magit-repos
:bind* ("C-x C-g" . magit-list-repositories)
:config
(setq magit-repository-directories `(("~/" . 0)
("~/src" . 10)
("~/oe-developers" . 10)))
(setq magit-repolist-columns
'(("Flag" 5 magit-repolist-column-flags ((:right-align t) nil))
("Name" 20 magit-repolist-column-ident nil)
("Branch" 10 magit-repolist-column-branch nil)
;; ("Version" 25 magit-repolist-column-version nil)
("Pull" 5 magit-repolist-column-unpulled-from-upstream ((:right-align t) nil))
("Push" 5 magit-repolist-column-unpushed-to-upstream ((:right-align t) nil))
;; ("Pull" 5 magit-repolist-column-unpulled-from-pushremote ((:right-align t) nil))
;; ("Push" 5 magit-repolist-column-unpushed-to-pushremote ((:right-align t) nil))
("Path" 99 magit-repolist-column-path nil)))
(setq magit-repolist-sort-key '("Flag" . t)))go install \
github.com/rogpeppe/godef@latest \
github.com/tslight/lazygit.go/cmd/github@latest \
golang.org/x/tools/cmd/godoc@latest \
golang.org/x/tools/cmd/goimports@latest \
golang.org/x/tools/gopls@latest \
&& echo "Finished installing Go packages :-)"(use-package go-mode :ensure
:init
(setenv "GOPATH" (concat (getenv "HOME") "/go"))
(add-to-list 'exec-path (concat (getenv "GOPATH") "/bin"))
:config
;; Use goimports instead of go-fmt
(setq gofmt-command "goimports")
;; Customize compile command to run go build
;; (if (not (string-match "go" compile-command))
;; (set (make-local-variable 'compile-command)
;; "go build -v && go test -v && go vet"))
(defun ts-go-indent ()
(setq indent-tabs-mode 1)
(setq tab-width 2))
:hook
(go-mode . ts-go-indent)
(before-save . gofmt-before-save))(use-package gptel :ensure
:config
(gptel-make-gh-copilot "copilot")
(setq gptel-backend (gptel-get-backend "copilot")))(use-package hungry-delete :ensure :defer 6 :config (global-hungry-delete-mode))(use-package json-mode :ensure
:config
(defun ts-json-mode-setup ()
(json-mode)
(json-pretty-print (point-min) (point-max))
(goto-char (point-min))
(set-buffer-modified-p nil))
(add-to-list 'auto-mode-alist
'("\\.json\\'" . 'ts-json-mode-setup)))(use-package kdl-mode :ensure t)(use-package markdown-mode :ensure
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . gfm-mode)
("\\.markdown\\'" . gfm-mode))
:init (setq markdown-command "multimarkdown"))Needs rnix-lsp or nixd for eglot
(use-package nix-mode :ensure t)(use-package htmlize :ensure)(use-package restclient :ensure)(use-package terraform-mode :ensure)Like undo-tree but doesn’t hijack, modify or potentially corrupt the default,
idiosyncratic, but very powerful built-in undo logic.
However, sometimes it’s easy to get lost all the undo/redo forks Emacs makes available, so a visual indication is fantastic.
(use-package vundo :ensure :bind ("C-c u" . vundo))(use-package web-mode :ensure
:mode
"\\.phtml\\'"
"\\.tpl\\.php\\'"
"\\.[agj]sp\\'"
"\\.as[cp]x\\'"
"\\.erb\\'"
"\\.mustache\\'"
"\\.djhtml\\'"
"\\.html\\.twig\\'"
"\\.html?\\'"
"\\.php?\\'"
"\\.css?\\'"
:hook (web-mode . js2-minor-mode)
:custom
(web-mode-code-indent-offset 2)
(web-mode-markup-indent-offset 2)
(web-mode-attr-indent-offset 2)
(web-mode-css-indent-offset 2)
(web-mode-code-indent-offset 2)
(web-mode-enable-auto-pairing t))(use-package which-key :ensure :defer 5 :config (which-key-mode))(use-package highlight-indentation :ensure)
(use-package yaml-mode :ensure
:hook
(yaml-mode . highlight-indentation-mode)
(yaml-mode . hs-minor-mode)
(yaml-mode . display-line-numbers-mode))(use-package yasnippet :ensure :hook (prog-mode . yas-minor-mode))
(use-package yasnippet-snippets :ensure)