About This web page is a tangled version of my literate elisp config . Throughout this document, you may find helpful notes, tricks, and comments. I have been tinkering with emacs in some way since 2013. I made this repeatable and git-controlled in 2019, and in 2023 I began to publish it on my web site.
Notes on code blocks If a code block is active, then it will appear with emacs-lisp
syntax highlighting. If it’s not being used, then it will show up with plaintext
highlighting. For example:
(print "This code will not be run!")
( print "This code is run in my config!" )
Whether a code block is run at load time is controlled by the :load yes
block argument of literate-elisp
.
Package Management I love and rely heavily on straight.el
.
( defvar bootstrap-version )
( let (( bootstrap-file
( expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory ))
( bootstrap-version 6 ))
( unless ( file-exists-p bootstrap-file )
( with-current-buffer
( url-retrieve-synchronously
"<https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el>"
'silent 'inhibit-cookies )
( goto-char ( point-max ))
( eval-print-last-sexp )))
( load bootstrap-file nil 'nomessage ))
( setq straight-use-package-by-default t )
( straight-use-package 'use-package )
( require 'use-package )
( setq use-package-compute-statistics t )
( use-package general )
( use-package org )
( use-package
literate-elisp
:demand t
:config
;; ;; To make \`elisp-refs' work with \`literate-elisp', we need to add an advice to \`elisp-refs–read-all-buffer-forms'.
( eval-after-load "elisp-refs"
' ( advice-add
'elisp-refs– ;read-all-buffer-forms
:around #' literate-elisp-refs– ;read-all-buffer-forms))
;; To make \`elisp-refs' work with \`literate-elisp', we need to add an advice to \`elisp-refs–loaded-paths'.
( eval-after-load "elisp-refs"
' ( advice-add
'elisp-refs– ;loaded-paths
:filter-return #' literate-elisp-refs– ;loaded-paths))
;; To make \`helpful' work with \`literate-elisp', we need to add an advice to \`helpful–find-by-macroexpanding'.
( eval-after-load 'helpful
' ( advice-add
'helpful– ;find-by-macroexpanding
:around #' literate-elisp-helpful– ;find-by-macroexpanding)))
( require 'org-element ) ; TODO: until org-element–cache-active-p autoload fixed in literate-elisp upstream
( provide 'packages-settings )
MacOS specific settings ( when ( eq system-type 'darwin )
( setq mac-command-modifier 'control )
( setq mac-right-command-modifier 'meta )
( add-to-list 'default-frame-alist ' ( ns-transparent-titlebar . t ))
( add-to-list
'default-frame-alist
' ( ns-appearance . light )) ;; or dark - depending on your theme
( use-package osx-plist :straight ' ( osx-plist :type git :host github :repo "gonewest818/osx-plist" )))
Path ( setq default-directory "~/" )
( use-package package )
( use-package
exec-path-from-shell
:demand t
:init
( setq exec-path-from-shell-variables
' ( "PATH" "MANPATH" "OPENAI_API_KEY" ))
:config
( when ( memq window-system ' ( mac ns x ))
( exec-path-from-shell-initialize )))
Window management Zoom I think this is a little too aggressive right now, but it’s a cool idea.
(use-package
zoom
:init (setq zoom-size '(0.618 . 0.618))
:config (zoom-mode))
Visual Fill Column (use-package
visual-fill-column
:init (setq visual-fill-column-center-text t)
:config (visual-fill-column-mode 1))
Centered window ( use-package
centered-window
:init ( setq cwm-centered-window-width 180 )
:ensure t
:config ( centered-window-mode t )
; reload the fringe color after loading the theme
( cwm-update-fringe-background ))
Miscellaneous ( setq require-final-newline t )
( setq show-trailing-whitespace t )
( setq native-comp-async-report-warnings-errors nil )
;; Show the line number of the cursor in the mode bar at the bottom of each buffer
( setq line-number-mode t )
;; Disable the loud bell
( setq ring-bell-function
( lambda ()
( let (( orig-fg ( face-foreground 'mode-line )))
( set-face-foreground 'mode-line "#F2804F" )
( run-with-idle-timer 0.1 nil
( lambda ( fg )
( set-face-foreground 'mode-line fg ))
orig-fg ))))
;; Make sure all backup files only live in one place
( setq backup-directory-alist ` (( ".*" . , temporary-file-directory )))
( setq auto-save-file-name-transforms
` (( ".*" , temporary-file-directory t )))
;; Don't truncate lines
( setq truncate-lines t )
( setq-default indent-tabs-mode nil )
;; Don't show the scroll bar on the side of buffers
( scroll-bar-mode -1 )
;; Don't show the toolbar, it just takes up space
( tool-bar-mode -1 )
;; Show column number in the modeline
( setq column-number-mode t )
( setq blink-paren-function nil )
( setq inhibit-startup-screen t )
( use-package
ctrlf
:config
( add-to-list
'ctrlf-minibuffer-bindings ' ( "C-r" . ctrlf-backward-default ))
( setq ctrlf-default-search-style 'fuzzy-regexp )
( setq ctrlf-default-search-style 'literal )
( ctrlf-mode t ))
( use-package
whole-line-or-region
:config ( whole-line-or-region-global-mode t ))
( use-package
popper
:bind
(( "C-`" . popper-toggle-latest )
( "M-`" . popper-cycle )
( "C-M-`" . popper-toggle-type ))
:init
( setq popper-reference-buffers
' ( "\\*Messages\\*"
"Output\\*$"
"\\*Async Shell Command\\*"
help-mode
compilation-mode ))
( popper-mode +1 ) ( popper-echo-mode +1 ))
( use-package page-break-lines :config ( global-page-break-lines-mode ))
( use-package eldoc :hook ( prog-mode . eldoc-mode ))
( use-package
expand-region
:config ( global-set-key ( kbd "M-J" ) 'er/expand-region ))
( use-package which-key :config ( which-key-mode 1 ))
( use-package
ibuffer
:config
( global-set-key ( kbd "C-x C-b" ) 'ibuffer )
( define-key ibuffer-mode-map ( kbd "M-o" ) nil ))
Direnv ( use-package
direnv
:config ( direnv-mode 't )
)
Window movement keybindings ( define-key term-raw-map ( kbd "M-o" ) 'next-multiframe-window )
( define-key term-raw-map ( kbd "M-i" ) 'previous-multiframe-window )
( define-key global-map ( kbd "M-o" ) 'next-multiframe-window )
( define-key global-map ( kbd "M-i" ) 'previous-multiframe-window )
( setq aw-keys ' ( ?a ?s ?d ?f ?g ?h ?j ?k ?l ))
Sqlite So far, I am unable to find a way to compile sqlite3 on my own, but I would love to be able to do this with straight package management.
;; Override the 'yes-or-no-p' temporarily
( let (( original-yes-or-no-p ( symbol-function 'yes-or-no-p )))
( fset 'yes-or-no-p ( lambda ( &rest args ) t ))
;; Load the sqlite3 package
( use-package sqlite3
:straight ( sqlite3
:type git
:host github
:repo "pekingduck/emacs-sqlite3-api"
:files ( "*.c" "*.h" "*.el" "Makefile" )))
;; Restore the original function
( fset 'yes-or-no-p original-yes-or-no-p ))
Anzu ( use-package
anzu
:bind
(( [remap query-replace] . #' anzu-query-replace )
( [remap query-replace-regexp] . #' anzu-query-replace-regexp ))
:config ( global-anzu-mode +1 ))
Line Highlighting ( use-package lin :init ( lin-global-mode t ))
( use-package
hl-line
:config
( add-hook
'eshell-mode-hook ( lambda () ( setq-local global-hl-line-mode nil )))
( add-hook
'term-mode-hook ( lambda () ( setq-local global-hl-line-mode nil )))
( add-hook
'vterm-mode-hook ( lambda () ( setq-local global-hl-line-mode nil )))
( global-hl-line-mode t ))
( literate-elisp-load "term-settings.org" )
( use-package dash )
( use-package ht )
;; Replace the text of selections
( pending-delete-mode t )
Undo Tree I haven’t found a great way to use undo-tree, but everyone seems to love it.
(use-package undo-tree :init (global-undo-tree-mode))
So long mode I find this breaks browsing of long json files, more than it helps me out.
(global-so-long-mode t)
Dashboard ( use-package
dashboard
:straight
' ( emacs-dashboard
:type git
:host github
:repo "emacs-dashboard/emacs-dashboard"
:files ( "banners" :defaults ))
:config
;; Set the title
( setq dashboard-banner-logo-title "Welcome to Emacs!" )
;; Set the banner
( setq dashboard-startup-banner 'official )
( setq dashboard-items
' (( projects . 5 )
( recents . 5 ) ( bookmarks . 5 )
;; (agenda . 5)
( registers . 5 )))
;; ;; Value can be
;; ;; 'official which displays the official emacs logo
;; ;; 'logo which displays an alternative emacs logo
;; ;; 1, 2 or 3 which displays one of the text banners
;; ;; "path/to/your/image.png" which displays whatever image you would prefer
;; ;; Content is not centered by default. To center, set
( setq dashboard-center-content t )
( setq initial-buffer-choice ( lambda () ( get-buffer "*dashboard*" )))
;; ;; To disable shortcut "jump" indicators for each section, set
;; (setq dashboard-show-shortcuts nil)
;; Override this function so that we can filter remote projects
( defun dashboard-projects-backend-load-projects ()
"Depending on `dashboard-projects-backend' load corresponding backend.
Return function that returns a list of projects."
( cl-remove-if
( lambda ( x ) ( string-search "/ssh" x ))
( cl-case
dashboard-projects-backend
( ` projectile
( require 'projectile )
( dashboard-mute-apply ( projectile-cleanup-known-projects ))
( projectile-load-known-projects ))
( ` project-el
( require 'project )
( dashboard-mute-apply
( dashboard-funcall-fboundp #' project-forget-zombie-projects ))
( project-known-project-roots ))
( t
( display-warning
' ( dashboard ) "Invalid value for `dashboard-projects-backend'"
:error )))))
( dashboard-setup-startup-hook ))
Icons ( use-package all-the-icons )
( use-package
all-the-icons-ibuffer
:hook ( ibuffer-mode . all-the-icons-ibuffer-mode ))
;; I don't think I like buffer expose after all
( use-package
all-the-icons-completion
:config ( all-the-icons-completion-mode )
:hook ( marginalia-mode . all-the-icons-completion-marginalia-setup ))
( literate-elisp-load "projectile-settings.org" )
; Re-enable with SVG support
( use-package
svg-lib
:straight ' ( svg-lib :host github :repo "emacs-straight/svg-lib" ))
( use-package
kind-icon
:straight ' ( kind-icon :host github :repo "jdtsmith/kind-icon" )
:ensure t
:after corfu
:config
; On my linux machine, I need to use smaller icons like this due to the 4k display
( when ( eq system-type 'gnu/linux )
( setq kind-icon-default-style
' ( :padding
-1
:stroke 0
:margin 0
:radius 0
:height 0.5
:scale 1.0 )))
:custom
( kind-icon-default-face 'corfu-default ) ; to compute blended backgrounds correctly
:config ( add-to-list 'corfu-margin-formatters #' kind-icon-margin-formatter ))
Fonts ;; Font settings
( if ( eq system-type 'darwin )
( if ( and ( display-graphic-p ) ( > ( x-display-pixel-width ) 1440 ))
;; Set default font larger if on a big screen
( set-face-font 'default "roboto mono-15" )
;; (set-face-font 'default "arial-15")
;; else
( set-face-font 'default "roboto mono-14" )
;; (set-fontset-font "fontset-default" "Menlo 12")
)
;; else
( if ( not ( eq window-system nil ))
( if ( and ( display-graphic-p ) ( > ( x-display-pixel-width ) 1440 ))
;; Set default font larger if on a big screen
( set-face-font 'default "roboto mono-12" )
;; else
( set-face-font 'default "roboto mono-12" )
;; (set-fontset-font "fontset-default" "Menlo 12")
)
;; else
))
;; Use ace-popup-menu for completions
( use-package
ace-popup-menu
:config
( ace-popup-menu-mode 1 )
( setq ace-popup-menu-show-pane-header t ))
Emacs startup profiler ( use-package esup )
Scratch ( use-package
scratch
:defer t
:straight
' ( scratch
:host nil
:type git
:repo "https://codeberg.org/emacs-weirdware/scratch.git" )
:config ( scratch--create 'emacs-lisp-mode "*scratch*" ))
( use-package fuzzy )
( use-package fuzzy-match )
( use-package free-keys )
( use-package restart-emacs )
; ---- Auto Revert Modes ----- ;
( autoload 'eimp-mode "eimp" "Emacs Image Manipulation Package." t )
( add-hook 'image-mode-hook 'auto-revert-mode )
; --- CSV --- ;
( use-package
csv-mode
:straight
' ( csv-mode :type git :host github :repo "emacsmirror/csv-mode" ))
( use-package
explain-pause-mode
:straight
' ( explain-pause-mode
:type git
:host github
:repo "lastquestion/explain-pause-mode" ))
;; use helpful instead of the normal help buffers
;; Note that the built-in `describe-function' includes both functions
;; and macros. `helpful-function' is functions only, so we provide
;; `helpful-callable' as a drop-in replacement.
( use-package
helpful
:defer t
;; TODO: Add these back in when helpful plays nicely with literate-elisp
;; :bind
;; ("C-h f" . helpful-callable)
;; ("C-h v" . helpful-variable)
;; ("C-h k" . helpful-key)
)
( use-package
dimmer
:config
( dimmer-configure-which-key )
( dimmer-configure-org )
( dimmer-configure-posframe )
( dimmer-configure-magit )
( dimmer-configure-hydra )
( setq dimmer-fraction 0.15 )
( dimmer-mode t ))
( use-package
volatile-highlights
:config ( volatile-highlights-mode t ))
( use-package hl-todo :init ( global-hl-todo-mode ))
Indentation ( electric-indent-mode 0 )
;; (use-package
;; aggressive-indent
;; :config (aggressive-indent-global-mode nil))
( use-package
apheleia
:config
( setf ( alist-get 'isort apheleia-formatters )
' ( "isort" "--stdout" "-" ))
( setf ( alist-get 'python-ts-mode apheleia-mode-alist ) ' ( isort black ))
( add-to-list
'apheleia-formatters
' ( prettier-toml
npx "prettier" "--stdin-filepath" filepath "--parser=toml" ))
( add-to-list 'apheleia-mode-alist ' ( conf-toml-mode . prettier-toml ))
( defun apheleia-indent-region+ ( orig scratch callback )
( with-current-buffer scratch
( setq-local indent-line-function
( buffer-local-value 'indent-line-function orig ))
( indent-region ( point-min ) ( point-max ))
( funcall callback scratch )))
( push ' ( jsonian-mode . prettier-json ) apheleia-mode-alist )
( setq apheleia-mode-alist
( assq-delete-all 'emacs-lisp-mode apheleia-mode-alist ))
( apheleia-global-mode t ))
( literate-elisp-load "elisp-settings.org" )
( use-package
elisp-autofmt
:commands ( elisp-autofmt-mode elisp-autofmt-buffer )
:hook ( emacs-lisp-mode . elisp-autofmt-mode )
:init ( setq elisp-autofmt-check-elisp-autofmt-exists 'always )
:straight
' ( elisp-autofmt
;; :files (:defaults "elisp-autofmt")
:host nil
:type git
:repo "https://codeberg.org/ideasman42/emacs-elisp-autofmt.git" )
:config ( setq elisp-autofmt-on-save-p nil ))
Whitespace butler ( use-package ws-butler
:hook ( prog-mode . ws-butler-mode )
:hook ( org-mode . ws-butler-mode ))
Global Keybindings ( global-set-key ( kbd "M-k" ) 'kill-this-buffer )
( global-set-key ( kbd "C-c C-b" ) 'compile )
( global-set-key ( kbd "M-0" ) 'delete-window )
( global-set-key ( kbd "M-1" ) 'delete-other-windows )
( global-set-key ( kbd "M-2" ) 'split-window-below )
( global-set-key ( kbd "M-3" ) 'split-window-right )
; Unbind reverse search because we'll use swiper
( global-unset-key ( kbd "C-r" ))
( global-set-key ( kbd "M-u" ) 'upcase-dwim )
( global-set-key ( kbd "M-l" ) 'downcase-dwim )
( global-set-key ( kbd "C-." ) 'xref-find-definitions-other-window )
( define-key global-map ( kbd "RET" ) 'newline-and-indent )
Copying syntax highlighting to the clipboard ( when ( eq system-type 'darwin )
( use-package
highlight2clipboard
:straight
' ( highlight2clipboard
:type git
:host github
:repo "Lindydancer/highlight2clipboard" )))
Breadcrumb mode Because I’m trying this out, I’m going to disable LSP’s breadcrumb mode, which I’ve been disappointed with.
(use-package
breadcrumb
:straight '(breadcrumb :type git :host github :repo "joaotavora/breadcrumb")
:config (breadcrumb-mode t))
Rsync-mode Loving use of my old colleague Ryan Pilgrim ’s package to sync accross our secure environments.
( use-package
rsync-mode
:straight ' ( rsync-mode :type git :host github :repo "jsigman/rsync-mode" ))
Shortcuts Jump to remote ( defun open-remote-dired ()
"Opens a Dired buffer at the path specified by REMOTE_HOST and REMOTE_PATH environment variables."
( interactive )
( condition-case nil
( let (( remote-host ( getenv "REMOTE_HOST" ))
( remote-path ( getenv "REMOTE_PATH" )))
( if ( and remote-host remote-path )
( progn
( message "Attempting to open remote directory..." )
( dired ( concat "/ssh:" remote-host ":" remote-path ))
( message "Remote directory opened." ))
( message
"Error: REMOTE_HOST or REMOTE_PATH environment variables not set." )))
( error
( message
"Error: Unable to open remote directory. Check your connection and environment variables." ))))
;; Bind the function to M-R globally
( global-set-key ( kbd "M-R" ) 'open-remote-dired )
Local Variables Settings This really improves use with local variables. You get a highly visible warning when a dir-local file is unreadable or misconfigured.
( defun my/dir-local-error-warning ( orig-fun &rest args )
"Advice to display a warning on directory local variable read errors."
( condition-case err
( apply orig-fun args )
( error
( display-warning
'dir-locals
( format "Error reading .dir-locals.el: %s"
( error-message-string err ))
:error ))))
( advice-add
'hack-dir-local-variables
:around #' my/dir-local-error-warning )
Config Modes Yaml ( use-package yaml-mode )
Parens ( setq show-paren-when-point-inside-paren 't )
( setq show-paren-style 'mixed )
( setq show-paren-context-when-offscreen 't )
( use-package
elec-pair
:config ;; Disable electric pair in minibuffer
( defun my/inhibit-electric-pair-mode ( char )
( or ( minibufferp ) ( electric-pair-conservative-inhibit char )))
( setq electric-pair-inhibit-predicate
#' my/inhibit-electric-pair-mode )
( electric-pair-mode t )
;; The ‘<’ and ‘>’ are not ‘parenthesis’, so give them no compleition.
( setq electric-pair-inhibit-predicate
( lambda ( c )
( or ( member c ' ( ?< ?> ?~ ))
( electric-pair-default-inhibit c )))))
( setq show-paren-context-when-offscreen t )
( setq show-paren-style 'mixed )
;; Treat ‘<’ and ‘>’ as if they were words, instead of ‘parenthesis’.
( modify-syntax-entry ?< "w<" )
( modify-syntax-entry ?> "w>" )
;; Show matching parens
( setq show-paren-delay 0 )
( show-paren-mode t )
Elisp ( use-package eros :config ( eros-mode t ))
( use-package
lisp-extra-font-lock
:config ( lisp-extra-font-lock-global-mode 1 ))
( use-package elisp-docstring-mode )
( use-package
highlight-function-calls
:hook ( emacs-lisp-mode . highlight-function-calls-mode ))
( use-package format-all :hook ( elisp-mode . format-all-mode ))
( use-package
inspector
:straight
' ( inspector :type git :host github :repo "mmontone/emacs-inspector" ))
( setq eval-expression-print-length nil )
( setq eval-expression-print-level nil )
( add-to-list
'auto-mode-alist
' ( "\\.dir-locals\\(?:-2\\)?\\.el\\'" . emacs-lisp-mode ))
Dired Mode ( setq
dired-omit-files
"^\\.?#\\|^\\.\\(DS_Store\\|localized\\|AppleDouble\\)$\\|^\\.\\.$" )
( setq dired-kill-when-opening-new-dired-buffer t )
( when ( eq system-type 'darwin ) ( setq
insert-directory-program "gls"
dired-use-ls-dired t ))
( setq dired-listing-switches "-al --group-directories-first" )
;; wdired settings
( use-package
wdired
:config
( setq wdired-allow-to-change-permissions t )
( define-key dired-mode-map ( kbd "e" ) 'wdired-change-to-wdired-mode )
( define-key dired-mode-map ( kbd "M-G" ) nil ))
Projectile ( use-package
projectile
:init ( setq projectile-git-submodule-command nil )
;; always ignore the home directory and root
( setq projectile-ignored-projects
` ( "/" "~/" , ( expand-file-name "~/" )))
( setq projectile-track-known-projects-automatically nil )
;; Use alien as the default, and project-wise add other files
( setq projectile-indexing-method 'native )
( setq projectile-enable-caching t )
( setq projectile-files-cache-expire 300 )
( setq projectile-file-exists-remote-cache-expire nil )
:config
( define-key projectile-mode-map ( kbd "s-p" ) 'projectile-command-map )
( define-key
projectile-mode-map ( kbd "C-c p" ) 'projectile-command-map )
( define-key projectile-mode-map ( kbd "M-K" ) 'projectile-kill-buffers )
( add-to-list 'projectile-globally-ignored-directories "/venv" )
( add-to-list 'projectile-globally-ignored-directories "/data" )
( add-to-list 'projectile-globally-ignored-directories "/typings" )
( add-to-list 'projectile-globally-ignored-directories "/node_modules" )
( add-to-list 'projectile-globally-ignored-directories "/.mypy_cache" )
( add-to-list
'projectile-globally-ignored-directories "/.pytest_cache" )
( add-to-list 'projectile-globally-ignored-directories "/.cache" )
( add-to-list 'projectile-globally-ignored-directories "/.dvc/cache" )
( add-to-list 'projectile-globally-ignored-directories "/.dvc/tmp" )
( add-to-list
'projectile-globally-ignored-directories "/.jekyll-cache" )
( projectile-mode +1 )
;; (add-hook 'magit-run-section-hook 'projectile-invalidate-cache)
( add-hook
'magit-section-post-command-hook 'projectile-invalidate-cache )
)
Corfu-Vertico-Orderless Corfu ( use-package
corfu
;; Optional customizations
:custom
( corfu-cycle t ) ;; Enable cycling for `corfu-next/previous'
( corfu-auto t ) ;; Enable auto completion
;; (corfu-commit-predicate nil) ;; Do not commit selected candidates on next input
( corfu-quit-at-boundary 'separator ) ;; Automatically quit at word boundary
( corfu-quit-no-match 'separator ) ;; Automatically quit if there is no match
( corfu-scroll-margin 5 ) ;; Use scroll margin
;; (corfu-preview-current nil) ;; Do not preview current candidate
( corfu-auto-delay 0.0 )
( corfu-auto-prefix 1 )
( corfu-on-exact-match 'quit )
;; (corfu-separator ?\s) ;; Orderless field separator
;; (corfu-preview-current nil) ;; Disable current candidate preview
;; (corfu-preselect-first nil) ;; Disable candidate preselection
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
;; (corfu-echo-documentation nil) ;; Disable documentation in the echo area
;; (corfu-scroll-margin 5) ;; Use scroll margin
;; You may want to enable Corfu only for certain modes.
;; :hook ((prog-mode . corfu-mode)
;; (shell-mode . corfu-mode)
;; (eshell-mode . corfu-mode))
;; Recommended: Enable Corfu globally.
;; This is recommended since dabbrev can be used globally (M-/).
:init ( global-corfu-mode )
;; :config
;; (define-key corfu-map (kbd "M-p") #'corfu-doc-scroll-down) ;; corfu-next
;; (define-key corfu-map (kbd "M-n") #'corfu-doc-scroll-up) ;; corfu-previous
;; Quit on save
:hook ( before-save-hook . corfu-quit )
:load-path "straight/build/corfu/extensions"
:config
( require 'corfu-history )
( corfu-history-mode 1 )
( savehist-mode 1 )
( add-to-list 'savehist-additional-variables 'corfu-history )
;; (corfu-mode-hook . corfu-doc-mode)
)
Cape ( defun add-cape-completions ()
( add-to-list 'completion-at-point-functions #' cape-file )
;; (add-to-list 'completion-at-point-functions
;; #'cape-keyword)
;; (add-to-list 'completion-at-point-functions
;; #'cape-symbol)
)
;; Add extensions
( use-package
cape
;; Bind dedicated completion commands
;; :bind (("C-c p p" . completion-at-point) ;; capf
;; ("C-c p t" . complete-tag) ;; etags
;; ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion
;; ("C-c p f" . cape-file)
;; ("C-c p k" . cape-keyword)
;; ("C-c p s" . cape-symbol)
;; ("C-c p a" . cape-abbrev)
;; ("C-c p i" . cape-ispell)
;; ("C-c p l" . cape-line)
;; ("C-c p w" . cape-dict)
;; ("C-c p \\" . cape-tex)
;; ("C-c p _" . cape-tex)
;; ("C-c p ^" . cape-tex)
;; ("C-c p &" . cape-sgml)
;; ("C-c p r" . cape-rfc1345))
:hook ( corfu-mode . add-cape-completions ))
;; A few more useful configurations...
( setq completion-cycle-threshold 3 )
Orderless ;; Optionally use the `orderless' completion style.
( use-package
orderless
:init
;; Tune the global completion style settings to your liking!
;; This affects the minibuffer and non-lsp completion at point.
( setq
completion-styles ' ( orderless partial-completion basic )
completion-category-defaults nil
completion-category-overrides nil ))
;; ;; Use dabbrev with Corfu!
;; (use-package dabbrev
;; ;; Swap M-/ and C-M-/
;; :bind (("M-/" . dabbrev-completion)
;; ("C-M-/" . dabbrev-expand)))
;; A few more useful configurations...
( use-package
emacs
:init
;; 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)
)
;; Enable vertico
( use-package
vertico
:init ( vertico-mode )
:bind ( :map vertico-map ( "C-j" . vertico-exit-input ))
;; Different scroll margin
;; (setq vertico-scroll-margin 0)
;; Show more candidates
;; (setq vertico-count 20)
;; Grow and shrink the Vertico minibuffer
;; (setq vertico-resize t)
;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
;; (setq vertico-cycle t)
)
;; Persist history over Emacs restarts. Vertico sorts by history position.
( use-package savehist :init ( savehist-mode ))
;; A few more useful configurations...
( use-package
emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
( defun crm-indicator ( args )
( cons
( format "[CRM%s] %s"
( replace-regexp-in-string
"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" crm-separator )
( 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 ))
Selectrum Currently using Vertico over this
(setq projectile-completion-system 'default)
;; (setq projectile-completion-system 'default)
(use-package selectrum :config (selectrum-mode t))
(use-package
selectrum-prescient
:config (selectrum-prescient-mode t) (prescient-persist-mode t)
(setq enable-recursive-minibuffers t)
;; Persist history over Emacs restarts
(savehist-mode)
;; Optional performance optimization
;; by highlighting only the visible candidates.
(setq orderless-skip-highlighting (lambda () selectrum-is-active))
(setq selectrum-highlight-candidates-function
#'orderless-highlight-matches))
Ivy/Counsel/Swiper Settings Currently not using this in favor of Vertico
(use-package ivy)
(use-package counsel)
(use-package swiper)
;; Case insensitive searchs
(setq completion-ignore-case t)
(setq case-fold-search nil)
(setq
counsel-find-file-ignore-regexp
"^\\.?#\\|^\\.\\(DS_Store\\|localized\\|AppleDouble\\)$\\|^\\.\\.$")
(ivy-mode 1) ;; Turn on ivy by default
(setq ivy-use-virtual-buffers t) ;; no idea, but recommended by project maintainer
(setq enable-recursive-minibuffers t) ;; no idea, but recommended by project maintainer
(setq ivy-count-format "(%d/%d) ") ;; changes the format of the number of results
(global-set-key
(kbd "C-s")
'swiper) ;; replaces i-search with swiper
(global-set-key
(kbd "M-x")
'counsel-M-x) ;; Gives M-x command counsel features
(global-set-key
(kbd "C-x C-f")
'counsel-find-file) ;; gives C-x C-f counsel features
(global-set-key
(kbd "C-x b")
'counsel-switch-buffer) ;; gives C-x C-f counsel features
(global-set-key (kbd "<f1> f") 'counsel-describe-function)
(global-set-key (kbd "<f1> v") 'counsel-describe-variable)
(global-set-key (kbd "<f1> l") 'counsel-find-library)
(global-set-key (kbd "<f2> i") 'counsel-info-lookup-symbol)
(global-set-key (kbd "<f2> u") 'counsel-unicode-char)
(global-set-key (kbd "C-c C-r") 'ivy-resume)
(global-set-key (kbd "C-c g") 'counsel-git)
(global-set-key (kbd "C-c j") 'counsel-git-grep)
(global-set-key
(kbd "C-c k")
'counsel-ag) ;; add counsel/ivy features to ag package
(global-set-key (kbd "C-x l") 'counsel-locate)
(global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
;;(define-key read-expression-map (kbd "C-r") 'counsel-expression-history)
(define-key ivy-minibuffer-map (kbd "C-j") 'ivy-immediate-done)
(define-key ivy-minibuffer-map (kbd "C-M-j") nil)
;;set action options during execution of counsel-find-file
;; replace "frame" with window to open in new window
(ivy-set-actions
'counsel-find-file
'(("j" find-file-other-frame "other frame")
("b" counsel-find-file-cd-bookmark-action "cd bookmark")
("x" counsel-find-file-extern "open externally")
("d" delete-file "delete")
("r" counsel-find-file-as-root "open as root")))
;; set actions when running C-x b
;; replace "frame" with window to open in new window
(ivy-set-actions
'ivy-switch-buffer
'(("j" switch-to-buffer-other-frame "other frame")
("k" kill-buffer "kill")
("r" ivy--rename-buffer-action "rename")))
;; Use fuzzy matching for ivy in modes that aren't swiper
(setq ivy-re-builders-alist
'((swiper . ivy--regex-plus) (t . ivy--regex-fuzzy)))
;; Don't list .. and . in the ivy files search
(setq ivy-extra-directories ())
;; Persist histories across startups
(use-package prescient)
(use-package ivy-prescient)
;; Use prescient to store history of search results and preference based on these
(ivy-prescient-mode)
(prescient-persist-mode t)
(use-package counsel-projectile)
(counsel-projectile-mode)
(setq projectile-completion-system 'ivy)
(use-package
all-the-icons-ivy-rich
:config (all-the-icons-ivy-rich-mode t))
(use-package ivy-rich :config (ivy-rich-mode t))
Company Settings Company was a great package, but I’m currently not using it. I migrated over to the simpler and more flexible Corfu.
(use-package
company
:config
;; Dont wait to show completions
(setq company-idle-delay 0)
(setq company-minimum-prefix-length 1)
(setq company-quickhelp-delay nil)
(global-company-mode t)
(use-package
company-async-files
:straight
'(company-async-files
:type git
:host github
:repo "CeleritasCelery/company-async-files"))
; I dont want these company backends
(setq company-backends (remove 'company-bbdb company-backends))
(setq company-backends (remove 'company-eclim company-backends))
(setq company-backends (remove 'company-semantic company-backends))
(setq company-backends (remove 'company-clang company-backends))
(setq company-backends (remove 'company-xcode company-backends))
(setq company-backends (remove 'company-cmake company-backends))
;; (setq company-backends (remove 'company-files company-backends))
(setq company-backends
(remove 'company-dabbrev-code company-backends))
(setq company-backends (remove 'company-dabbrev company-backends))
; I dont want these company backends
(setq company-backends (remove 'company-bbdb company-backends))
(setq company-backends (remove 'company-eclim company-backends))
(setq company-backends (remove 'company-semantic company-backends))
(setq company-backends (remove 'company-clang company-backends))
(setq company-backends (remove 'company-xcode company-backends))
(setq company-backends (remove 'company-cmake company-backends))
;; (setq company-backends (remove 'company-files company-backends))
(setq company-backends
(remove 'company-dabbrev-code company-backends))
(setq company-backends (remove 'company-dabbrev company-backends)))
(use-package
company-quickhelp
:config ;; Sort by recent use
(company-quickhelp-mode))
(setq company-dabbrev-downcase nil)
(use-package company-box :hook (company-mode . company-box-mode))
(use-package company-prescient :config (company-prescient-mode t))
;; Add yasnippet support for all company backends
;; https://github.com/syl20bnr/spacemacs/pull/179
(defvar company-mode/enable-yas t
"Enable yasnippet for all backends.")
(defun company-mode/backend-with-yas (backend)
(if (or (not company-mode/enable-yas)
(and (listp backend) (member 'company-yasnippet backend)))
backend
(append
(if (consp backend)
backend
(list backend))
'(:with company-yasnippet))))
(setq company-backends
(mapcar #'company-mode/backend-with-yas company-backends))
(use-package company-posframe :config (company-posframe-mode t))
MATLAB (use-package
matlab-mode
'(matlab-mode
:type git
:repo "https://git.code.sf.net/p/matlab-emacs/src"))
(require 'matlab)
(setq matlab-shell-command-switches '("-nodesktop" "-nosplash"))
Consult/Embark/Marginalia Marginalia ( use-package marginalia :demand t :config ( marginalia-mode ))
Embark ( use-package
embark
:demand t
:bind
(( "C-." . embark-act ) ;; pick some comfortable binding
;; ("C-;" . embark-dwim) ;; good alternative: M-.
( "C-h B" . embark-bindings )) ;; alternative for `describe-bindings'
:init
;; Optionally replace the key help with a completing-read interface
( setq prefix-help-command #' embark-prefix-help-command )
:config
;; Hide the mode line of the Embark live/completions buffers
( add-to-list
'display-buffer-alist
' ( "\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
( window-parameters ( mode-line-format . none )))))
;; Consult users will also want the embark-consult package.
( use-package
embark-consult
:ensure t ; only need to install it, embark loads it after consult if found
:after consult
:hook ( embark-collect-mode . consult-preview-at-point-mode ))
Consult ;; Example configuration for Consult
( use-package
consult
:demand t
;; Replace bindings. Lazily loaded due by `use-package'.
:bind
( ;; C-c bindings (mode-specific-map)
( "C-c h" . consult-history )
( "C-c m" . consult-mode-command )
( "C-c b" . consult-bookmark )
( "C-c k" . consult-kmacro )
;; C-x bindings (ctl-x-map)
( "C-x M-:" . consult-complex-command ) ;; orig. repeat-complex-command
( "C-x b" . consult-buffer ) ;; orig. switch-to-buffer
( "C-x 4 b" . consult-buffer-other-window ) ;; orig. switch-to-buffer-other-window
( "C-x 5 b" . consult-buffer-other-frame ) ;; orig. switch-to-buffer-other-frame
;; Custom M-# bindings for fast register access
( "M-#" . consult-register-load )
( "M-'" . consult-register-store ) ;; orig. abbrev-prefix-mark (unrelated)
( "C-M-#" . consult-register )
;; Other custom bindings
( "M-y" . consult-yank-pop ) ;; orig. yank-pop
( "<help> a" . consult-apropos ) ;; orig. apropos-command
;; M-g bindings (goto-map)
( "M-g e" . consult-compile-error )
( "M-g f" . consult-flymake ) ;; Alternative: consult-flycheck
( "M-g g" . consult-goto-line ) ;; orig. goto-line
( "M-g M-g" . consult-goto-line ) ;; orig. goto-line
( "M-g o" . consult-outline ) ;; Alternative: consult-org-heading
( "M-g m" . consult-mark )
( "M-g k" . consult-global-mark )
( "M-g i" . consult-imenu )
( "M-g I" . consult-imenu-multi )
;; M-s bindings (search-map)
( "M-s f" . consult-find )
( "M-s F" . consult-locate )
( "M-s g" . consult-grep )
( "M-s G" . consult-git-grep )
;; ("M-s r" . consult-ripgrep)
( "M-s r" . consult-ripgrep-project-root )
( "M-s l" . consult-line )
( "M-s L" . consult-line-multi )
( "M-s m" . consult-multi-occur )
( "M-s k" . consult-keep-lines )
( "M-s u" . consult-focus-lines )
;; Isearch integration
( "M-s e" . consult-isearch-history )
:map
isearch-mode-map
( "M-e" . consult-isearch-history ) ;; orig. isearch-edit-string
( "M-s e" . consult-isearch-history ) ;; orig. isearch-edit-string
( "M-s l" . consult-line ) ;; needed by consult-line to detect isearch
( "M-s L" . consult-line-multi )) ;; needed by consult-line to detect isearch
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI. You may want to also
;; enable `consult-preview-at-point-mode` in Embark Collect buffers.
:hook ( completion-list-mode . consult-preview-at-point-mode )
;; The :init configuration is always executed (Not lazy)
:init
( defun consult-ripgrep-project-root ( &optional initial )
( interactive "P" )
( let (( dir ( funcall consult-project-function )))
( consult--grep
"Ripgrep" #' consult--ripgrep-make-builder dir initial )))
;; (setq consult-ripgrep-args "rg --null --line-buffered --color=never --max-columns=1000 --path-separator /\ --smart-case --no-heading --line-number .")
( setq consult-project-function 'projectile-project-root )
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
( setq
register-preview-delay 0.1
register-preview-function #' consult-register-format )
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
( advice-add #' register-preview :override #' consult-register-window )
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
( advice-add #' register-preview :override #' consult-register-window )
;; Use Consult to select xref locations with preview
( setq
xref-show-xrefs-function #' consult-xref
xref-show-definitions-function #' consult-xref )
;; Configure other variables and modes in the :config section,
;; after lazily loading the package.
:config
;; Optionally configure preview. The default value
;; is 'any, such that any key triggers the preview.
( setq consult-preview-key nil )
;; For some commands and buffer sources it is useful to configure the
;; :preview-key on a per-command basis using the `consult-customize' macro.
( consult-customize
consult-theme
:preview-key
' ( :debounce 0.2 any )
consult-ripgrep
consult-git-grep
consult-grep
consult-bookmark
consult-recent-file
consult-xref
consult--source-bookmark
consult--source-file-register
consult--source-recent-file
consult--source-project-recent-file
;; :preview-key "M-."
:preview-key ' ( :debounce 0.4 any ))
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
( setq consult-narrow-key "<" ) ;; (kbd "C-+")
;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
;; Optionally configure a function which returns the project root directory.
;; There are multiple reasonable alternatives to chose from.
;;;; 1. project.el (project-roots)
;; (setq consult-project-root-function
;; (lambda ()
;; (when-let (project (project-current))
;; (car (project-roots project)))))
;;;; 2. projectile.el (projectile-project-root)
( autoload 'projectile-project-root "projectile" )
( setq consult-project-root-function #' projectile-project-root )
;;;; 3. vc.el (vc-root-dir)
;; (setq consult-project-root-function #'vc-root-dir)
;;;; 4. locate-dominating-file
;; (setq consult-project-root-function (lambda () (locate-dominating-file "." ".git")))
)
;; Optionally add the `consult-flycheck' command.
( use-package
consult-flycheck
:after consult
:bind ( :map flycheck-command-map ( "!" . consult-flycheck )))
;; Enable Consult-Selectrum integration.
;; This package should be installed if Selectrum is used.
Latex ( use-package
tex
:straight auctex
:defer t
:hook ( LaTeX-mode . visual-line-mode )
:hook ( LaTeX-mode . flyspell-mode )
:hook ( LaTeX-mode . LaTeX-math-mode )
:hook ( LaTeX-mode . TeX-source-correlate-mode )
:config
( setq TeX-auto-save t )
( setq TeX-parse-self t )
( setq-default TeX-master nil )
;; (add-hook 'LaTeX-mode-hook 'company-auctex-init)
;; (add-hook 'LaTeX-mode-hook 'company-mode)
( add-hook 'LaTeX-mode-hook 'turn-on-reftex )
( setq reftex-plug-into-AUCTeX t )
( setq TeX-PDF-mode t ))
( use-package cdlatex )
;; -------------------------/AucTex-------------------------------;;
Snippets Yasnippet ( use-package
yasnippet
:demand t
:init
( load "yasnippet.el" ) ; get rid of weird invalid function issue
)
( use-package
yasnippet-snippets
:demand t
:straight
' ( yasnippet-snippets
:type git
:host github
:repo "jsigman/yasnippet-snippets" ))
( yas-global-mode 1 )
( use-package
consult-yasnippet
:after consult
:config ( global-set-key ( kbd "M-Y" ) 'consult-yasnippet ))
Yasnippet-Capf (use-package
yasnippet-capf
:after cape
:init
(setq yasnippet-capf-lookup-by 'key) ;; key or name
:config (add-to-list 'completion-at-point-functions #'yasnippet-capf))
Terminal Vterm ( use-package
vterm
:init
( setq vterm-always-compile-module t )
( setq vterm-timer-delay 0.01 )
:config ( define-key vterm-mode-map ( kbd "M-k" ) 'kill-this-buffer )
;; (define-key vterm-mode-map (kbd "M-i") 'previous-multiframe-window)
;; (define-key vterm-mode-map (kbd "M-o") 'next-multiframe-window)
( define-key vterm-mode-map ( kbd "M-0" ) 'delete-window )
( define-key vterm-mode-map ( kbd "M-1" ) 'delete-other-windows )
( define-key vterm-mode-map ( kbd "M-2" ) 'split-window-below )
( define-key vterm-mode-map ( kbd "M-3" ) 'split-window-right )
( define-key vterm-mode-map ( kbd "M-T" ) 'vterm-toggle )
( define-key vterm-mode-map ( kbd "M-R" ) 'vterm-toggle-cd )
; Unbind M-s so we can use this for other commands
( define-key vterm-mode-map ( kbd "M-s" ) 'nil )
( setq vterm-toggle-scope 'dedicated )
( setq vterm-toggle-project-root t )
( setq vterm-toggle-cd-auto-create-buffer nil )
( setq vterm-toggle-reset-window-configration-after-exit t )
( setq vterm-toggle-fullscreen-p nil )
( setq vterm-toggle-hide-method 'bury-all-vterm-buffer )
( defun kill-buffer-and-its-windows ( buffer )
"Kill BUFFER and delete its windows. Default is `current-buffer'.
BUFFER may be either a buffer or its name (a string)."
( interactive ( list
( read-buffer "Kill buffer: "
( current-buffer )
'existing )))
( setq buffer ( get-buffer buffer ))
( if ( buffer-live-p buffer ) ; Kill live buffer only.
( let
(( wins ( get-buffer-window-list buffer nil t ))) ; On all frames.
( when ( and ( buffer-modified-p buffer )
( fboundp '1on1-flash-ding-minibuffer-frame ))
( 1on1-flash-ding-minibuffer-frame t )) ; Defined in `oneonone.el'.
( when
( kill-buffer buffer ) ; Only delete windows if buffer killed.
( dolist ( win wins ) ; (User might keep buffer if modified.)
( when ( window-live-p win )
;; Ignore error, in particular,
;; "Attempt to delete the sole visible or iconified frame".
( condition-case nil
( delete-window win )
( error nil ))))))
( when ( interactive-p )
( error
"Cannot kill buffer. Not a live buffer: `%s'" buffer ))))
( setq vterm-kill-buffer-on-exit t )
( define-key
vterm-mode-map ( kbd "M-k" )
( lambda ()
( interactive )
( kill-buffer-and-its-windows ( current-buffer ))))
;; Add goto-address-mode to vterm-mode-hook
( add-hook 'vterm-mode-hook 'goto-address-mode ))
Vterm Toggle ;; Special overrides of vterm toggle functions to work better with projectile
( defun vterm-toggle--new ( &optional buffer-name )
"New vterm buffer."
( let* (( buffer-name ( or buffer-name vterm-buffer-name ))
( project-root
( when vterm-toggle-project-root
( ignore-errors
( projectile-project-root ))))
( default-directory ( or project-root default-directory )))
( if vterm-toggle-fullscreen-p
( vterm buffer-name )
( if ( eq major-mode 'vterm-mode )
( let (( display-buffer-alist nil ))
( vterm buffer-name ))
( vterm-other-window buffer-name )))))
( defun vterm-toggle--project-root ()
( projectile-project-root ))
( use-package
vterm-toggle
:after vterm
:demand t
:bind
( :map
vterm-mode-map
( "<escape>" . vterm-send-C-c )
( "M-T" . vterm-toggle )
( "M-R" . vterm-toggle-cd )
( "M-n" . vterm-toggle-forward )
( "M-p" . vterm-toggle-backward ))
( :map global-map ( "M-T" . vterm-toggle ) ( "M-R" . vterm-toggle-cd ))
:config ( setq vterm-toggle-fullscreen-p nil )
( add-to-list
'display-buffer-alist
' (( lambda ( buffer-or-name _ )
( let (( buffer ( get-buffer buffer-or-name )))
( with-current-buffer buffer
( or ( equal major-mode 'vterm-mode )
( string-prefix-p
vterm-buffer-name ( buffer-name buffer ))))))
( display-buffer-reuse-window display-buffer-in-direction )
( direction . bottom )
( dedicated . t ) ;dedicated is supported in emacs27
( reusable-frames . visible )
( window-height . 0.3 )
( window-width . 0.3 ))))
Ripgrep ( use-package wgrep :config ( setq wgrep-auto-save-buffer t ))
( use-package rg :config ( rg-enable-menu ) ( setq rg-executable "rg" ))
Avy ( use-package
avy
:config
;; (global-set-key
;; (kbd "C-;")
;; 'avy-goto-char-timer) ;; I use this most frequently
( global-set-key
( kbd "C-'" )
'avy-goto-line ) ;; Consistent with ivy-avy
( global-set-key
( kbd "C-M-'" )
'avy-goto-end-of-line ) ;; Consistent with ivy-avy
( setq avy-case-fold-search nil ) ;; case sensitive makes selection easier
( setq avy-indent-line-overlay t ))
Language Server Protocol (LSP) LSP Mode ( setq my/lsp-package "lsp" )
;------------------------LSP---------------------------;
; PATCH BELOW
( setenv "LSP_USE_PLISTS" "true" )
( literate-elisp-load "corfu-vertico-settings.org" )
( use-package
lsp-mode
:custom ( lsp-completion-provider :none ) ; We use corfu
:demand t
:init
( setq lsp-signature-render-documentation t )
( setq lsp-signature-auto-activate t )
( setq lsp-signature-doc-lines 3 )
( setq lsp-prefer-flymake nil )
( setq lsp-idle-delay 0.0 )
( setq lsp-enable-snippet t )
( setq lsp-keymap-prefix "M-P" )
( setq lsp-log-io nil )
( setq lsp-print-performance nil )
( setq lsp-response-timeout 10 )
( setq lsp-enable-on-type-formatting nil )
( setq lsp-keep-workspace-alive nil )
( setq lsp-headerline-breadcrumb-enable-diagnostics nil )
( setq lsp-headerline-breadcrumb-enable nil )
( setq read-process-output-max ( * 1024 1024 ))
( setq lsp-semantic-highlighting-faces t )
( setq lsp-enable-imenu nil )
( setq lsp-enable-text-document-color t )
( setq lsp-completion-no-cache t )
( setq lsp-completion-filter-on-incomplete nil )
( setq lsp-enable-file-watchers t )
( setq lsp-auto-execute-action nil )
( setq lsp-auto-guess-root 't )
( setq lsp-document-sync-method nil )
( setq lsp-completion-use-last-result nil )
( setq lsp-completion-show-kind t )
( setq lsp-completion-show-detail t )
;; (defun my/lsp-mode-setup-completion ()
;; (setf (alist-get
;; 'styles
;; (alist-get 'lsp-capf completion-category-defaults))
;; '(orderless))) ;; Configure orderless
( defun my/lsp-mode-setup-completion ()
( setf ( alist-get
'styles
( alist-get 'lsp-capf completion-category-defaults ))
' ( orderless )))
;; Optionally configure the cape-capf-buster.
( setq-local completion-at-point-functions
( list ( cape-capf-buster #' lsp-completion-at-point )))
:hook
( lsp-mode . lsp-enable-which-key-integration )
( lsp-completion-mode . my/lsp-mode-setup-completion )
;; (lsp-mode . lsp-ui-mode)
)
LSP UI For right now, I don’t really like LSP UI, let’s not load this config
(use-package
lsp-ui
:config
(setq lsp-ui-doc-enable nil)
(setq lsp-ui-peek-enable nil)
(setq lsp-ui-peek-fontify "never") ;; never, on-demand, or always
(setq lsp-ui-peek-list-width 50)
(setq lsp-ui-peek-peek-height 20)
(setq lsp-ui-sideline-code-actions-prefix "")
(setq lsp-ui-doc nil)
;inline right flush docs
(setq lsp-ui-sideline-enable nil)
(setq lsp-ui-sideline-ignore-duplicate t)
(setq lsp-ui-sideline-show-code-actions nil)
(setq lsp-ui-sideline-show-diagnostics nil)
(setq lsp-ui-sideline-show-hover nil)
(setq lsp-ui-sideline-show-symbol nil)
(setq lsp-ui-sideline-delay 0.01)
(add-hook
'lsp--managed-mode-hook
(lambda nil
(interactive)
(remove-hook 'post-self-insert-hook 'lsp--on-self-insert t)))
(define-key
lsp-ui-mode-map
[remap xref-find-definitions]
#'lsp-ui-peek-find-definitions)
(define-key
lsp-ui-mode-map
[remap xref-find-references]
#'lsp-ui-peek-find-references)
(setq lsp-ui-flycheck-enable nil)
(add-hook 'flycheck-mode-hook 'lsp-ui-sideline-mode)
(literate-elisp-load "flycheck-settings.org")
(require 'lsp-ui-flycheck)
(define-key
lsp-ui-flycheck-list-mode-map
(kbd "<M-RET>")
'lsp-ui-flycheck-list--visit)
(define-key
lsp-ui-flycheck-list-mode-map
(kbd "RET")
'lsp-ui-flycheck-list--view)
(setq lsp-ui-doc-header t)
(setq lsp-ui-doc-include-signature t)
(setq lsp-ui-doc-max-height 30)
(setq lsp-ui-doc-max-width 120)
(setq lsp-ui-doc-position (quote at-point))
(setq lsp-ui-doc-use-childframe nil)
(setq lsp-ui-doc-use-webkit nil)
:bind
(:map
lsp-ui-imenu-mode-map
("<return" . lsp-ui-imenu--view)
("RET" . lsp-ui-imenu--view)))
LSP with iedit I’m now using iedit instead of my hand-crafted lsp-mc mode. It is integrated and works slightly better.
;---Multiple cursors------;
( literate-elisp-load "multiple-cursors-settings.org" )
( use-package iedit :init ( setq iedit-toggle-key-default ( kbd "C-," )))
( defun my/lsp-iedit ()
( lsp-iedit-highlights )
;; (iedit-switch-to-mc-mode)
)
( setq my/lsp-highlight-setup "iedit" )
( pcase my/lsp-highlight-setup
( "iedit" ( use-package
iedit
:init
( setq iedit-toggle-key-default nil )
( setq iedit-auto-narrow t )
:bind
( :map
lsp-mode-map
( "M-S" . lsp-iedit-highlights )
( :map iedit-mode-keymap ( "C-g" . iedit--quit )))
:after ( :all lsp-mode )
:custom-face ( iedit-occurrence (( t ( :background "Red" ))))))
( "lsp-mc" ( straight-use-package
' ( lsp-mc :type git :host github :repo "jsigman/lsp-mc" ))
( require 'lsp-mc ) ( add-hook 'lsp-mode-hook 'lsp-mc-mode )))
Modes for LSP Configure here the modes for which you’d like to run LSP mode.
( add-hook 'LaTeX-mode-hook #' lsp-deferred )
( add-hook 'yaml-base-mode-hook #' lsp-deferred )
( add-hook 'json-mode-hook #' lsp-deferred )
( add-hook 'dockerfile-mode-hook #' lsp-deferred )
( setq lsp-enable-on-type-formatting t )
( setq lsp-enable-indentation t )
( add-hook 'sh-mode-hook #' lsp-deferred )
( use-package lsp-mssql :hook ( sql-mode . lsp ))
;; (use-package
;; lsp-markdown
;; :config (add-hook 'markdown-mode-hook 'lsp-markdown))
;; ;; Automatically install lsp servers
( defun my/install-lsp-servers ()
( interactive )
( lsp-install-server t 'pyright )
( lsp-install-server t 'xmlls )
( lsp-install-server t 'yamlls )
( lsp-install-server t 'html-ls )
( lsp-install-server t 'json-ls )
( lsp-install-server t 'dockerfile-ls )
( lsp-install-server t 'bash-ls ))
LSP Docker This mode is used to run language servers in a docker container. At some point I’d like to use this.
(use-package lsp-docker)
LSP File Watchers ( add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\venv\\'" )
( add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\.dvc\\'" )
( add-to-list
'lsp-file-watch-ignored-directories "[/\\\\]\\kubernetes\\'" )
( add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\notes\\'" )
( add-to-list
'lsp-file-watch-ignored-directories "[/\\\\]\\checkpoints\\'" )
( add-to-list
'lsp-file-watch-ignored-directories "[/\\\\]\\experiments\\'" )
( add-to-list
'lsp-file-watch-ignored-directories "[/\\\\]\\.mypy_cache\\'" )
( add-to-list
'lsp-file-watch-ignored-directories "[/\\\\]\\.pytest_cache\\'" )
Eglot Currently not using this in favor of LSP-mode
(use-package eglot)
(setq my/lsp-package 'eglot)
;; (add-to-list 'eglot-server-programs
;; `(python-base-mode . ("pyls" "-v" "--tcp" "--host"
;; "localhost" "--port" :autoport)))
(add-hook 'python-base-mode-hook 'eglot-ensure)
(add-hook 'shell-script-mode 'eglot-ensure)
(add-hook 'yaml-mode 'eglot-ensure)
(add-hook 'js-mode 'eglot-ensure)
; Disable flymake in eglot buffers
(add-hook 'eglot--managed-mode-hook (lambda () (flymake-mode -1)))
(provide 'eglot-settings)
Python ( require 'python )
( setq
python-shell-interpreter "python3"
python-shell-interpreter-args "-i" )
( define-key python-mode-map ( kbd "C-c C-c" ) nil )
( use-package
highlight-indent-guides
:hook ( python-mode . highlight-indent-guides-mode ))
( add-hook
'python-mode-hook
( lambda ()
( mapc
( lambda ( pair ) ( push pair prettify-symbols-alist ))
' ( ;; Syntax
;; ("def" . #x2131)
;; ("not" . #x2757)
( "in" . #x2208 )
;; ("not in" . #x2209)
( "return" . #x27fc ) ( "yield" . #x27fb )
;; ("for" . #x2200)
;; Base Types
;; ("int" . #x2124)
;; ("float" . #x211d)
;; ("str" . #x1d54a)
;; ("True" . #x1d54b)
;; ("False" . #x1d53d)
;; Mypy
;; ("Dict" . #x1d507)
;; ("List" . #x2112)
;; ("Tuple" . #x2a02)
;; ("Set" . #x2126)
;; ("Iterable" . #x1d50a)
;; ("Any" . #x2754)
;; ("Union" . #x22c3)
))))
;; python mode keymap
( define-key python-mode-map ( kbd "C-c C-p" ) nil )
( use-package
py-isort
:config
( define-key python-mode-map ( kbd "M-I" ) 'py-isort-buffer )
( define-key python-ts-mode-map ( kbd "M-I" ) 'py-isort-buffer ))
( use-package
pip-requirements
:init
( add-to-list
'auto-mode-alist
` ( , ( rx "requirements" ( zero-or-more anything ) ".in" string-end )
. pip-requirements-mode )))
Python Docstrings ( use-package
buftra
:straight
' ( buftra.el :type git :host github :repo "humitos/buftra.el" ))
( use-package
py-pyment
:straight
' ( py-cmd-buffer.el
:type git
:host github
:repo "humitos/py-cmd-buffer.el" )
:after python
:config ( setq py-pyment-options ' ( "--output=google" )))
MsPyls LSP Not using this in favor of Pyright
(use-package
lsp-python-ms
:config
(setq lsp-python-ms-cache "System")
(setq lsp-python-ms-completion-add-brackets t)
(setq lsp-python-ms-nupkg-channel "beta")
(setq lsp-python-ms-log-level "Warning")
(setq lsp-document-sync-method nil)
(setq lsp-auto-execute-action nil)
(setq lsp-python-ms-auto-install-server t)
(add-to-list 'company-lsp-filter-candidates '(mspyls . t)))
Pyright LSP ( add-hook 'python-mode-hook #' lsp-deferred )
( setq lsp-diagnostics-disabled-modes
' ( python-mode python-mode python-ts-mode ))
( use-package
lsp-pyright
:straight
' ( lsp-pyright :type git :host github :repo "emacs-lsp/lsp-pyright" )
:init ( setq lsp-pyright-multi-root nil )
( setq lsp-pyright-auto-import-completions nil )
( setq lsp-pyright-diagnostic-mode "workspace" )
( setq lsp-pyright-typechecking-mode "basic" )
( setq lsp-pyright-disable-organize-imports t )
:config ( setq lsp-pyright-log-level "trace" ))
Copying lines as a single line for pasting into the pdbpp debugger ( defun python-multiline-to-singleline ()
"Convert multi-line Python code in the current region to a single line with single spaces."
( interactive )
( when ( use-region-p )
( let* (( start ( region-beginning ))
( end ( region-end ))
( multi-line-code ( buffer-substring start end ))
( single-line-code ( replace-regexp-in-string "[ \t\n]+" " " multi-line-code )))
( kill-new single-line-code )
( message "Single-line code copied to kill ring." ))))
( with-eval-after-load 'python
( define-key python-mode-map ( kbd "C-c C-l" ) 'python-multiline-to-singleline ))
Large Language Models in Emacs Github Copilot ( use-package
copilot
:straight
( :host github :repo "zerolfx/copilot.el" :files ( "dist" "*.el" ))
:bind
( :map
copilot-completion-map (( "M-<return>" . copilot-accept-completion )))
:hook ( prog-mode . copilot-mode )
:hook ( yaml-mode . copilot-mode )
:hook ( org-mode . copilot-mode )
:config
( setq copilot-max-char -1 )
( setq copilot-indent-offset-warning-disable t )
:ensure t )
C3PO This one didn’t work very well
(use-package
c3po
:straight (:host github :repo "d1egoaz/c3po.el")
:config
(setq chat-api-key
(f-read-text (expand-file-name "~/.openai/emacs-key.txt"))))
OpenAI (use-package
openai
:straight
(openai :type git :host github :repo "emacs-openai/openai")
:init (setq openai-key (getenv "OPENAI_API_KEY")))
(use-package
chatgpt
:straight (chatgpt :type git :host github :repo "emacs-openai/chatgpt")
;; :config (setq chatgpt-model "gpt-4-0613")
)
(use-package
codegpt
:straight
(codegpt :type git :host github :repo "emacs-openai/codegpt"))
(use-package
dall-e
:straight
(dall-e :type git :host github :repo "emacs-openai/dall-e"))
Ellama (use-package llm)
(use-package
ellama
:init
(setopt
ellama-provider (make-llm-ollama :chat-model "codellama:34b")))
Flycheck ( use-package
flycheck
:init
( define-fringe-bitmap 'my-flycheck-fringe-indicator
( vector
#b00000000
#b00000000
#b00000000
#b00000000
#b00000000
#b00000000
#b00000000
#b00011100
#b00111110
#b00111110
#b00111110
#b00011100
#b00000000
#b00000000
#b00000000
#b00000000
#b00000000 ))
( flycheck-define-error-level
'error
:severity 2
:overlay-category 'flycheck-error-overlay
:fringe-bitmap 'my-flycheck-fringe-indicator
:fringe-face 'flycheck-fringe-error )
( flycheck-define-error-level
'warning
:severity 1
:overlay-category 'flycheck-warning-overlay
:fringe-bitmap 'my-flycheck-fringe-indicator
:fringe-face 'flycheck-fringe-warning )
( flycheck-define-error-level
'info
:severity 0
:overlay-category 'flycheck-info-overlay
:fringe-bitmap 'my-flycheck-fringe-indicator
:fringe-face 'flycheck-fringe-info )
;; :config
;; (use-package flycheck-pos-tip )
;; (flycheck-pos-tip-mode)
)
; Flycheck
( setq flycheck-idle-change-delay 0.1 )
( setq flycheck-display-errors-delay 0.1 )
( setq flycheck-idle-buffer-switch-delay 0.1 )
( setq flycheck-checkers ( remove 'python-pylint flycheck-checkers ))
( setq flycheck-checkers ( remove 'python-pycompile flycheck-checkers ))
( setq flycheck-checkers ( remove 'python-pyright flycheck-checkers ))
( add-hook 'after-init-hook #' global-flycheck-mode )
( setq flycheck-global-modes
' ( python-base-mode js-mode python-mode python-ts-mode ))
Toggling flycheck buffer with “M-C” I have my own little hook to open the flycheck buffer with M-C
, and close it again with another M-C
keystroke.
( defvar should-delete-flycheck-list-buffer nil )
( defun my/flycheck-list-errors ()
"Open flycheck list if it doesn't exist. If it does, close it."
( interactive )
( let* (( target-buffer-name "*Flycheck errors*" )
( target-buffer ( get-buffer target-buffer-name ))
( target-window ( get-buffer-window target-buffer )))
( if ( and target-buffer target-window )
;; the target buffer exists and window is visible
( progn
( when should-delete-flycheck-list-buffer
( delete-window target-window ))
( kill-buffer target-buffer ))
;; the target buffer doesn't exist or the window isn't visible
( let* (( starting-window-count ( count-windows )))
( flycheck-list-errors )
( setq should-delete-flycheck-list-buffer
( > ( count-windows ) starting-window-count ))))))
( define-key flycheck-mode-map ( kbd "M-C" ) 'my/flycheck-list-errors )
Ruff in flycheck Credit to abo-abo Update: Now supported as part of the official flycheck package.
;; From https://github.com/flycheck/flycheck/issues/1974#issuecomment-1343495202
(flycheck-define-checker
python-ruff
"A Python syntax and style checker using the ruff utility.
To override the path to the ruff executable, set
`flycheck-python-ruff-executable'.
See URL `http://pypi.python.org/pypi/ruff'."
:command
("ruff" "check"
(eval
(when buffer-file-name
(concat "--stdin-filename=" buffer-file-name)))
"-")
:standard-input t
:error-filter
(lambda (errors)
(let ((errors (flycheck-sanitize-errors errors)))
(seq-map #'flycheck-flake8-fix-error-level errors)))
:error-patterns
((warning
line-start
(file-name)
":"
line
":"
(optional column ":")
" "
(id (one-or-more (any alpha)) (one-or-more digit))
" "
(message (one-or-more not-newline))
line-end))
:modes (python-mode python-ts-mode))
(eval-after-load 'flycheck
'(add-to-list 'flycheck-checkers 'python-ruff))
TRAMP General Settings ( setq enable-remote-dir-locals 't )
( setq tramp-chunksize 4050 )
( setq tramp-verbose 10 )
( setq vc-ignore-dir-regexp ( format "\\(%s\\)\\|\\(%s\\)"
vc-ignore-dir-regexp
tramp-file-name-regexp ))
Magit in Tramp Local PATH ( defun my-setup-tramp-path ()
( let (( local-path ( cdr ( assoc 'my-project-specific-path dir-local-variables-alist ))))
( when local-path
( add-to-list 'tramp-remote-path
( concat "/sshx:your_username@remote_host:" local-path )))))
( add-hook 'hack-dir-local-variables-hook #' my-setup-tramp-path )
Lock files Disable lock files in TRAMP
( defun my-tramp-file-name-handler ( operation &rest args )
"Disable file locks for TRAMP files."
( if ( eq operation 'vc-registered )
nil
( let (( file-name-handler-alist
( remove ( cons "\\`/\\(ssh\\|scp\\|ftp\\):" 'my-tramp-file-name-handler )
file-name-handler-alist )))
( apply operation args ))))
( add-to-list 'file-name-handler-alist
' ( "\\`/\\(ssh\\|scp\\|ftp\\):" . my-tramp-file-name-handler ))
Dir-locals helper function I’m still trying to make all my editing features work inside TRAMP with Emacs.
(defun set-remote-venv-path ()
"Set PATH for TRAMP to include the venv/bin directory."
(with-parsed-tramp-file-name default-directory tramp-info
(let* ((absolute-local-directory (if (string= tramp-info-localname "~/")
(tramp-call-process tramp-info-method tramp-info-user tramp-info-host "pwd" nil t nil)
tramp-info-localname))
(remote-path (concat "/" tramp-info-method ":" tramp-info-user "@" tramp-info-host ":" absolute-local-directory)))
(set (make-local-variable 'process-environment)
(append
(list (format "PATH=%svenv/bin:%s"
remote-path
(getenv "PATH")))
process-environment)))))
(defun set-remote-venv-path ()
"Set PATH for TRAMP to include the venv/bin directory."
(with-parsed-tramp-file-name default-directory tramp-info
(let ((remote-path (if (string= tramp-info-localname "~/")
(concat "/" tramp-info-method ":" tramp-info-user "@" tramp-info-host ":/")
(concat "/" tramp-info-method ":" tramp-info-user "@" tramp-info-host ":" tramp-info-localname))))
(set (make-local-variable 'process-environment)
(append
(list (format "PATH=%svenv/bin:%s"
remote-path
(getenv "PATH")))
process-environment)))))
Direnv in Tramp Code exists in an unmerged branch .
( defcustom my-direnv-enabled-hosts nil
"List of remote hosts to use Direnv on.
Each host must have `direnv' executable accessible in the default
environment."
:type ' ( repeat string )
:group 'my )
( defun tramp-sh-handle-start-file-process@my-direnv ( args )
"Enable Direnv for hosts in `my-direnv-enabled-hosts'."
( with-parsed-tramp-file-name
( expand-file-name default-directory ) nil
( if ( member host my-direnv-enabled-hosts )
( progn ( pcase-let (( ` ( , name , buffer , program . , args ) args ))
` ( , name , buffer "direnv" "exec" , localname , program ,@ args )) ( debug ))
args )))
( with-eval-after-load "tramp-sh"
( advice-add
'tramp-sh-handle-start-file-process
:filter-args #' tramp-sh-handle-start-file-process@my-direnv ))
Java/Javascript/JSON ( use-package jq-mode )
( use-package
jsonian
:straight ' ( jsonian :type git :host github :repo "iwahbe/jsonian" :build ( :not autoloads )))
Org Mode ( defun org-src-format-and-save ()
( interactive )
( when ( provided-mode-derived-p major-mode 'python-base-mode )
( if ( and ( boundp 'apheleia-formatter )
( seq-contains-p apheleia-formatter 'ruff ))
( apheleia-format-buffer 'ruff )
( apheleia-format-buffer 'black )))
( when ( eq major-mode 'emacs-lisp-mode )
( elisp-autofmt-buffer ))
( sit-for 0.100 )
( org-edit-src-save ))
( use-package
org
:defer t
:hook ( org-mode-hook . visual-line-mode )
:hook ( org-babel-after-execute-hook . org-display-inline-images )
:hook ( org-babel-after-execute-hook . append )
:bind
( :map
org-mode-map
;; ("\C-cl" . org-store-link)
;; ("\C-ca" . org-agenda)
( "C-'" . nil )
( "C-c C-c" . org-ctrl-c-ctrl-c )
( "C-M-<return>" . my/org-babel-execute-and-next )
( "C-c <" . nil )
:map
org-src-mode-map
( "C-x C-s" . org-src-format-and-save ))
:config
( setq org-format-latex-options
( plist-put org-format-latex-options :scale 2.0 ))
( setq org-latex-create-formula-image-program 'dvisvgm )
( org-babel-do-load-languages
'org-babel-load-languages
' (( emacs-lisp . t )
( sqlite . t )
( shell . t )
( jq . t )
( jupyter . nil )
( python . t )))
( defun my/load-org-jupyter ()
( org-babel-do-load-languages
'org-babel-load-languages ' (( jupyter . t )))
( org-babel-jupyter-aliases-from-kernelspecs 'refresh ))
( visual-line-mode t )
( setq org-log-done t )
;; adding this does some weird stuff in colors
( setq org-startup-indented nil )
;; fontify code in code blocks
( setq org-src-fontify-natively t )
( setq org-confirm-babel-evaluate nil ) ;don't prompt me to confirm everytime I want to evaluate a block
( setq org-src-preserve-indentation t )
( defun my-update-direnv-in-org-src ()
"Update direnv environment variables for org-src buffers."
( when ( and ( bound-and-true-p direnv-mode )
( eq major-mode 'org-mode ))
( let (( org-file-path ( buffer-file-name ( buffer-base-buffer ))))
( when org-file-path
( direnv-update-environment org-file-path )))))
( add-hook 'org-src-mode-hook 'my-update-direnv-in-org-src ))
Org Babel ( setq ob-ipython-command "jupyter" )
( use-package
plantuml-mode
:after org
:config
( setq plantuml-default-exec-mode 'executable )
( setq org-plantuml-exec-mode 'plantuml )
( add-to-list 'auto-mode-alist ' ( "\\.plantuml\\'" . plantuml-mode )))
( use-package ob-napkin )
( use-package mermaid-mode )
( use-package ob-mermaid )
( use-package htmlize :after org )
( defun my/org-babel-execute-and-next ()
( interactive )
( org-babel-execute-src-block )
( org-babel-next-src-block ))
Colors in Org ( use-package
org-bullets
:after org
:hook ( org-mode-hook . org-bullets-mode ))
;;nil means to wrap lines in org mode
( setq org-startup-truncated nil )
Org Modern I thought I liked this at first, but now I’m going to disable it because of some annoying text interactions.
(use-package org-modern :after org :config (global-org-modern-mode))
(use-package
org-modern-indent
:after org
:straight
'(org-modern-indent
:type git
:host github
:repo "jdtsmith/org-modern-indent")
:config
(setq org-startup-indented t)
(add-hook 'org-mode-hook #'org-modern-indent-mode 90))
Org Roam I’m not currently using Org Roam, but maybe some day I’d like to.
(straight-use-package 'org-roam)
(use-package
org-roam
:ensure t
:custom (org-roam-directory (file-truename "~/Documents/PERSONAL/ORG_ROAM/"))
:bind
(("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
;; Dailies
("C-c n j" . org-roam-dailies-capture-today))
:config (org-roam-setup) (require 'org-roam-protocol))
Jupyter ( use-package
zmq
:straight ' ( zmq :host github :repo "nnicandro/emacs-zmq" )
:init
; macro to wrap loading
( defmacro safe-wrap ( fn &rest clean-up )
` ( unwind-protect
( let ( retval )
( condition-case ex
( setq retval
( progn
, fn ))
( 'error
( message ( format "Caught exception: [%s]" ex ))
( setq retval ( cons 'exception ( list ex )))))
retval )
,@ clean-up ))
( defun fix-zmq-file-naming ()
"copy .so to .dylib so that we can proceed with installing zmq"
( let* (( tag ( concat "tags/" zmq-emacs-version ))
( api-url
"https://api.github.com/repos/nnicandro/emacs-zmq/" )
( repo-url "https://github.com/nnicandro/emacs-zmq/" )
( release-url ( concat api-url "releases/" ))
( info
( zmq--download-url
( concat release-url tag ) ( require 'json )
( let (( json-object-type 'plist ))
( ignore-errors
( json-read )))))
( tag-name
( or ( plist-get info :tag_name ) ( throw 'failure nil )))
( ezmq-sys ( concat "emacs-zmq-" ( zmq--system-configuration )))
( assets
( cl-remove-if-not
( lambda ( x ) ( string-prefix-p ezmq-sys x ))
( mapcar
( lambda ( x ) ( plist-get x :name ))
( append ( plist-get info :assets ) nil )))))
( when assets
( let (( default-directory
( file-name-directory ( locate-library "zmq" ))))
;; We have a signature file and a tar.gz file for each binary so the
;; minimum number of files is two.
( if ( > ( length assets ) 2 )
( error "TODO More than one file found" )
( let* (( tgz-file
( cl-find-if
( lambda ( x ) ( string-suffix-p "tar.gz" x )) assets ))
( lib
( expand-file-name ( concat
"emacs-zmq" module-file-suffix )
( expand-file-name
( file-name-sans-extension
( file-name-sans-extension
tgz-file ))))))
( let* (( source-file
( concat ( file-name-sans-extension lib ) ".so" )))
( when ( not ( f-exists? lib ))
( print ( format "Copy from %s to %s" source-file lib ))
( copy-file source-file lib )))
t ))))))
( let ( original-noninteractive-value
noninteractive )
;; this is a hack so i don't have to ask about downloading the compatible binary
( setq noninteractive t )
( safe-wrap
( condition-case nil
( require 'zmq )
( error
( fix-zmq-file-naming )
( require 'zmq )))) ;; set the variable back to its original value
( setq noninteractive original-noninteractive-value )))
( use-package
jupyter
:defer t
:custom ( jupyter-repl-echo-eval-p t )
:config
( defun my-switch-to-python-ts-mode-if-jupyter ()
"Switches to python-ts-mode if the org source block is of type jupyter-python."
( when ( and ( eq major-mode 'python-mode )
( string=
( org-element-property
:language ( org-element-at-point ))
"jupyter-python" ))
( python-ts-mode )))
( add-hook
'org-src-mode-hook 'my-switch-to-python-ts-mode-if-jupyter )
;; (add-to-list 'org-src-lang-modes '("python" . python-ts))
)
Org Markdown This is really only used in the publishing script of my emacs config, I don’t need to load this on every startup.
ox-md (use-package ox-jekyll-md :init (setq org-jekyll-md-include-yaml-front-matter nil))
org-jekyll-lite This is really only used in the publishing script of my emacs config, I don’t need to load this on every startup.
( use-package
ox-jekyll-lite
:after org
:straight
' ( ox-jekyll-lite
:type git
:host github
:repo "jsigman/ox-jekyll-lite" ))
Org Appear ( use-package
org-appear
:straight
' ( org-appear :type git :host github :repo "awth13/org-appear" )
:after org
:hook ( org-mode-hook . org-appear-mode ))
Org Ref (use-package request)
(use-package
org-ref
:after org
:config
(setq org-latex-pdf-process
(list "latexmk -shell-escape -bibtex -f -pdf %f")))
Magit and Version Control Magit ( use-package
magit
:after ( projectile )
:demand t
:init
( setq magit-delete-by-moving-to-trash nil )
( setq vc-handled-backends nil )
( eval-after-load 'magit-branch
' ( progn
( advice-add
'magit-checkout
:after ( lambda ( &rest args ) ( projectile-invalidate-cache nil )))
( advice-add
'magit-branch-and-checkout
:after
( lambda ( &rest args ) ( projectile-invalidate-cache nil )))))
:bind
( :map
magit-mode-map
( "C-x g" . nil )
( "M-G" . nil )
( "M-0" . nil )
( "M-1" . nil )
( "M-2" . nil )
( "M-3" . nil ))
:bind ( :map global-map ( "M-G" . magit-status ))
:config ( use-package transient ))
Forge Haven’t yet found a great use for this.
(use-package
forge
:after magit
:config
; This is so we can access forge information
(setq auth-sources '("~/.authinfo")))
Magit Todos mode This is currently broken for me.
(use-package magit-todos :config (magit-todos-mode t))
Magit coloring git-gutter
( use-package
git-gutter+
:config ( global-git-gutter+-mode t )
( setq git-gutter+-modified-sign " " ) ;; two space
( setq git-gutter+-added-sign "+" ) ;; multiple character is OK
( setq git-gutter+-deleted-sign "-" )
( set-face-foreground 'git-gutter+-modified "magenta" )
( set-face-foreground 'git-gutter+-added "dark green" )
( set-face-foreground 'git-gutter+-deleted "red" ))
( use-package pcre2el )
( use-package async )
( use-package hl-todo )
( use-package rg )
( use-package ag )
( use-package ghub :defer t )
; add this so that git gutter plus does not screw up tramp sessions
; it disables GGP during tramp
( defun git-gutter+-refresh ()
( git-gutter+-clear )
( when ( not ( file-remote-p ( buffer-file-name )))
( let (( file ( buffer-file-name )))
( when ( and file ( file-exists-p file ))
( if ( file-remote-p file )
( let* (( repo-root ( git-gutter+-root-directory file ))
( default-directory
( git-gutter+-remote-default-directory
repo-root file )))
( git-gutter+-process-diff
( git-gutter+-remote-file-path repo-root file )))
( git-gutter+-process-diff
( git-gutter+-local-file-path file )))))))
diff-hl
(use-package
diff-hl
:config (global-diff-hl-mode)
(add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh)
(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))
Ediff ( use-package
ediff
:defer t
:init ( setq ediff-split-window-function 'split-window-horizontally )
( setq ediff-window-setup-function
'ediff-setup-windows-plain )
( setq ediff-diff-options "-w" ))
Multiple Cursors (MC) ( use-package
multiple-cursors
:config
( global-set-key ( kbd "C-M-j" ) 'mc/edit-lines )
( global-set-key ( kbd "C->" ) 'mc/mark-next-like-this )
( global-set-key ( kbd "C-<" ) 'mc/mark-previous-like-this )
( global-set-key ( kbd "C-c C-<" ) 'mc/mark-all-like-this )
( global-set-key ( kbd "C-M-=" ) 'mc/mark-all-symbols-like-this ))
Docker ( use-package
dockerfile-mode
:config ( setq dockerfile-mode-command "docker" ))
( use-package docker
:ensure t
:bind ( "C-c d" . docker ))
Debug Adapter Protocal (DAP) I’m currently not using DAP mode, and prefer to use python from the command line (vterm) with pdb
. Some day I’d like to learn this.
(use-package
dap-mode
:init
(if (eq system-type 'gnu/linux)
(add-to-list 'image-types 'svg))
:config
(add-hook
'dap-stopped-hook (lambda (arg) (call-interactively #'dap-hydra)))
;; Enabling only some features
(setq dap-auto-configure-features
'(sessions locals controls tooltip))
(setq dap-python-debugger 'debugpy)
(require 'dap-mode)
(require 'dap-python)
(require 'dap-ui)
(add-hook 'python-mode-hook 'dap-mode)
(add-hook 'python-mode-hook 'dap-ui-mode)
(add-hook 'python-mode-hook 'dap-tooltip-mode)
(define-key python-mode-map (kbd "M-D") #'dap-hydra))
Treemacs ( use-package
treemacs
:bind (( "M-P" . treemacs ))
:config ( setq treemacs-persist-file "treemacs-persist" ))
( use-package treemacs-projectile :after treemacs )
( use-package
treemacs-icons-dired
:after
treemacs
dired
:config ( treemacs-icons-dired-mode ))
Markdown ( use-package
markdown-mode
:mode ( "README\\.md\\'" . gfm-mode )
:init ( setq markdown-command "multimarkdown" )
:hook ( markdown-mode . lsp-deferred )
:config )
HTML (when (not (eq system-type 'gnu/linux))
(require 'html-ts-mode)
(define-key html-ts-mode-map (kbd "M-o M-o") nil)
(define-key html-mode-map (kbd "M-o M-o") nil)
(define-key sgml-mode-map (kbd "M-o M-o") nil)
(define-key html-mode-map (kbd "M-o") nil)
(define-key sgml-mode-map (kbd "M-o") nil)
(define-key html-mode-map (kbd "M-o") 'next-multiframe-window)
(define-key html-mode-map (kbd "M-i") 'previous-multiframe-window)
(define-key html-ts-mode-map (kbd "M-o M-o") nil)
(define-key html-ts-mode-map (kbd "M-o") nil)
(define-key html-ts-mode-map (kbd "M-o") 'next-multiframe-window)
(define-key
html-ts-mode-map (kbd "M-i") 'previous-multiframe-window))
Web mode ( use-package
web-mode
:config
( add-to-list 'auto-mode-alist ' ( "\\.liquid\\'" . web-mode )))
Lua Non-gnu ELPA version (use-package
lua-mode
:ensure t
:mode ("\\.lsyncd\\.conf\\'" . lua-mode))
lua-ts-mode (use-package
lua-ts-mode
:straight
'(lua-ts-mode
:type git
:host nil
:repo "https://git.sr.ht/~johnmuhl/lua-ts-mode"
:files ("*.el"))
:mode (("\\.lua\\'" . lua-ts-mode) ("lsyncd\\.conf\\'" . lua-ts-mode))
:config
;; Any additional configuration you might want goes here
)
Tree-Sitter Tree-Sitter mode This is the old way of using tree-sitter
in emacs. In emacs 29, this moved to treesit.
(use-package
tree-sitter
:config (global-tree-sitter-mode t)
:hook ((tree-sitter-after-on-hook . tree-sitter-hl-mode) (python-mode . tree-sitter-hl-mode)))
(use-package tree-sitter-langs)
Combobulate Combobulate seems like a cool idea, but I’ve found it to be more frustrating than helpful in python.
( use-package
combobulate
:straight ' ( combobulate :type git :host github :repo "mickeynp/combobulate" )
;; You can manually enable Combobulate with `M-x
;; combobulate-mode'.
:hook
(( python-ts-mode . combobulate-mode )
( js-ts-mode . combobulate-mode )
( css-ts-mode . combobulate-mode )
( yaml-ts-mode . combobulate-mode )
( typescript-ts-mode . combobulate-mode )
( tsx-ts-mode . combobulate-mode ))
;; Amend this to the directory where you keep Combobulate's source
;; code.
:bind
( :map
combobulate-key-map (( "C-;" . combobulate-avy-jump ) ( "M-k" . nil ))))
Treesit ( defun copy-different-key-bindings ( source-map dest-map )
"Copy key bindings from SOURCE-MAP to DEST-MAP, but only where they differ."
( map-keymap
( lambda ( binding value )
( unless ( eq value ( lookup-key dest-map ( vector binding )))
( define-key dest-map ( vector binding ) value )))
source-map ))
( use-package
treesit-auto
:straight ' ( treesit-auto :type git :host github :repo "renzmann/treesit-auto" )
:demand t
:init
( setq treesit-auto-install t )
( setq treesit-auto-langs
' ( awk
bash
bibtex
c
cmake
commonlisp
cpp
css
dockerfile
html
java
javascript
json
latex
make
markdown
proto
python
ruby
toml
typescript
yaml ))
:config ( global-treesit-auto-mode )
;; set up treesit mode hooks for relevant modes
( setq python-ts-mode-hook python-mode-hook )
( setq yaml-ts-mode-hook yaml-mode-hook )
( setq json-ts-mode-hook json-mode-hook )
;; (setq js-ts-mode-hook js-mode-hook)
( setq markdown-ts-mode-hook markdown-mode-hook )
( setq bash-ts-mode-hook sh-mode-hook )
;; Then call the function like this:
( copy-different-key-bindings python-mode-map python-ts-mode-map )
;; (copy-different-key-bindings yaml-mode-map yaml-ts-mode-map)
;; (copy-different-key-bindings json-mode-map json-ts-mode-map)
;; (copy-different-key-bindings markdown-mode-map markdown-ts-mode-map)
( copy-different-key-bindings sh-mode-map bash-ts-mode-map ))
Modeline Telephone Line (use-package
telephone-line
:config
(setq telephone-line-lhs
'((evil . (telephone-line-evil-tag-segment))
(accent
.
(telephone-line-vc-segment
telephone-line-erc-modified-channels-segment
telephone-line-process-segment))
(nil
.
(telephone-line-minor-mode-segment
telephone-line-buffer-segment))))
(setq telephone-line-rhs
'((nil . (telephone-line-misc-info-segment))
(accent . (telephone-line-major-mode-segment))
(evil . (telephone-line-airline-position-segment))))
(telephone-line-mode t))
Doom Modeline Bugfix: Requires installing shrink path manually on linux. Not sure why.
( use-package
shrink-path
:straight
' ( shrink-path :type git :host github :repo "zbelial/shrink-path.el" ))
( use-package doom-modeline :config ( doom-modeline-mode 1 ) ( setq doom-modeline-unicode-fallback t ))
Awesome Tray (use-package
awesome-tray
:straight
'(awesome-tray
:type git
:host github
:repo "manateelazycat/awesome-tray")
:init
(setq awesome-tray-active-modules
'("buffer-name" "mode-name" "belong")) ;TODO: add "belong" back in after treesit
:config (awesome-tray-mode 1) awesome-tray-active-modules)
Diminish/Blackout (use-package diminish)
(diminish 'anzu-mode)
(diminish 'ivy-mode)
(diminish 'rainbow-mode)
(diminish 'eldoc-mode)
(diminish 'projectile-mode)
(diminish 'blacken-mode)
(diminish 'python-black-on-save-mode)
(diminish 'which-key-mode)
(diminish 'flycheck-mode)
(add-hook 'undo-tree-mode-hook (lambda () (diminish 'undo-tree-mode)))
(diminish 'auto-revert-mode)
(diminish 'beacon-mode)
(diminish 'all-the-icons-dired-mode)
(diminish 'tree-sitter-hl-mode)
(use-package blackout)
(blackout 'ivy-mode)
(blackout 'company-posframe-mode)
(blackout 'company-mode)
(diminish 'yas-mode)
(blackout 'yas-minor-mode)
(blackout 'rainbow-mode)
(blackout 'which-key-mode)
(blackout 'projectile-mode)
(blackout 'git-gutter-mode)
(blackout 'git-gutter+-mode)
(blackout 'goggles-mode)
(blackout 'org-roam-mode)
(blackout 'polymode)
(blackout 'poly-org-mode)
(blackout 'smartparens-mode)
(blackout 'visual-line-mode)
(blackout 'anzu-mode)
(blackout 'apheleia-mode)
(blackout 'explain-pause-mode)
(blackout 'volatile-highlights-mode)
(blackout 'all-the-icons-dired-mode)
(blackout 'jupyter-repl-interaction-mode)
(blackout 'page-break-lines-mode)
(blackout 'org-src-mode)
(blackout 'whole-line-or-region-local-mode)
(blackout 'smartparens-mode)
(blackout 'tree-sitter-hl-mode)
(blackout 'tree-sitter-mode)
(blackout 'highlight-indent-guides-mode)
(blackout 'copilot-mode)
(diminish 'jupyter-repl-interaction-mode)
(diminish 'page-break-lines-mode)
(diminish 'org-src-mode)
(diminish 'highlight-indent-guides)
Colors and Theme ;; Treat all themes as safe; no query before use.
( setf custom-safe-themes 't )
( setq frame-title-format nil )
Emacs Theme Leuven Leuven is always a nice option, beautiful with Org Mode.
(use-package leuven-theme
:config
(load-theme 'leuven-dark))
Trying this theme out for a little bit.
( use-package
catppuccin-theme
:config
( load-theme 'catppuccin :no-confirm )
( setq catppuccin-flavor 'frappe )
;; (setq catppuccin-flavor 'latte)
;; (setq catppuccin-flavor 'macchiato)
;; (setq catppuccin-flavor 'mocha)
( catppuccin-reload ))
ef-day I’m always changing my theme, but I tend to like light themes with yellow-ish backgrounds. Almost like handwriting with a yellow memo pad.
(use-package ef-themes :config (load-theme 'ef-day t))
Gruvbox-dark (use-package
gruvbox-theme
:ensure t
:config (load-theme 'gruvbox-dark-hard :no-confirm)
;; :after (centered-window-mode) :hook (centered-window-mode . cwm-update-fringe-background)
)
Nano (use-package
nano
:straight
(nano-emacs :type git :host github :repo "rougier/nano-emacs")
:config (require 'nano))
Colors in Dired ( use-package rainbow-mode :hook ( LaTeX-mode . rainbow-mode ))
( use-package dired-hacks :hook ( emacs-lisp-mode . rainbow-mode ))
Catch if running centered-window-mode This may be needed to set the fringe to the new background color. Run it when startup is finished.
( add-hook 'emacs-startup-hook
( lambda ()
( when ( fboundp 'cwm-update-fringe-background )
( cwm-update-fringe-background ))))