These configurations represent my preferred version of Emacs, one that tries to
be as minimalist as I want possible. Beware that this configuration uses a
cutting-edge version of Emacs, so YMMV.
emacs-version
Cool Emacs configs from cool people:
- Lots of cool people
- hrs (he likes org-mode and evil)
- Konrad’s and Arnaud’s
- The doom-emacs guy
- Introduction
- What packages you can find here
- =use-package=
- :after
- :defer
- :demand
- :init
- :config
- Personal
- Package configuration
- Setting-up
- Support
- Built-in
- Extensions
- =smart-mode-line=
- =orderless=
- =cape=
- =vertico=
- =corfu=
- =consult=
- =marginalia=
- =undo-tree=
- =dashboard=
- =treemacs=
- =exec-path-from-shell=
- =anzu=
- =deadgrep=
- =link-hint=
- =avy=
- =which-key=
- =eglot=
- =highlight-numbers=
- =highlight-escape-sequences=
- =flyspell=
- =diff-hl=
- =ace-window=
- =super-save=
- =yasnippet=
- =vimish-fold=
- =magit=
- =git-timemachine=
- =expand-region=
- =smartparens=
- =rainbow-delimiters=
- =beacon=
- =aggressive-indent=
- =highligh-indent-guides=
- =helpful=
- =openwith=
- =page-break-lines=
- =writeroom-mode=
- =ssh=
- =ligature.el=
- =mixed-pitch-mode=
- =hl-todo=
- =emacs-tree-sitter=
- =lispy=
- =embark=
- =embark-consult=
- =notmuch=
- =tempel=
- =forge=
- =puni=
- =info-colors=
- Theme
- File modes
- =prog-mode=
- =text-mode=
- Org
- =cc-mode= languages
- C/C++
- CUDA
- R
- Shell script
- Makefile
- PlantUML
- Lisp
- Elisp
- Python
- CMake
- Dockerfile
- GMPL
- Julia
- LaTeX
- Meson
- sxhkdrc
- Configuration files
- Rust
- Perl
- Dot (Graphviz)
- Bison/Flex/Yacc
- Markdown
- JavaScript
- Typescript
- Clojure
- Racket
- YAML
- GGO
- Git-related files
- Go Language
- Terraform
- Vimscript
- Lua
- Local variables
First of all, welcome to my configuration file for Emacs. I built it from almost the ground up, picking up configs from several sources, some of which I’ve cited in the beginning of this file.
As I’d like that this file be used as a source of inspiration for others, I
wrote it in an .org
file, using all of org-mode
’s black magic powers of tangling
source blocks to intertwine both source .el
and prose.
Also, I’ve used in almost all sections of this document a package called
use-package
in order to organize all the additional packages that I use to get a
better Emacs experience. So, I’ll teach you to read a use-package
statement!
That way you can understand what’s happening beneath all sugar syntax.
You can find the following packages in this configuration file:
- ace-window
- aggressive-indent
- ansi-color
- anzu
- auctex
- auctex-latexmk
- autoinsert
- auto-virtualenv
- avy
- bash-completion
- beacon
- bison
- cape
- cargo
- cc-mode
- cider
- clang-format
- clj-refactor
- clojure-mode
- clojure-mode-extra-font-locking
- cmake-font-lock
- cmake-mode
- comint
- compile
- conf-mode
- consult
- corfu
- corfu-doc
- cperl-mode
- crux
- cuda-mode
- dashboard
- deadgrep
- delight
- diff-hl
- dired
- dockerfile-mode
- eglot
- elec-pair
- electric
- elisp-mode
- elisp-slime-nav
- embark
- embark-consult
- ess
- ess-r-mode
- exec-path-from-shell
- expand-region
- files
- flymake
- flymake-diagnostic-at-point
- forge
- gcmh
- gdb-mi
- general
- ggo-mode
- git-modes
- git-timemachine
- gmpl-mode
- go-mode
- graphviz-dot-mode
- gruvbox-theme
- gud
- hcl-mode
- helpful
- hide-mode-line
- highlight-doxygen
- highlight-escape-sequences
- highlight-indent-guides
- highlight-numbers
- hl-todo
- htmlize
- hydra
- ibuffer
- inf-clojure
- info-colors
- js
- julia-mode
- jupyter
- ligature
- link-hint
- lisp-extra-font-lock
- lisp-mode
- lispy
- lua-mode
- magit
- make-mode
- marginalia
- markdown-mode
- meson-mode
- midnight
- mixed-pitch
- mode-local
- modern-cpp-font-lock
- no-littering
- notmuch
- ob
- ob-R
- openwith
- orderless
- org
- org-agenda
- org-appear
- org-attach
- org-bars
- org-capture
- org-contrib
- org-id
- org-inline-pdf
- org-journal
- org-ref
- org-refile
- ox
- ox-beamer
- ox-dnd
- ox-extra
- ox-hugo
- ox-latex
- ox-twbs
- page-break-lines
- paren
- plantuml-mode
- preproc-font-lock
- prog-mode
- project
- puni
- pyenv
- python
- racket-mode
- rainbow-delimiters
- recentf
- reftex
- rust-mode
- sendmail
- sh-script
- smart-mode-line
- smartparens
- smerge-mode
- ssh
- subword
- super-save
- sxhkd-mode
- tempel
- terraform-mode
- tex
- text-mode
- toc-org
- tramp
- treemacs
- tree-sitter
- tree-sitter-langs
- typescript-mode
- undo-tree
- uniquify
- use-package
- vertico
- vertico-directory
- view
- vimish-fold
- vimrc-mode
- visual-fill-column
- websocket
- which-key
- whitespace
- windmove
- writeroom-mode
- wucuo
- xref
- yaml-mode
- yasnippet
- zmq
Briefly, this package wraps your configuration for a given package in a neat little statement, which can include several useful categorizations and sub-tools.
Here are all little keywords you can use to organize your configs:
The :after
keyword sets a relation of dependency between the loading
of two packages. In other words, you can tell use-package
that a given
package should only be loaded if that other package is already loaded.
(use-package foo)
(use-package bar
:after foo)
(use-package moo
:after (foo bar)) ; Supports mmultiple dependencies!
The :defer
keyword tells use-package
that it can defer the loading
of your package until its absolutely needed. Its behaviour is the
opposite of the keyword :demand
.
(use-package foo
:defer t)
The :demand
keyword says to use-package
that this package must not
be lazy-loaded, and should be loaded right away as Emacs loads.
(use-package foo
:demand)
The :init
keyword can tell use-package
to execute said commands
BEFORE the package is loaded. In reality, said execution will happen
as soon as the use-package
statement is processed on the Emacs loading
process.
(use-package foo
:init
(setq bar t))
The :config
keyword, much like the :init
keyword, tells
use-package
to execute commands. The difference is that commands
defined with this keyword will only execute AFTER the package is
loaded. There is an important difference here, as use-package
uses
what’s called lazy loading, i.e. only load the package when you
actually need it.
(use-package foo
:config
(foo-init))
Stuff that isn’t either a package nor a language nor downloadable: stuff you coded yourself.
To-do:
- [X] Increase/decrease font size
- [ ] Input date on command (and as a new heading in
org-mode
)
Some basic info about me.
(setq user-full-name "Henrique Silva"
user-mail-address "hcpsilva@inf.ufrgs.br")
Some very useful functions I got from other people or that I coded myself.
To get the current selected text without newlines.
(defun hcps/get-selected-text (start end)
(interactive "r")
(when (use-region-p)
(kill-new
(replace-regexp-in-string
"\n" " "
(buffer-substring start end)))))
Insert the current date.
(defun hcps/date-iso ()
"Insert the current date, ISO format, eg. 2016-12-09."
(interactive)
(insert (format-time-string "%F")))
(defun hcps/date-iso-with-time ()
"Insert the current date, ISO format with time, eg. 2016-12-09T14:34:54+0100."
(interactive)
(insert (format-time-string "%FT%T%z")))
(defun hcps/date-long ()
"Insert the current date, long format, eg. December 09, 2016."
(interactive)
(insert (format-time-string "%B %d, %Y")))
(defun hcps/date-long-with-time ()
"Insert the current date, long format, eg. December 09, 2016 - 14:34."
(interactive)
(insert (capitalize (format-time-string "%B %d, %Y - %H:%M"))))
(defun hcps/date-short ()
"Insert the current date, short format, eg. 2016.12.09."
(interactive)
(insert (format-time-string "%Y.%m.%d")))
(defun hcps/date-short-with-time ()
"Insert the current date, short format with time, eg. 2016.12.09 14:34"
(interactive)
(insert (format-time-string "%Y.%m.%d %H:%M")))
‘Cause that is kinda cool to have. Got it from this place.
(defun advise-once (symbol where function &optional props)
(advice-add symbol :after `(lambda (&rest _) (advice-remove ',symbol #',function)))
(advice-add symbol where function props))
To use with this configuration file.
(defconst config-file-name (expand-file-name "config.org" user-emacs-directory)
"The path to the configuration")
(defun hcps/async-byte-compile-org-config ()
"To add as a hook when saving the config file."
(when (yes-or-no-p "Recompile config?")
(let ((default-directory user-emacs-directory)
(compile-script (concat "compile-" (file-name-base config-file-name) ".el")))
(start-process
"Emacs : Config compilation" (concat "*" (file-name-sans-extension compile-script) "*")
"emacs" "--batch" "-l" compile-script))))
Sometimes it’s cool to have a single-use hook.
(eval-and-compile
(defmacro hcps/hook-require-once (hook package)
"Add a hook to `pre-command-hook' which requires the given package once."
(let ((func (intern (concat "hcps/" (symbol-name hook) "-require-" (symbol-name package)))))
`(progn
(defun ,func ()
(remove-hook ',hook #',func)
(require ',package))
(add-hook ',hook #',func)))))
Probably the dumbest way to do this
(defmacro hcps/macro-dolist (macro list-name)
"Kinda like an macro map, but more specific."
(let ((list (symbol-value list-name)))
(macroexp-progn
(mapcar (lambda (item) `(,macro ,item)) list))))
Directly from Magnar Sveen’s s.el
(defun hcps/s-trim-left (s)
"Remove whitespace at the beginning of S."
(declare (pure t) (side-effect-free t))
(if (string-match "\\`[ \t\n\r]+" s)
(replace-match "" t t s)
s))
(defun hcps/s-trim-right (s)
"Remove whitespace at the end of S."
(declare (pure t) (side-effect-free t))
(if (string-match "[ \t\n\r]+\\'" s)
(replace-match "" t t s)
s))
(defun hcps/s-trim (s)
"Remove whitespace at the beginning and end of S."
(declare (pure t) (side-effect-free t))
(s-trim-left (s-trim-right s)))
Inside other languages or strings, like in shell-scripts and such.
- [ ]
org-src-font-lock-fontify-block
org-fontify-meta-lines-and-blocks
(defun hcps/externally-fontify-sub-block (lang start end)
"Shamelessly stolen from `org-mode' implementation (sort-of).
Many languages include code sections in a different language.
This way we don't need to reimplement the font-lock rules and we
still get the pretty colors."
(when (fboundp lang)
(let ((string (buffer-substring-no-properties start end))
(modified (buffer-modified-p))
(this-buffer (current-buffer)))
(remove-text-properties start end '(face nil))
(with-current-buffer
(get-buffer-create (format " *block-fontification:%s*" (symbol-name lang)))
(let ((inhibit-modification-hooks nil))
(erase-buffer)
;; Add string and a final space to ensure property change.
(insert string " "))
(unless (eq major-mode lang) (funcall lang))
(font-lock-ensure)
(let ((pos (point-min))
next)
(while (setq next (next-property-change pos))
;; Handle additional properties from font-lock, so as to
;; preserve, e.g., composition.
(dolist (prop (cons 'face font-lock-extra-managed-props))
(let ((new-prop (get-text-property pos prop)))
(put-text-property
(+ start (1- pos)) (1- (+ start next)) prop new-prop
this-buffer)))
(setq pos next))))
(add-text-properties
start end
'(font-lock-fontified t fontified t font-lock-multiline t))
(set-buffer-modified-p modified))))
(defun hcps/fontify-region-as-lang (lang rx-start rx-end)
(lambda (limit)
(let ((case-fold-search t))
(when (re-search-forward rx-start limit t)
(let ((block-start (match-end 0))
(block-end nil))
(when (re-search-forward rx-end nil t)
(setq block-end (match-beginning 0))
(hcps/externally-fontify-sub-block lang block-start block-end)))))))
A clear modeline is prettier sometimes
(defun hcps/clean-mode-line ()
"Clean mode-line format."
(setq-local mode-line-format ""))
also goddamnit can we please not have variable pitch?
(custom-set-faces '(mode-line-active ((t (:inherit mode-line)))))
Using the transpose-lines
function.
(defmacro ew/save-column (&rest body)
`(let ((column (current-column)))
(unwind-protect
(progn ,@body)
(move-to-column column))))
(defun hcps/move-line-up ()
"Move up the current line."
(interactive)
(ew/save-column
(transpose-lines 1)
(forward-line -2)))
(defun hcps/move-line-down ()
"Move down the current line."
(interactive)
(ew/save-column
(forward-line 1)
(transpose-lines 1)
(forward-line -1)))
Stuff changed in trunk and I’m way too eager to return to stable.
(defun define-obsolete-fix (func obsolete current &optional when &rest args)
(apply func obsolete current (or when "now") args))
(advice-add #'define-obsolete-function-alias :around #'define-obsolete-fix)
(advice-add #'define-obsolete-variable-alias :around #'define-obsolete-fix)
(defun disable-scroll-margin (fun &rest args)
"Disable margin from active line in modes where it is detrimental."
(let ((temp-scroll-margin scroll-margin))
(setq-local scroll-margin 0)
(apply fun args)
(setq-local scroll-margin temp-scroll-margin)))
(defun turn-off-cursor (&rest _)
"It is kinda unnecessary while inside some modes."
(internal-show-cursor nil nil))
Defaults that are better if defined other way.
Silly names for easier path usage.
(eval-and-compile
(defconst current-user (getenv "USER") "The current user.")
(defconst home-dir (getenv "HOME") "The user home dir.")
(defconst lisp-user-dir (expand-file-name "lisp" user-emacs-directory) "The extra emacs-lisp directory.")
(defconst var-user-dir (expand-file-name "var" user-emacs-directory) "The temporaries directory.")
(defconst straight-user-dir (expand-file-name "straight/repos") "The default straight repos directory.")
(defconst vendor-user-dir (expand-file-name "vendor" lisp-user-dir) "The externally .el directory.")
(defconst documents-user-dir (expand-file-name "Documents" home-dir) "The (usually) default documents directory.")
(defconst proj-user-dir (expand-file-name "Repositories" home-dir) "Default projects directory.")
(defconst onedrive-user-dir (expand-file-name "OneDrive" home-dir) "Default OneDrive path."))
Almost every GUI element of Emacs is useless and a waste of screen
space. Most of those are turned off in my early-init.el
config.
And then there’s the title question. I for one like Emacs capitalized, so…
(setq-default frame-title-format
'((capitalize invocation-name)
(:eval (if (buffer-file-name)
(abbreviate-file-name (buffer-file-name))
"%b"))))
Here’s every other setting relating to text editing I can’t categorize any further.
(setq-default fill-column 80
;; posssible values: (left right center full nil)
default-justification 'left
indent-tabs-mode nil
tab-always-indent 'complete
tab-first-completion nil
bidi-paragraph-direction 'left-to-right
sentence-end-double-space nil
tab-width 4
truncate-lines t
truncate-partial-width-windows nil
require-final-newline t
x-stretch-cursor t
cursor-in-non-selected-windows nil)
Here’s everything related to the mode-line.
(setq-default display-time-format "%H:%M "
display-time-default-load-average nil)
;; (add-to-list 'mode-line-misc-info '("@" system-name) t)
(display-time-mode 1)
(line-number-mode 1)
(column-number-mode 1)
(size-indication-mode 1)
I like the vim style of relative numbering of lines. Never mind, I
grew tired of it.
(setq-default display-line-numbers-type t
display-line-numbers-width-start t)
;; I used to do this globally, but now let's only do selectively
;; (add-hook 'prog-mode-hook #'display-line-numbers-mode)
And I also like the vim style of scrolling better.
(setq-default auto-window-vscroll t
;; line-move-visual nil
scroll-conservatively 101
scroll-margin 10)
Small fix for scroll-margin
(defun get-lines-from-top ()
(save-excursion
(beginning-of-line)
(count-screen-lines (point) (window-start))))
(defun scroll-margin-fix (func &rest args)
(apply func args)
(if (> scroll-margin 0)
(let ((diff (- (min scroll-margin (floor (* maximum-scroll-margin (window-screen-lines))))
(get-lines-from-top))))
(when (> diff 0)
(scroll-down 1)))))
(advice-add #'previous-line :around #'scroll-margin-fix)
;; (add-hook 'prog-mode-hook #'visual-line-mode)
Highlighting the current line is also very useful.
(global-hl-line-mode 1)
and let’s enable pixel-scroll-precision-mode
(pixel-scroll-precision-mode 1)
Random configs and definitions that don’t have a clear category.
(setq ad-redefinition-action 'accept ; Silence warnings for redefinition
confirm-kill-emacs #'yes-or-no-p ; Confirm before exiting Emacs
select-enable-clipboard t ; Merge system's and Emacs' clipboard
blink-matching-paren nil ; Disable annoying blink-matching-paren
window-combination-resize t ; Resize windows proportionally
use-dialog-box nil ; dont use graphical dialog boxes
resize-mini-windows t
read-process-output-max (* 1024 1024)
ring-bell-function 'ignore) ; No bell ring
(add-hook 'after-save-hook
#'executable-make-buffer-file-executable-if-script-p)
;; (setq initial-major-mode 'text-mode)
;; (setq initial-scratch-message "\
;; This buffer is for notes you don't want to save.
;; If you want to create a file, visit that file with \\[find-file],
;; then enter the text in that file's own buffer.")
;; Replace yes/no prompts with y/n
(fset #'yes-or-no-p #'y-or-n-p)
;; Set Emacs to call the garbage collector on focus-out
;; (add-hook 'focus-out-hook #'garbage-collect)
;; use GPG-agent instead of the default
(setenv "SSH_AUTH_SOCK"
(expand-file-name "gnupg/S.gpg-agent.ssh" (getenv "XDG_RUNTIME_DIR")))
(setq epg-pinentry-mode 'loopback)
(global-auto-revert-mode t)
;; (setq hippie-expand-try-functions-list '(try-expand-dabbrev
;; try-expand-dabbrev-all-buffers
;; try-expand-dabbrev-from-kill
;; try-complete-file-name-partially
;; try-complete-file-name
;; try-expand-all-abbrevs
;; try-expand-list
;; try-expand-line
;; try-complete-lisp-symbol-partially
;; try-complete-lisp-symbol))
;; (require 'ediff)
;; (setq ediff-window-setup-function 'ediff-setup-windows-plain)
;; (require 'eshell)
;; (setq eshell-directory-name (expand-file-name "eshell" var-user-dir))
;; (global-diff-hl-mode 1)
;; (add-hook 'dired-mode-hook 'diff-hl-dired-mode)
;; ;; use hippie-expand instead of dabbrev
;; (global-set-key (kbd "M-/") 'hippie-expand)
Finally, let’s load our custom variables
(setq custom-file (expand-file-name "custom.el" var-user-dir))
(when (file-exists-p custom-file)
(load-file custom-file))
Everything that isn’t an specific file-mode .el
.
Some setting up before we start configuring the packages themselves.
(eval-and-compile
(setq straight-check-for-modifications '(check-on-save find-when-checking))
(defvar bootstrap-version)
(let ((bootstrap-file (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(setq package-user-dir (expand-file-name "straight" user-emacs-directory))
(unless (file-directory-p package-user-dir)
(make-directory package-user-dir t)))
I use use-package
to load my packages and to organize them neatly in this org
file.
(eval-when-compile
(straight-use-package 'use-package)
(setq use-package-verbose t
use-package-always-defer t
use-package-hook-name-suffix nil
straight-use-package-by-default t
byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)))
;; general requires this bit otherwise everything blows up when native
;; compiling
(eval-and-compile
(straight-use-package 'general)
(require 'general))
also lets add a (require 'cl-lib)
for good measure
(eval-when-compile
(require 'cl-lib))
All these packages just help on the configuration of the rest of the other packages.
And we’ll use delight
to hide minor-modes names and such.
(use-package delight
:demand t
:commands delight
:delight
(auto-fill-function " af")
(eldoc-mode " ed")
(editorconfig-mode)
(visual-line-mode " vl")
(abbrev-mode))
Automatic hacks to the garbage collector settings
(use-package gcmh
:demand t
:straight (:type built-in)
:load-path (lambda () (expand-file-name "gcmh" vendor-user-dir))
:delight (gcmh-mode)
:config
(gcmh-mode 1))
no-littering
will help us by setting sane paths to all cache and history files
the packages might set.
(use-package no-littering
:demand t
:commands (no-littering-expand-var-file-name no-littering-expand-etc-file-name)
:config
(require 'no-littering)
(setq custom-file (no-littering-expand-var-file-name "custom.el")))
To facilitate my keybinding issues, I also use general.el
. It adds some very
welcome keywords to use-package
, in which I’ll use extensively throughout this
file.
(use-package general
:demand t
:commands (general-define-key general-def)
:preface
(defconst hcps/leader-key "C-c"
"Leader key for some personal commands.")
(defvar hcps/leader-map (make-sparse-keymap)
"Keymap for all my leader bindings.")
:init
(general-def
:keymaps 'override
hcps/leader-key '(:keymap hcps/leader-map :package general)
;; "C-c x" #'hcps/date-iso
"<f9>" #'hcps/get-selected-text
"M--" #'text-scale-decrease
"M-+" #'text-scale-increase
"M-K" #'hcps/move-line-up
"M-J" #'hcps/move-line-down
"<f12>" #'menu-bar-mode)
:config
;; leader-map keybindings
(general-def 'hcps/leader-map
"\\" #'indent-region
"e a" #'align-current
"e e" #'eval-region
;; cute names for the prefixes (some will only be defined further
;; along)
"g" '(:ignore t :wk "magit")
"f" '(:ignore t :wk "file")
"w" '(:ignore t :wk "window")
"n" '(:ignore t :wk "navigate")
"o" '(:ignore t :wk "org")
"m" '(:ignore t :wk "mode")
"v" '(:ignore t :wk "view")
"e" '(:ignore t :wk "edit")
"p" '(:ignore t :wk "project")
"l" '(:ignore t :wk "mail")
"m e" '(:ignore t :wk "eglot")))
Made by the doom-emacs guy. Yeah I know I could just write a function for this, but eh.
(use-package hide-mode-line
:commands hide-mode-line-mode)
Pretty little package that hides unnecessary hooks to set local variables
(use-package mode-local
:demand t
:straight (:type built-in))
Which stands for…
A Collection of Ridiculously Useful eXtensions for Emacs.
… yeah.
(use-package crux
:hook
(find-file-hook . crux-reopen-as-root)
:general
(:keymaps 'hcps/leader-map
;; file stuff
:prefix "f"
"s" #'crux-sudo-edit
"m" #'crux-rename-file-and-buffer ;; as in `move'
"d" #'crux-delete-file-and-buffer
"c" #'crux-find-user-custom-file
"n" #'crux-create-scratch-buffer
"i" #'crux-find-user-init-file
"o" #'crux-open-with)
(:keymaps 'hcps/leader-map
;; edit stuff
:prefix "e"
"E" #'crux-eval-and-replace))
hydra
is a package that allows keybindings to be activated under the pressing of
a specific combination of keys. These will then be active as long as only them
are being pressed, as on the moment a key which isn’t part of the hydra is
pressed the hydra is killed and the keybindings deactivated.
(use-package hydra
:commands defhydra
:custom
(hydra-default-hint nil))
(with-eval-after-load 'hydra
(defhydra hydra-eyebrowse (:color blue)
"
^Eyebrowse^ ^Do^ ^Switch^
^---------^---------^--^----------------^------^------------
_q_ quit _c_ create _<_ previous
^^ _k_ kill _>_ next
^^ _r_ rename _e_ last
^^ ^^ _s_ switch
^^ ^^ ^^
"
("q" nil)
("<" eyebrowse-prev-window-config :color red)
(">" eyebrowse-next-window-config :color red)
("c" eyebrowse-create-window-config)
("e" eyebrowse-last-window-config)
("k" eyebrowse-close-window-config :color red)
("r" eyebrowse-rename-window-config)
("s" eyebrowse-switch-to-window-config))
(with-eval-after-load 'general
(general-def '(global-map special-mode-map)
"C-c e" 'hydra-eyebrowse/body)))
(with-eval-after-load 'hydra
(defhydra hydra-flycheck (:color pink)
"
^
^Flycheck^ ^Errors^ ^Checker^
^────────^──────────^──────^────────────^───────^───────────
_q_ quit _<_ previous _?_ describe
_m_ manual _>_ next _d_ disable
_v_ verify setup _f_ check _s_ select
^^ _l_ list ^^
^^ ^^ ^^
"
("q" nil)
("<" flycheck-previous-error)
(">" flycheck-next-error)
("?" flycheck-describe-checker :color blue)
("d" flycheck-disable-checker :color blue)
("f" flycheck-buffer)
("l" flycheck-list-errors :color blue)
("m" flycheck-manual :color blue)
("s" flycheck-select-checker :color blue)
("v" flycheck-verify-setup :color blue))
(with-eval-after-load 'general
(general-def '(global-map special-mode-map)
"C-c f" 'hydra-flycheck/body)))
The one and only, for runtime use only!
(use-package use-package
:commands (use-package-core use-package))
The ones that really don’t require use-package :straight t
.
- [ ] bookmark
- [ ] dired
- [ ] hippie-expand
- [ ] eshell
- [ ] save-place
- [X] ibuffer
- [-] autoinsert
- [ ] org
- [X] shellscript
- [ ] elisp
- [X] c
- [X] makefile
- [X] electric-pairs
- [X] project
- [X] flymake
- [X] xref
Let’s monitor ourselves with whitespace
.
(use-package whitespace
:straight (:type built-in)
:commands (whitespace-mode whitespace-cleanup delete-trailing-whitespace)
:hook
(before-save-hook . whitespace-cleanup)
:custom
(whitespace-line-column nil)
(whitespace-style
'(face tabs indentation trailing lines-tail space-after-tab space-before-tab)))
I didn’t know this existed before like 5 seconds ago.
(use-package view
:demand t
:straight (:type built-in)
:custom
(view-read-only t)
:general
(:keymaps 'view-mode-map
"/" #'search-forward
"?" #'search-backward
"k" #'scroll-up
"j" #'scroll-down)
("C-v" #'View-scroll-half-page-forward
"M-v" #'View-scroll-half-page-backward))
This compilation helper mode facilitates the navigation of error outputs on compilations.
(use-package compile
:straight (:type built-in)
:commands compile-mode
:custom
(compilation-ask-about-save nil)
(compilation-always-kill t)
(compilation-scroll-output 'first-error)
(compilation-auto-jump-to-first-error t))
tramp
is very useful when it comes to editing remote files and to editing as
super-user.
(use-package tramp
:straight (:type built-in)
:custom
(tramp-default-method "ssh")
(tramp-terminal-type "xterm-mono"))
To have pretty colors on ansi output.
(use-package ansi-color
:straight (:type built-in)
:commands
(ansi-color-for-comint-mode-on ansi-color-filter-apply ansi-color-process-output)
:hook
((shell-mode-hook . ansi-color-for-comint-mode-on)
(eshell-preoutput-filter-functions . ansi-color-filter-apply)
(comint-output-filter-functions . ansi-color-process-output)))
A package that creates commands to move around windows.
(use-package windmove
:straight (:type built-in)
:general
(:keymaps 'override
"C-M-h" #'windmove-left
"C-M-l" #'windmove-right
"C-M-k" #'windmove-up
"C-M-j" #'windmove-down))
Originally, midnight
is used to run something at midnight. I use its feature
that kills old buffers.
(use-package midnight
:disabled
:defer 60
:straight (:type built-in)
:custom
(clean-buffer-list-delay-general (/ 1 12))
(clean-buffer-list-delay-special (* 1 3600))
(clean-buffer-list-kill-buffer-names
'("*Help*" "*Apropos*" "*Buffer List*" "*Compile-Log*" "*info*" "*vc*"
"*vc-diff*" "*diff*" "*IBuffer*" "*Finder*")))
uniquify
creates automatic meaningful names for buffers with the same name:
(use-package uniquify
:demand t
:straight (:type built-in)
:custom
(uniquify-buffer-name-style 'post-forward)
(uniquify-separator ":")
(uniquify-after-kill-buffer-p t)
(uniquify-ignore-buffers-re "^[*[:space:]]"))
Keep a list of recent files with recentf
(use-package recentf
:straight (:type built-in)
:commands recentf-open-files
:hook
(kill-emacs-hook . recentf-cleanup)
:custom
(recentf-save-file (expand-file-name "recentf-save.el" var-user-dir))
(recentf-max-menu-items 0)
(recentf-max-saved-items 300)
(recentf-exclude
(list
'file-remote-p
"\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\)$"
"^/tmp/"
"^/ssh:"
"\\.?ido\\.last$"
"\\.revive$"
"/TAGS$"
var-user-dir
package-user-dir
no-littering-var-directory
no-littering-etc-directory
(expand-file-name "savefile" user-emacs-directory)))
(recentf-auto-cleanup 'never)
:config
(recentf-mode 1))
Way better than the default one (and is built-in!)
(use-package ibuffer
:straight (:type built-in)
:general
(:keymaps 'ibuffer-mode-map
"q" #'kill-this-buffer)
(:keymaps 'hcps/leader-map
"B" #'ibuffer)
("C-x C-b" #'ibuffer))
To easily insert boilerplate text into files that need it, e.g. an org-mode beamer file, org-mode latex-file or a shell-script.
- https://emacs.stackexchange.com/questions/45629/template-for-new-file
- https://www.emacswiki.org/emacs/AutoInsertMode
- https://www.emacswiki.org/emacs/AutoInsertChoose
(use-package autoinsert
:straight (:type built-in)
:hook
(find-file-hook . auto-insert)
:custom
(auto-insert t)
(auto-insert-query nil)
(auto-insert-directory (expand-file-name "templates/" user-emacs-directory))
:config
(auto-insert-mode 1))
If this works, I’ll be very much pleasantly surprised.
(use-package comint
:straight (:type built-in)
:preface
(defun comint-fix-window-size ()
"Change process window size."
(when (derived-mode-p 'comint-mode)
(let ((process (get-buffer-process (current-buffer))))
(when process
(set-process-window-size process (window-height) 72)))))
:hook
((comint-exec-hook . comint-fix-window-size)
(comint-mode-hook . rainbow-delimiters-mode)))
Minor mode to highlight matching parenthesis after point.
(use-package paren
:demand t
:straight (:type built-in)
:commands show-paren-mode
:custom
(show-paren-delay 0)
(show-paren-style 'parenthesis)
:custom-face
(show-paren-match ((t (:inherit hl-line :foreground unspecified :background "#504945" :extend nil)))))
For pretty much every programming language it’s interesting to have automatic pair close insert.
(use-package elec-pair
:demand t
:straight (:type built-in)
:config
(electric-pair-mode 1))
Like the previous one but for indentation.
(use-package electric
:demand t
:straight (:type built-in)
:custom
(electric-indent-chars '(?\n ?}))
:config
(electric-indent-mode 1)
(electric-layout-mode 1))
(use-package xref
:straight (:type built-in)
:custom
(xref-search-program 'ripgrep)
(xref-show-xrefs-function #'consult-xref)
:general
(:keymaps 'hcps/leader-map
:prefix "m"
"d" #'xref-find-definitions
"r" #'xref-find-references
"a" #'xref-find-apropos))
Basic GUD
configuration as setup to gdb-mi
(use-package gud
:straight (:type built-in)
:custom
(gud-chdir-before-run nil))
An upgrade from GUD
, has more shiny stuff
(use-package gdb-mi
:straight (:type built-in)
:commands gdb
:custom
(gdb-many-windows t))
Built-in replacement for projectile
???
(use-package project
:straight (:type built-in)
:commands project-root
:custom
(project-vc-ignores '(".DS_Store"))
:general
(:keymaps 'hcps/leader-map
"p" '(:keymap project-prefix-map)))
No better place to put these, honestly
(use-package files
:demand t
:straight (:type built-in)
:hook
((focus-out-hook . do-auto-save)
(mouse-leave-buffer-hook . do-auto-save))
:custom
(auto-save-timeout 5)
(auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/") t))))
For dealing with merges in VCSs
(use-package smerge-mode
:straight (:type built-in)
:delight
(smerge-mode " sm")
:init
(with-eval-after-load 'hydra
(defhydra hydra-smerge (:color pink
:pre (smerge-mode 1))
"
^Movement^ ^Merge Action^ ^Other
^^^^^^------------------------------------------------
_n_: next hunk _b_: keep base _M_: makeup
_p_: prev hunk _m_: keep mine _r_: resolve
^ ^ _a_: keep all _R_: refine
^ ^ _o_: keep other _s_: swap
^ ^ _c_: keep current _q_: quit
^ ^ _C_: combine with next
^ ^ _e_: ediff
"
("n" smerge-next)
("p" smerge-prev)
("a" smerge-keep-all)
("b" smerge-keep-base)
("m" smerge-keep-upper)
("o" smerge-keep-lower)
("c" smerge-keep-current)
("C" smerge-combine-with-next)
("e" smerge-ediff :color blue)
("M" smerge-makeup-conflict)
("r" smerge-resolve)
("R" smerge-refine)
("s" smerge-swap)
("q" nil :color blue)))
:general
(:keymaps 'hcps/leader-map
:prefix "f e"
nil '(:ignore t :wk "smerge")
"h" #'hydra-smerge/body
"n" #'smerge-next
"p" #'smerge-prev
"r" #'smerge-resolve
"a" #'smerge-keep-all
"b" #'smerge-keep-base
"o" #'smerge-keep-lower ; for the obsolete keep-other
"l" #'smerge-keep-lower
"m" #'smerge-keep-upper ; for the obsolete keep-mine
"u" #'smerge-keep-upper
"E" #'smerge-ediff
"C" #'smerge-combine-with-next
"R" #'smerge-refine)
:config
(require 'hydra))
Default package for sending email, originally uses the homonymous Perl script,
now setup to use msmtp
(use-package sendmail
:straight (:type built-in)
:commands sendmail-send-it
:custom
(sendmail-program "/usr/bin/msmtp")
(send-mail-function #'sendmail-send-it)
(mail-specify-envelope-from t)
(message-sendmail-envelope-from 'header)
(mail-envelope-from 'header))
Built-in error checking and linting package.
(use-package flymake
:straight (:type built-in)
:commands (flymake-mode flymake-goto-next-error flymake-goto-prev-error)
:delight
(flymake-mode " fm" flymake)
:general
(:keymaps 'flymake-mode-map
"M-n" #'flymake-goto-next-error
"M-p" #'flymake-goto-prev-error))
Also lets add posframe
support to it
(use-package flymake-diagnostic-at-point
:after flymake
:commands (flymake-diagnostic-at-point-mode)
:straight
(flymake-diagnostic-at-point
:type git
:host github
:repo "waymondo/flymake-diagnostic-at-point")
:hook
(flymake-mode-hook . flymake-diagnostic-at-point-mode)
:custom
(flymake-diagnostic-at-point-display-diagnostic-function 'flymake-diagnostic-at-point-display-posframe)
(flymake-diagnostic-at-point-error-prefix "* ")
(flymake-diagnostic-at-point-timer-delay 1.5)
:custom-face
(flymake-diagnostic-at-point-posframe-background-face ((t (:inherit corfu-background :background unspecified))))
(flymake-diagnostic-at-point-posframe-border-face ((t (:inherit corfu-border :background unspecified)))))
Do things considering case in names
(use-package subword
:straight (:type built-in)
:commands (subword-mode global-subword-mode))
Some basic configuration for the Emacs file manager
(use-package dired
:demand t
:straight (:type built-in)
:custom
(dired-dwim-target t)
(dired-recursive-copies 'always))
The ones from MELPA and ELPA and whatever.
- [X] vterm
I use smart-mode-line
as it is very minimalist and informative (and it looks
very pretty on gruvbox
).
(use-package smart-mode-line
:disabled
:demand t
:init
(setq sml/use-projectile-p nil
sml/projectile-loaded-p nil
sml/projectile-replacement-format "")
:custom
(sml/size-indication-format " %I ")
(sml/line-number-format "%4l")
(sml/shorten-directory nil)
(sml/shorten-modes t)
(sml/mode-width 'full)
(sml/name-width 40)
(sml/theme 'respectful)
(sml/no-confirm-load-theme t)
(sml/replacer-regexp-list
`((,straight-user-dir ":STRAIGHT:")
(,user-emacs-directory ":ED:")
("^/sudo:.*:" ":SU:")
(,documents-user-dir ":DOC:")
(,proj-user-dir ":VCS:")
(,onedrive-user-dir ":OD:")))
:config
(sml/setup))
(use-package orderless
:demand t
:commands (orderless-filter orderless-highlight-matches)
:init
(setq-default completion-ignore-case t)
(setq-default completion-category-defaults nil)
:custom
(completion-styles '(orderless))
(completion-category-overrides '((eglot (styles . (orderless)))))
(orderless-matching-styles '(orderless-initialism orderless-regexp orderless-prefixes))
:custom-face
(orderless-match-face-0 ((t (:weight bold :foreground "#d75f5f"))))
(orderless-match-face-1 ((t (:weight bold :foreground "#ffaf00"))))
(orderless-match-face-2 ((t (:weight bold :foreground "#87afaf"))))
(orderless-match-face-3 ((t (:weight bold :foreground "#d787af"))))
:config
(savehist-mode 1))
Complete at point function wrappers for stuff that doesn’t have them. Useful in many senses.
(use-package cape
:demand t
:config
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-tex)
(add-to-list 'completion-at-point-functions #'cape-dabbrev t)
(add-to-list 'completion-at-point-functions #'cape-keyword))
Setting up vertico
, which is a completing-read system 100% based on Emacs
internals.
(use-package vertico
:after orderless
:demand t
:straight
(:files (:defaults "extensions/*")
:includes (vertico-buffer
vertico-directory
vertico-flat
vertico-indexed
vertico-mouse
vertico-quick
vertico-repeat
vertico-reverse))
:custom
(vertico-count 8)
(read-file-name-completion-ignore-case t)
(read-buffer-completion-ignore-case t)
:custom-face
(vertico-current ((t (:inherit hl-line :extend t))))
:general
(:keymaps 'vertico-map
"M-k" #'vertico-previous
"M-j" #'vertico-next
"C-f" #'vertico-exit-input
"C-u" #'vertico-scroll-down
"C-d" #'vertico-scroll-up)
:config
(vertico-mode 1))
Easier editing when dealing with filenames.
(use-package vertico-directory
:after vertico
:straight nil
:hook
(rfn-eshadow-update-overlay . vertico-directory-tidy)
:general
(:keymaps 'vertico-map
"TAB" #'vertico-directory-enter
"DEL" #'vertico-directory-delete-char
"M-DEL" #'vertico-directory-delete-word))
corfu.el
(Complete Overlay Region FUnction) is a pretty way to get in-buffer
completion and narrowing within a popup. Issue is, it doesn’t play along well
with LSP servers in general (at least with both lsp-mode
and eglot
). Really hope
that eventually changes in the future, ‘cause I like Corfu more than I like
company
.
(use-package corfu
:after orderless
:demand t
:commands (corfu-mode corfu-global-mode)
:preface
(defun corfu-enable-always-in-minibuffer ()
"Enable Corfu in the minibuffer if Vertico/Mct are not active."
(unless (or (bound-and-true-p mct--active)
(bound-and-true-p vertico--input))
(setq-local corfu-auto nil) ;; Enable/disable auto completion
(corfu-mode 1)))
:hook
(minibuffer-setup-hook . corfu-enable-always-in-minibuffer)
:custom
(corfu-auto nil)
(corfu-cycle t)
(corfu-quit-at-boundary nil)
(corfu-quit-no-match t)
(corfu-max-width 60)
(corfu-scroll-margin 5)
(corfu-echo-documentation nil)
:custom-face
(corfu-current ((t (:inherit hl-line :extend t))))
:general
(:keymaps 'corfu-map
"M-k" #'corfu-previous
"M-j" #'corfu-next
"SPC" #'corfu-insert-separator
[remap newline] #'corfu-insert)
:config
(global-corfu-mode 1))
Let’s also add corfu-doc
to display documentation in a meaningful way
(use-package corfu-doc
:after corfu
:straight
(corfu-doc
:type git
:host github
:repo "galeo/corfu-doc")
:hook
(corfu-mode-hook . corfu-doc-mode)
:custom
(corfu-doc-hide-threshold 1.0)
(corfu-doc-max-height 15)
(corfu-doc-delay 0.0)
:general
(:keymaps 'corfu-map
"M-d" #'corfu-doc-toggle))
Think of it as counsel
but without needing ivy
to work.
(use-package consult
:commands consult-xref
:custom
(consult-narrow-key "<")
(consult-project-root-function
(lambda ()
(when-let (project (project-current))
(car (project-roots project)))))
:general
(:keymaps 'hcps/leader-map
"f b" #'consult-bookmark
"f r" #'consult-recent-file
"e p" #'consult-yank-pop
"n l" #'consult-line
"n m" #'consult-mark
"n o" #'consult-outline
"n g" #'consult-ripgrep
"n G" #'consult-git-grep
"n e" #'consult-compile-error
"n f" #'consult-flycheck
"n j" #'consult-goto-line
"m f" #'consult-flymake)
("C-x b" #'consult-buffer
"C-h a" #'consult-apropos))
Adds information on some selection functions such as find-file
and others. Feels
good to use Emacs built-in function in a prettier way.
(use-package marginalia
:after vertico
:demand t
:custom
(marginalia-annotators
'(marginalia-annotators-heavy
marginalia-annotators-light
nil))
:general
(:keymaps 'minibuffer-local-map
"M-A" #'marginalia-cycle)
:config
(marginalia-mode 1))
Undo and redo and kools with undo-tree
!
(use-package undo-tree
:delight
:preface
(defconst hcps/undo-tree-visualizer-diff t
"My value for the `undo-tree-visualizer-diff' variable.")
(defun reset-visualizer-diff (&rest _)
"Because undo-tree-visualize sets the value of this variable to nil on quit."
(setq undo-tree-visualizer-diff hcps/undo-tree-visualizer-diff))
(defun wolfgang/clean-undo-tree ()
"Clear current buffer's undo-tree."
(interactive)
(let ((buff (current-buffer)))
(if (local-variable-p 'buffer-undo-tree)
(if (y-or-n-p "Clear buffer-undo-tree? ")
(progn
(setq buffer-undo-tree nil)
(message "Cleared undo-tree of buffer: %s" (buffer-name buff)))
(message "Cancelled clearing undo-tree of buffer: %s" (buffer-name buff)))
(error "Buffer %s has no local binding of `buffer-undo-tree'" (buffer-name buff)))))
:hook
((after-init-hook . global-undo-tree-mode)
(undo-tree-visualizer-mode-hook . hide-mode-line-mode))
:init
(advice-add #'undo-tree-visualize :before #'reset-visualizer-diff)
:custom
(undo-tree-visualizer-timestamps t)
(undo-tree-enable-undo-in-region t)
(undo-tree-auto-save-history nil)
(undo-tree-history-directory-alist `((".*" . ,temporary-file-directory)))
(undo-tree-visualizer-diff hcps/undo-tree-visualizer-diff)
:general
(:keymaps 'hcps/leader-map
"u" #'undo-tree-visualize
"U" #'wolfgang/clean-undo-tree))
There’s some utility in having a cool initial screen actually. And there’s a cool extension that provides such functionality.
(use-package dashboard
:functions dashboard-mode
:commands (dashboard-mode dashboard-insert-startupify-lists dashboard-refresh-buffer)
:init
(defun hcps/open-dashboard ()
(let ((buffer (switch-to-buffer "*dashboard*")))
(dashboard-mode)
buffer))
(setq-default initial-buffer-choice #'hcps/open-dashboard)
:custom
(dashboard-banner-logo-title (format "Welcome to Emacs, %s!" current-user))
(dashboard-set-heading-icons nil)
(dashboard-set-file-icons nil)
(dashboard-center-content t)
(dashboard-page-separator "\n\n\n")
(dashboard-startup-banner 'logo)
(dashboard-items '((recents . 10)
(bookmarks . 5)))
:general
(:keymaps 'dashboard-mode-map
"n" #'widget-forward
"p" #'widget-backward
"m" #'dashboard-jump-to-bookmarks
"r" #'dashboard-jump-to-recent-files)
:config
(setq-mode-local dashboard-mode scroll-margin 0)
(dashboard-setup-startup-hook))
While I’ve somewhat used neotree.el
, I believe that treemacs
is turning out to
be a better option, as it offers a bunch of extra integrating packages and is
overall more popular than the former.
(use-package treemacs
:commands treemacs-mode
:init
(advice-add #'treemacs-mode :around #'disable-scroll-margin)
:hook
(treemacs-mode-hook . hide-mode-line-mode)
:custom
(treemacs-persist-file (expand-file-name "treemacs/persist.org" var-user-dir))
(treemacs-display-in-side-window t)
(treemacs-follow-after-init t)
(treemacs-show-cursor nil)
(treemacs-no-png-images t)
(treemacs-project-follow-cleanup t)
(treemacs-sorting 'alphabetic-desc)
(treemacs-width 22)
:general
("M-0" #'treemacs-select-window
"M-t" #'treemacs)
:config
(treemacs-follow-mode 1)
(treemacs-filewatch-mode 1)
(treemacs-fringe-indicator-mode -1))
To ensure that Emacs uses the same path and environment as shell
uses, I use
exec-path-from-shell
. That way commands that work on the shell
will certainly
work on Emacs!
(use-package exec-path-from-shell
:straight
(exec-path-from-shell
:type git
:host github
:repo "purcell/exec-path-from-shell")
:init
(setenv "SHELL" "/bin/bash")
(setq-default shell-file-name "/bin/bash")
:custom
(exec-path-from-shell-shell-name "/bin/bash")
(exec-path-from-shell-arguments '("-l"))
(exec-path-from-shell-variables '("PATH" "MANPATH"))
:config
(exec-path-from-shell-initialize))
Besides the ISearch
from Emacs itself or the search function from evil
, I also
like to use anzu
.
(use-package anzu
:delight
(isearch-mode)
(anzu-mode)
:preface
(defun hcps/anzu-update-func (here total)
(when anzu--state
(let ((status (cl-case anzu--state
(search (format "(%d/%d) " here total))
(replace-query (format "(%d replaces) " total))
(replace (format "(%d/%d) " here total)))))
(propertize status 'face 'anzu-mode-line))))
:custom
(anzu-cons-mode-line-p t)
(anzu-mode-line-update-function #'hcps/anzu-update-func)
:general
(:keymaps 'hcps/leader-map
:prefix "e"
"r" #'anzu-query-replace-at-cursor-thing
"q" #'anzu-query-replace-regexp)
:config
(global-anzu-mode 1))
I use only the anzu-replace-at-cursor-thing
, which is a very useful to replace
multiple occurrences of a word fast.
I enjoy using ripgrep
to search for stuff using grep
syntax without the slowness
of it. So, I use deadgrep
!
(use-package deadgrep
:general
(:keymaps 'hcps/leader-map
:prefix "f"
"g" #'deadgrep))
link-hint
replicates the hinting mechanic from trydactil and such.
(use-package link-hint
:custom
(browse-url-browser-function 'browse-url-firefox)
:general
(:keymaps 'hcps/leader-map
"h" #'link-hint-open-link))
As I love some overkill, here’s avy
.
(use-package avy
:custom
(avy-styles-alist
'((avy-goto-char-2 . post)
(avy-goto-line . at-full)))
(avy-background t)
:general
("M-g f" #'avy-goto-line))
The package called which-key
shows you possible completions to the command
you’re typing in the mode-line.
(use-package which-key
:delight
:init
(hcps/hook-require-once pre-command-hook which-key)
:custom
(which-key-allow-evil-operators t)
:config
(which-key-mode 1))
Non-bloated lsp-mode
alternative. Always strive for leaner, simpler alternatives
(and try to contribute to them when possible).
(use-package eglot
:commands eglot-ensure
:hook
(eglot-managed-mode-hook . turn-on-eldoc-mode)
:init
(setq-default eglot-workspace-configuration
'((:diagnostics . ((:onChange . 5)))
(:completion . ((:filterAndSort . :json-false)))))
:custom
(eglot-autoreconnect t)
(eglot-autoshutdown t)
(eglot-extend-to-xref t)
(eglot-connect-timeout 60)
(eglot-send-changes-idle-time 0.10)
:general
(:keymaps 'hcps/leader-map
:prefix "m e"
"f" #'eglot-format
"r" #'eglot-rename
"a" #'eglot-code-actions
"d" #'eglot-find-declaration
"i" #'eglot-find-implementation
"C-r" #'eglot-reconnect
"C-s" #'eglot-shutdown
"C-a" #'eglot-shutdown-all)
:config
(add-to-list 'eglot-server-programs
'((perl-mode cperl-mode) . ("perl" "-MPerl::LanguageServer" "-e" "Perl::LanguageServer::run()")))
(push :documentHighlightProvider eglot-ignored-server-capabilities)
(require 'xref))
This highlights numbers in prog-mode
:
(use-package highlight-numbers
:commands highlight-numbers-mode)
And this is to highlight escape sequences in some common modes:
(use-package highlight-escape-sequences
:commands turn-on-hes-mode
:preface
(defconst hes-shell-escape-sequence-re "\\(\\\\\\([\"'?\\abfnrtv]\\)\\)"
"Simple regex to match any common escaped character in sh-mode")
:config
(add-to-list 'hes-mode-alist `(ggo-mode . ,hes-shell-escape-sequence-re))
(add-to-list 'hes-mode-alist `(shell-script-mode . ,hes-shell-escape-sequence-re)))
Of course, flyspell
corrects your writing!
(use-package wucuo
:commands (wucuo-start)
:delight
(wucuo-mode " fs")
(flyspell-mode " fs")
(flyspell-prog-mode " fs")
:custom
(ispell-program-name "aspell")
(ispell-extra-args '("--sug-mode=ultra" "--run-together" "--run-together-limit=16"))
(flyspell-issue-message-flag nil)
(flyspell-issue-welcome-flag nil)
:general
(:keymaps 'hcps/leader-map
"e d" #'ispell-change-dictionary)
:config
(add-to-list 'ispell-skip-region-alist '("^#+begin_src" . "^#+end_src")))
diff-hl
to highlight any diffs!
(use-package diff-hl
:commands (diff-hl-mode turn-on-diff-hl-mode diff-hl-magit-post-refresh))
ace-window
creates labels so we can jump windows with precision:
(use-package ace-window
:custom
(aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
:general
(:keymaps 'hcps/leader-map
"w o" #'ace-window))
super-save
auto-saves buffers when you switch or close buffers or when Emacs
loses focus, etc.
(use-package super-save
:disabled
:delight
:init
(hcps/hook-require-once before-save-hook super-save)
:custom
(super-save-auto-save-when-idle t)
(super-save-remote-files nil)
(super-save-idle-duration 60)
:config
(add-to-list 'super-save-triggers #'ace-window)
(super-save-mode 1))
I use yasnippet
to handle my snippet needs.
(use-package yasnippet
:disabled
:delight
(yas-minor-mode " ys")
:commands (yas-minor-mode yas-expand-snippet yas-lookup-snippet)
:preface
(defun hcps/get-pretty-source-path (path)
(replace-regexp-in-string
".*\\(?:src\\|source\\|include\\|inc\\)/\\(.+\\)$" "\\1"
path))
(defun hcps/get-pretty-include-guard (path)
(concat
"_"
(upcase (replace-regexp-in-string "[/.]" "_" (hcps/get-pretty-source-path path)))
"_"))
:init
(add-to-list 'hippie-expand-try-functions-list #'yas-hippie-try-expand)
:hook
(html-mode-hook . yas-minor-mode)
:custom
(yas-snippet-dirs `(,(expand-file-name "snippets" user-emacs-directory)))
:config
(general-def 'insert 'yas-minor-mode-map
"<tab>" yas-maybe-expand)
(yas-reload-all)
(yas-load-directory auto-insert-directory))
Enables vim-like folding of regions.
(use-package vimish-fold
:custom
(vimish-fold-header-width 79)
:general
(:keymaps 'vimish-fold-folded-keymap
"C-<tab>" #'vimish-fold-unfold)
(:keymaps 'vimish-fold-unfolded-keymap
"C-<tab>" #'vimish-fold-refold)
:config
(vimish-fold-global-mode 1))
Obviously, any configuration file that says it deserves any respect should
feature magit
, as it is, hands down, the best git
front-end in the visible
universe, nay, in the whole multiverse.
(use-package magit
:hook
((after-save-hook . magit-after-save-refresh-status)
(magit-file-mode-hook . diff-hl-mode)
(magit-post-refresh-hook . diff-hl-magit-post-refresh))
:preface
;; easy on-off for the following function
(defcustom magit-push-protected-branch nil
"When set, ask for confirmation before pushing to this branch (e.g. master)."
:type 'string
:safe #'stringp
:group 'magit)
;; are you sure you wanna push to master?
(defun magit-push--protected-branch (magit-push-fun &rest args)
"Ask for confirmation before pushing a protected branch."
(if (equal magit-push-protected-branch (magit-get-current-branch))
;; Arglist is (BRANCH TARGET ARGS)
(if (yes-or-no-p (format "Push branch %s? " (magit-get-current-branch)))
(apply magit-push-fun args)
(error "Push aborted by user"))
(apply magit-push-fun args)))
:init
(advice-add #'magit-push-current-to-pushremote
:around #'magit-push--protected-branch)
(advice-add #'magit-push-current-to-upstream
:around #'magit-push--protected-branch)
:custom
(git-commit-major-mode 'text-mode)
(magit-push-protected-branch "master")
(magit-save-repository-buffers 'dontask)
(magit-refs-show-commit-count 'all)
(magit-log-buffer-file-locked t)
(magit-revision-show-gravatars nil)
(magit-bury-buffer-function 'magit-mode-quit-window)
:general
(:keymaps 'hcps/leader-map
:prefix "g"
"p" #'magit-list-repositories
"g" #'magit-status
"d" #'magit-dispatch
"f" #'magit-file-dispatch
"l" #'magit-log
"b" #'magit-blame)
(:keymaps '(magit-log-mode-map magit-diff-mode-map magit-status-mode-map magit-mode-map magit-diff-section-base-map)
"j" #'magit-next-line
"k" #'magit-previous-line
"C-j" #'magit-section-forward
"C-k" #'magit-section-backward
"M-j" #'magit-section-forward-sibling
"M-k" #'magit-section-backward-sibling)
(:keymaps 'magit-status-mode-map
"h" #'magit-diff-toggle-refine-hunk
"l" #'magit-log
"J" #'magit-status-jump
"K" #'magit-discard)
:config
(transient-replace-suffix 'magit-dispatch #'magit-discard '("K" "Discard" magit-discard)))
Also, git-timemachine
is a beautiful way to walk through git history:
(use-package git-timemachine
:after magit
:hook
(git-timemachine-mode-hook . read-only-mode)
:general
(:keymaps 'git-timemachine-mode-map
"q" #'git-timemachine-quit
"w" #'git-timemachine-kill-abbreviated-revision
"g" #'git-timemachine-show-nth-revision
"c" #'git-timemachine-show-commit
"C-j" #'git-timemachine-show-next-revision
"C-k" #'git-timemachine-show-previous-revision)
(:keymaps 'hcps/leader-map
"g t" #'git-timemachine)
:config
(require 'magit))
Increase region by semantic units. It tries to be smart about it and adapt to the structure of the current major mode.
(use-package expand-region
:general
("C-+" #'er/contract-region
"C-=" #'er/expand-region))
When in need of smart pairing, look no further than smartparens
!
(use-package smartparens
:disabled
:delight (smartparens-mode " sp")
:commands (smartparens-mode smartparens-strict-mode)
:hook
(prog-mode-hook . smartparens-mode)
:custom
(sp-base-key-bindings 'paredit)
(sp-autoskip-closing-pair 'always)
(sp-hybrid-kill-entire-symbol nil)
:config
(require 'smartparens-config)
(sp-use-paredit-bindings)
(show-smartparens-global-mode 1))
With that, rainbow-delimiters
is a great match:
(use-package rainbow-delimiters
:commands rainbow-delimiters-mode)
This little add-on will highlight big cursor movements.
(use-package beacon
:init
(hcps/hook-require-once pre-command-hook beacon)
:delight
:config
(beacon-mode 1))
I use aggressive-indent
to keep my code indented as I type.
(use-package aggressive-indent
:commands aggressive-indent-mode
:custom
(aggressive-indent-comments-too t)
(aggressive-indent-sit-for-time 0.05)
:config
(add-to-list 'aggressive-indent-protected-commands 'undo-tree-visualize-undo)
(add-to-list 'aggressive-indent-protected-commands 'undo-tree-visualize-redo)
(add-to-list 'aggressive-indent-protected-commands 'comment-dwim))
Also highligh-indent-guides
is very useful, as Emacs doesn’t come with it out of
the box.
(use-package highlight-indent-guides
:delight
(highlight-indent-guides-mode)
:commands
(highlight-indent-guides-auto-set-faces highlight-indent-guides-mode)
:preface
(defun highlight-indent-guides-auto-set-faces-with-frame (frame)
(with-selected-frame frame
(highlight-indent-guides-auto-set-faces)))
:hook
(highlight-indent-guides-mode-hook . highlight-indent-guides-auto-set-faces)
:custom
(highlight-indent-guides-method 'character)
(highlight-indent-guides-responsive 'stack)
(highlight-indent-guides-character ?|)
(highlight-indent-guides-delay 0.05)
(highlight-indent-guides-auto-odd-face-perc 5)
(highlight-indent-guides-auto-even-face-perc 5)
(highlight-indent-guides-auto-character-face-perc 10))
helpful
is a package that is overall an improvement over the default help
windows.
(use-package helpful
:general
(:keymaps 'override
:prefix "C-h"
"F" #'helpful-function
"C" #'helpful-command
"M" #'helpful-macro)
(:keymaps 'override
[remap describe-key] #'helpful-key
[remap describe-variable] #'helpful-variable
[remap describe-function] #'helpful-callable))
openwith
is a small and useful tool to set how you want to open your files with
Emacs. I use it to set the opener of pdfs in my Emacs, as well to other diverse
media files.
(use-package openwith
:init
(hcps/hook-require-once pre-command-hook openwith)
:custom
(openwith-associations
'(("\\.pdf\\'" "xdg-open" (file))
;; ("\\.jpe?g\\'" "sxiv" (file))
;; ("\\.png\\'" "sxiv" (file))
;; ("\\.svg\\'" "sxiv" (file))
;; ("\\.jpeg\\'" "sxiv" (file))
;; ("\\.bmp\\'" "sxiv" (file))
("\\.flac\\'" "mpv" (file))
("\\.mkv\\'" "mpv" (file))
("\\.mp3\\'" "mpv" (file))
("\\.mp4\\'" "mpv" (file))))
(openwith-confirm-invocation t)
:config
(openwith-mode 1))
To make pretty page breaks in your Emacs buffers:
(use-package page-break-lines
:commands (page-break-lines-mode)
:delight
:custom
(page-break-lines-max-width (floor (/ fill-column 2)))
(page-break-lines-char ?-)
:custom-face
(page-break-lines ((t :inherit font-lock-comment-face :bold nil :italic nil))))
A nice writing environment for Emacs in a minor-mode.
(use-package writeroom-mode
:straight t
:straight visual-fill-column
:custom
(writeroom-fullscreen-effect 'maximized)
(writeroom-width (+ 3 fill-column))
:general
(:keymaps 'hcps/leader-map
"v w" #'writeroom-mode))
Here’s a small package that allows remotely opening sessions.
(use-package ssh
:after shell
:preface
(defcustom ssh-remote-user-server nil
"Dummy variable that holds a server name."
:type 'string
:safe #'stringp
:group 'ssh)
(defun hcps/get-user-server ()
"Call to set and print the user server."
(interactive)
(if (equal ssh-remote-user-server nil)
(setq ssh-remote-user-server
(read-from-minibuffer "What server to store: ")))
(concat "/ssh:" ssh-remote-user-server ":"))
(defun hcps/store-user-remote ()
"Store a server name to the desired target."
(interactive)
(let* ((read-server (read-from-minibuffer
(format "What server to store (current: %s): " ssh-remote-user-server)))
(server-to-connect (if (equal read-server "") ssh-remote-user-server read-server)))
(setq ssh-remote-user-server server-to-connect)))
:custom
(shell-command-dont-erase-buffer t)
(ssh-directory-tracking-mode t)
:config
(shell-dirtrack-mode t))
Obscure but nice way to enable ligature fonts.
(use-package ligature
:disabled
:demand t
:straight
(ligature
:type git
:host github
:repo "mickeynp/ligature.el")
:config
(ligature-set-ligatures 't '("www"))
;; enable Iosevka ligatures in programming modes
(ligature-set-ligatures
'prog-mode
'("<---" "<--" "<<-" "<-" "->" "-->" "--->" "<->" "<-->"
"<--->" "<---->" "<!--" "<==" "<===" "<=" "=>" "=>>" "==>"
"===>" ">=" "<=>" "<==>" "<===>" "<====>" "<!---" "<~~"
"<~" "~>" "~~>" "::" ":::" "==" "!=" "===" "!==" ":=" ":-"
":+" "<*" "<*>" "*>" "<|" "<|>" "|>" "+:" "-:" "=:"
"<******>" "++" "+++"))
(global-ligature-mode 1))
So we don’t trouble ourselves with setting which fonts should be fixed and which should be variable.
(use-package mixed-pitch
:disabled
:commands (mixed-pitch-mode)
:delight
(mixed-pitch-mode " mp")
:custom-face
(variable-pitch ((t (:font "Iosevka Aile" :weight light)))))
Pretty TODO
highlighting :)
(use-package hl-todo
:commands (hl-todo-mode))
Trying out and hopefully will switch to in in a few languages.
(use-package tree-sitter
:straight t
:straight tree-sitter-langs
:commands (tree-sitter-mode global-tree-sitter-mode)
:delight (tree-sitter-mode " ts")
:hook
(tree-sitter-mode-hook . tree-sitter-hl-mode)
:custom-face
(tree-sitter-hl-face:function.call ((t (:foreground "#8ec07c"))))
(tree-sitter-hl-face:method.call ((t (:foreground "#8ec07c"))))
(tree-sitter-hl-face:label ((t (:inherit font-lock-builtin-face :slant italic))))
:config
(require 'tree-sitter-langs))
Supposedly this works better than smartparens
when using Evil keybindings.
Hopefully this is the case, ‘cause I don’t really use smartparens
keybindings
the way (nor the frequency) I should be.
(use-package lispy
:commands (lispy-mode)
:delight (lispy-mode " lp"))
Finally, adding this amazing package
(use-package embark
:general
(:keymaps 'override
"M-SPC" #'embark-act
"M-S-SPC" #'embark-dwim))
To provide live preview of embark
actions.
(use-package embark-consult
:after (embark consult)
:demand t
:hook
(embark-collect-mode-hook . consult-preview-at-point-mode))
notmuch
interface for Emacs!
(use-package notmuch
:commands (notmuch-hello notmuch-show notmuch-tree notmuch-search)
:custom
(notmuch-search-oldest-first nil)
(notmuch-saved-searches
'((:name "inbox" :query "tag:inbox" :key "i")
(:name "unread" :query "tag:unread" :key "u")
(:name "graduacao" :query "tag:graduacao" :key "g")
(:name "cadeiras" :query "tag:cadeira" :key "c")
(:name "sent" :query "tag:sent" :key "t")
(:name "all mail" :query "*" :key "a")))
:general
(:keymaps 'hcps/leader-map
:prefix "l"
"h" #'notmuch-hello
"s" #'notmuch-search
"t" #'notmuch-tree
"w" #'notmuch-show
"n" #'notmuch-poll))
A tiny package that modernizes the tempo
built-in template package!
(use-package tempel
:commands (tempel-expand tempel-complete tempel-insert)
:preface
(defconst hcps/tempel-snippets-dir (expand-file-name "snippets" user-emacs-directory))
(defun tempel-setup-capf ()
;; Add the Tempel Capf to `completion-at-point-functions'. `tempel-expand'
;; only triggers on exact matches. Alternatively use `tempel-complete' if
;; you want to see all matches, but then Tempel will probably trigger too
;; often when you don't expect it.
;; NOTE: We add `tempel-expand' *before* the main programming mode Capf,
;; such that it will be tried first.
(setq-local completion-at-point-functions
(cons #'tempel-expand
completion-at-point-functions)))
:custom
(tempel-path (mapcar (lambda (f) (expand-file-name f hcps/tempel-snippets-dir))
'("prog-mode" "lisp-mode" "text-mode" "org-mode")))
(tempel-trigger-prefix "<")
:general
(:keymaps 'tempel-map
"M-n" #'tempel-next
"M-p" #'tempel-previous
[remap keyboard-quit] #'tempel-abort))
Add commands to magit
that interact with git
forges!
(use-package forge
:disabled
:after magit)
Soft parenthesis handling!
(use-package puni
:demand
:commands (puni-disable-puni-mode puni-mode)
:hook
(eval-expression-minibuffer-setup-hook . puni-mode))
info-colors
makes the info node buffers a little bit more readable.
(use-package info-colors
:straight
(info-colors
:type git
:host github
:repo "ubolonton/info-colors")
:hook
(Info-selection-hook . info-colors-fontify-node))
Here I define the theme that I use, which is gruvbox
, as it provides nice
support for a lot of packages and is very pleasant for the eyes.
- [ ] Use this.
(use-package gruvbox-theme
:demand t
:config
(load-theme 'gruvbox-dark-medium t))
Here I’ll store any package load and configurations related to languages and file types.
I still need to add packages relating to these languages:
- [ ] Scala
- [X] Dot (using Graphviz)
- [ ] English (as in literal english)
- [ ] Coq (yes, I’m slowly turning into what I most hate (check the hrs config!))
- [X] PKGBUILD
- [X] Markdown
- [X] Clojure
- [X]
prog-mode
- [X]
text-mode
- [X]
bison-mode
- [X] Typescript
- [ ] Scheme and Geiser
This mode gets derived by all programming modes.
(use-package prog-mode
:straight (:type built-in)
:preface
(defun setup-hyphen-word-component ()
(modify-category-entry ?- ?u))
:hook
((prog-mode-hook . rainbow-delimiters-mode)
(prog-mode-hook . subword-mode)
(prog-mode-hook . eldoc-mode)
(prog-mode-hook . puni-mode)
(prog-mode-hook . hl-todo-mode)
(prog-mode-hook . page-break-lines-mode)
(prog-mode-hook . highlight-indent-guides-mode)
(prog-mode-hook . tempel-setup-capf)
(prog-mode-hook . turn-on-hes-mode)
(prog-mode-hook . flymake-mode)
(prog-mode-hook . highlight-numbers-mode)
(prog-mode-hook . show-paren-mode)
(prog-mode-hook . whitespace-mode)
(prog-mode-hook . display-line-numbers-mode)))
Sane basic configurations to text-mode
.
(use-package text-mode
:straight (:type built-in)
:hook
((text-mode-hook . whitespace-mode)
(text-mode-hook . page-break-lines-mode)
(text-mode-hook . auto-fill-mode)
(text-mode-hook . wucuo-start)
(text-mode-hook . tempel-setup-capf)
(text-mode-hook . (lambda () (ansi-color-apply-on-region (point-min) (point-max) t)))))
org-mode
is probably the killer mode and one of the main reasons as to why
anyone should try Emacs.
Important links:
- https://sachachua.com/blog/2015/02/learn-take-notes-efficiently-org-mode/
- https://doc.norang.ca/org-mode.html#AgendaSetup
- https://joshrollinswrites.com/help-desk-head-desk/2020-07-16/
- https://blog.jethro.dev/posts/capturing_inbox/
(use-package org
:mode ("\\.org\\'" . org-mode)
:straight t
:straight org-contrib
:delight
(org-indent-mode nil org-indent)
:preface
(defconst org-electric-pairs '((?/ . ?/) (?= . ?=) (?~ . ?~)))
(defun org-mode-insert-zero-width-space ()
(interactive)
(insert "\u200B"))
:hook
((org-mode-hook . hes-mode)
(org-mode-hook . eldoc-mode)
(org-mode-hook . (lambda () (whitespace-toggle-options 'lines-tail))))
:custom
(org-return-follows-link t)
;; the following used to be '(latex script entities)
(org-highlight-latex-and-related nil)
(org-hide-leading-stars t)
(org-hide-emphasis-markers t)
(org-support-shift-select nil)
(org-link-descriptive t)
(org-log-done 'note)
(org-directory (if (file-directory-p onedrive-user-dir)
(expand-file-name "org" onedrive-user-dir)
documents-user-dir))
(org-cycle-emulate-tab t)
(org-use-property-inheritance nil)
(org-startup-indented t)
(org-startup-folded t)
(org-use-speed-commands t)
(org-outline-path-complete-in-steps nil)
(org-fontify-done-headline t)
(org-fontify-todo-headline t)
(org-catch-invisible-edits 'smart)
;; 10 pixels because default-font-width doesn't work with daemon mode
(org-image-actual-width (round (* 10 fill-column 0.85)))
(org-display-remote-inline-images 'download)
(org-modules
'(ol-w3m ;; this comment is here for identation purposes
ol-bbdb ol-bibtex ol-docview ol-gnus ol-info ol-irc ol-mhe
ol-rmail ol-eww org-tempo org-inlinetask org-indent))
;; logging stuff
(org-tag-alist
'(("noexport" . ?e)
("ignore" . ?i)
("TOC" . ?t)
("DEPRECATED" . ?d)
("NOTE" . ?n)
("WIP" . ?g)
("PERSONAL" . ?p)
("MEETING" . ?m)
("REFILE" . ?f)
("REPEAT" . ?r)
("UNI" . ?u)
("WORK" . ?w)
("URGENT" . ?a)))
(org-todo-keywords '((sequence "TODO(t)" "STARTED(s!)" "|" "DONE(d!)")
(sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)")))
(org-log-into-drawer t)
;; (org-effort-property "EFFORT")
(org-global-properties
'(("EFFORT_ALL" . "0 1 2 3 4 5 6 7 8 9 10")))
:general
(:keymaps 'org-mode-map
:prefix hcps/leader-key
"v n s" #'org-narrow-to-subtree
"v n b" #'org-narrow-to-block
"m i" '(:ignore t :wk "insert")
"m i d" #'org-insert-drawer
"m i t" #'org-insert-time-stamp
"m i l" #'org-insert-link
"m t" #'org-set-tags-command
"m f" #'org-set-effort
"m d" #'org-deadline
"m h" #'org-schedule
"m o" #'org-priority
"m p" #'org-set-property
"m s" #'org-match-sparse-tree
"m t" #'org-todo ; mark a TODO item as DONE
"m h" #'org-do-promote
"m l" #'org-do-demote
"m <tab>" #'outline-toggle-children)
(:keymaps 'org-mode-map
"H-n" #'outline-next-visible-heading
"H-p" #'outline-previous-visible-heading
"H-u" #'outline-up-heading
"H-i" #'org-toggle-inline-images
"H-<" #'org-promote-subtree
"H->" #'org-demote-subtree
"H-SPC" #'org-mode-insert-zero-width-space
"H-TAB" #'outline-toggle-children)
(:keymaps 'hcps/leader-map
"o b" #'org-switchb)
:config
(setq org-effort-property "EFFORT")
(setq-mode-local org-mode electric-pair-inhibit-predicate (lambda (c) (if (char-equal c ?<) t (electric-pair-default-inhibit c))))
(setq-mode-local org-mode electric-pair-pairs (append electric-pair-pairs org-electric-pairs)))
Stuff that increases the capabilities of org-mode
With it I also use toc-org
, which is an useful way to automatically
maintain an updated table of contents of your .org
file. Check it out!
(use-package toc-org
:hook
(org-mode-hook . toc-org-mode)
:custom
(toc-org-max-depth 3)
(toc-org-hrefify-default "org"))
Makes the emphasis markers magically show up when you hover those words!
(use-package org-appear
:hook
(org-mode-hook . org-appear-mode))
org-ref is the de-facto way to cite inside Emacs, as it supports multiple export backends and such
(use-package org-ref
:disabled
:preface
(defconst hcps/user-org-ref-path
(expand-file-name "Documentos/Papers" onedrive-user-dir))
:custom
(org-ref-bibliography-notes (expand-file-name "notes.org" hcps/user-org-ref-path))
(org-ref-default-bibliography `(,(expand-file-name "references.bib" hcps/user-org-ref-path)))
(reftex-default-bibliography `(,(expand-file-name "references.bib" hcps/user-org-ref-path)))
(org-ref-pdf-directory hcps/user-org-ref-path)
(org-ref-completion-library 'org-ref-ivy-cite)
(org-ref-insert-cite-function 'org-ref-ivy-insert-cite-link)
(org-ref-insert-label-function 'org-ref-ivy-insert-label-link)
(org-ref-insert-ref-function 'org-ref-ivy-insert-ref-link)
(org-ref-show-broken-links nil)
:general
(:keymaps 'org-mode-map
:prefix hcps/leader-key
:non-normal-prefix hcps/alt-leader-key
"m c" #'org-ref-cite-hydra/body)
:config
(require 'doi-utils))
The ultimate journaling tool of the ultimate note-taking tool.
(use-package org-agenda
:straight (:type built-in)
:preface
(defun hcps/open-agenda ()
"Opens my custom org-agenda command."
(interactive)
(org-agenda nil " "))
(defun hcps/goto-inbox ()
"Open the organizer file."
(interactive)
(find-file (expand-file-name "organizer.org" org-directory)))
:custom
(org-columns-default-format
"%20CATEGORY(FILE) %35ITEM(TASK) %PRIORITY(P) %EFFORT(E) %DEADLINE(D) %TAGS(T)")
(org-agenda-files
(append (directory-files-recursively (expand-file-name "org" onedrive-user-dir) "\\.org\\'")
(directory-files-recursively proj-user-dir "^hcps[[:alnum:]-]*\\.org\\'")))
(org-agenda-start-with-log-mode t)
(org-agenda-use-tag-inheritance t)
(org-agenda-block-separator nil)
(org-agenda-view-columns-initially t)
(org-agenda-skip-deadline-if-done t)
(org-agenda-skip-scheduled-if-done t)
(org-agenda-log-mode-items '(clock closed))
(org-agenda-custom-commands
`((" " "Agenda"
((agenda ""
((org-agenda-span 'week)
(org-deadline-warning-days 0)))
(todo "STARTED"
((org-agenda-overriding-header "IN PROGRESS")
(org-agenda-block-separator ?-)))
(tags "URGENT"
((org-agenda-overriding-header "URGENT TASKS")))
(tags "UNI"
((org-agenda-overriding-header "UNI STUFF")))
(todo "TODO"
((org-agenda-overriding-header "PROJECTS")
(org-agenda-files ',(directory-files-recursively proj-user-dir "^hcps[[:alnum:]-]*\\.org\\'"))))
(tags "REFILE"
((org-agenda-overriding-header "TO REFILE")
(org-agenda-files '(,(expand-file-name "org/organizer.org" onedrive-user-dir)))))))))
:general
(:keymaps 'hcps/leader-map
"o a" #'hcps/open-agenda
"o i" #'hcps/goto-inbox))
org-journal
is a powerful tool to journal your day.
(use-package org-journal
:custom
(org-journal-dir (format-time-string (expand-file-name "org/journal/%Y" onedrive-user-dir)))
(org-journal-file-type 'monthly)
(org-journal-file-format "%Y%m")
(org-journal-date-format "%e %b %Y (%A)")
(org-journal-time-format "")
:general
(:keymaps 'hcps/leader-map
"o j" #'org-journal-new-entry))
It is built-in and it is beautiful.
(use-package org-capture
:straight (:type built-in)
:commands (org-capture-mode org-capture-upgrade-templates)
:preface
(defconst org-main-notes-file (expand-file-name "org/organizer.org" onedrive-user-dir)
"File that I use to store notes before reviewing them.")
:custom
(org-default-notes-file org-main-notes-file)
(org-capture-templates
`(("t" "todo" entry (file+headline ,org-main-notes-file "Inbox")
"* TODO %? :REFILE:\nDEADLINE: %^T\n%U\n"
:empty-lines 1 :kill-buffer t)
("n" "note" entry (file+headline ,org-main-notes-file "Inbox")
"* %? :NOTE:REFILE:\n%U\n"
:empty-lines 1 :kill-buffer t)
("m" "meeting" entry (file+headline ,org-main-notes-file "Inbox")
"* %? :MEETING:REFILE:\nSCHEDULED: %^{Meeting date?}T\n%U\n"
:empty-lines 1 :kill-buffer t)))
:general
(:keymaps 'hcps/leader-map
"o c" #'org-capture))
Apparently this doesn’t get loaded with org
by default?
(use-package org-id
:after org
:straight (:type built-in)
:custom
(org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
(org-id-locations-file-relative t))
Configurations related to this feature in specific
(use-package org-attach
:after org
:straight (:type built-in)
:custom
(org-attach-use-inheritance 'selective)
(org-attach-dir-relative t)
(org-attach-id-dir "attach/")
(org-attach-id-to-path-function-list
'(org-attach-id-ts-folder-format org-attach-id-uuid-folder-format))
(org-attach-preferred-new-method 'id)
:general
(:keymaps 'org-mode-map
:prefix hcps/leader-key
"m a" #'org-attach))
As of Org 9.4, there is a org-refile.el
!
(use-package org-refile
:after org
:straight (:type built-in)
:custom
(org-refile-use-outline-path 'file)
(org-refile-allow-creating-parent-nodes 'confirm)
(org-refile-targets '((org-agenda-files :maxlevel . 1)))
:general
(:keymaps 'org-mode-map
:prefix hcps/leader-key
"m r" #'org-refile))
To see inline pdf images! Amazing right?
(use-package org-inline-pdf
:after org
:hook
(org-mode-hook . org-inline-pdf-mode))
Adds bars to visualize the indentation provided by the built-in org-indent
(use-package org-bars
:straight
(org-bars
:type git
:host github
:repo "tonyaldon/org-bars")
:hook
(org-mode-hook . org-bars-mode)
:config
(setq org-bars-stars '(:empty "*" :invisible "*" :visible "*")
org-bars-color-options '(:desaturate-level-faces 15
:darken-level-faces 30)
org-bars-extra-pixels-height 0))
Configurations relating all the numerous org exporters.
(use-package ox
:after org
:straight (:type built-in)
:straight htmlize
:preface
(defconst org-export-default-output-folder "build"
"Defines the default export folder for `ox' and friends.")
(defun org-export-output-file-name-modified (orig-fun extension &optional subtreep pub-dir)
"Collect all generated files from an export in a neat folder."
(unless pub-dir
(setq pub-dir org-export-default-output-folder)
(unless (file-directory-p pub-dir)
(make-directory pub-dir)))
(apply orig-fun extension subtreep pub-dir nil))
(defun org-export-remove-zero-width-space (text &rest _)
(unless (org-export-derived-backend-p 'org)
(replace-regexp-in-string "\u200B" "" text)))
:init
(advice-add #'org-export-output-file-name
:around #'org-export-output-file-name-modified)
(advice-add #'org-export-dispatch
:around #'disable-scroll-margin)
:custom
(org-export-backends '(latex html ascii))
(org-export-exclude-tags '("noexport" "NOEXPORT"))
(org-export-allow-bind-keywords t)
(org-export-headline-levels 5)
(org-export-creator-string
(format "Emacs %s (Org mode %s–%s)" emacs-version (org-release) (org-git-version)))
(org-export-with-sub-superscripts '{})
(org-export-with-latex t)
(org-export-babel-evaluate t)
(org-export-in-background t)
(org-export-snippet-translation-alist
'(("b" . "beamer")
("l" . "latex")
("h" . "html")
("o" . "odt")))
:general
(:keymaps 'org-mode-map
:prefix hcps/leader-key
"m e" #'org-export-dispatch)
:config
(add-to-list 'org-export-filter-final-output-functions
#'org-export-remove-zero-width-space t))
ox-extra
defines a couple of cool extras, like ignore-headlines
!
(use-package ox-extra
:after (ox org-contrib)
:straight (:type built-in)
:hook
((org-export-filter-parse-tree-functions . org-export-ignore-headlines)
(org-export-before-parsing-hook . org-latex-header-blocks-filter)))
Configurations to the LaTeX org exporter.
(use-package ox-latex
:after ox
:straight (:type built-in)
:custom
(org-latex-image-default-width "1\\linewidth")
(org-latex-packages-alist
`((,(concat "cache=false,outputdir=" org-export-default-output-folder) "minted")
("T1" "fontenc")
("" "placeins")))
(org-latex-listings 'minted)
(org-latex-minted-options
'(("breaklines")
("breakafter" "d")
("linenos" "true")
("xleftmargin" "\\parindent")))
(org-latex-pdf-process
'("latexmk -pdfxelatex='xelatex -shell-escape -interaction=nonstopmode' -f -xelatex -outdir=%o %f"))
:config
(add-to-list 'org-latex-classes
'("iiufrgs"
"\\documentclass{iiufrgs}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")))
(add-to-list 'org-latex-classes
'("newlfm"
"\\documentclass{newlfm}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))
(add-to-list 'org-latex-classes
'("IEEEtran"
"\\documentclass{IEEEtran}"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))
To the oh-so-pretty Hugo markdown format!
(use-package ox-hugo
:after ox
:demand t)
Twitter bootstrap htmls!
(use-package ox-twbs
:after ox
:demand t)
Yeah. That’s right.
I mean, it’s basically a tool to interface with the D&D LaTeX class. Not that nerdy, is it?
(use-package ox-dnd
:after ox
:straight (:type built-in)
:load-path (lambda () (expand-file-name "emacs-org-dnd" vendor-user-dir)))
To export pretty slide presentations
(use-package ox-beamer
:after ox
:straight (:type built-in)
:delight
(org-beamer-mode nil)
:custom
(org-beamer-environments-extra
'(("onlyenv" "O" "\\begin{onlyenv}%a" "\\end{onlyenv}")
("minipage" "m" "\\begin{minipage}[%R]{%O}" "\\end{minipage}%")))
:general
(:keymaps 'org-beamer-mode-map
:prefix hcps/leader-key
"m b" '(:ignore t :wk "beamer")
"m b e" #'org-beamer-select-environment
"m b p" #'org-beamer-export-to-pdf))
Now, some configurations relating org-babel and its magic source blocks.
(use-package ob
:after org
:straight (:type built-in)
:delight
(org-src-mode)
:preface
(defun org-babel-tangle-block ()
(interactive)
(let ((current-prefix-arg '(4)))
(call-interactively #'org-babel-tangle)))
(defun org-babel-strip-ansi-codes (func &rest args)
(let ((result (apply func args)))
(unless (null result)
(replace-regexp-in-string ansi-color-control-seq-regexp "" result))))
(defun org-babel-region-strip-ansi-codes (func beg &rest args)
"Remove all ansi-color codes from point (the end of the region) to `beg'."
(while (re-search-forward ansi-color-control-seq-regexp beg t -1)
(replace-match "" nil nil))
(apply func beg args))
:hook
(org-babel-after-execute-hook . org-remove-inline-images)
:init
(advice-add #'org-trim :around #'org-babel-strip-ansi-codes)
(advice-add #'org-no-properties :around #'org-babel-strip-ansi-codes)
(advice-add #'org-element-normalize-string :around #'org-babel-strip-ansi-codes)
(advice-add #'org-babel-examplify-region :around #'org-babel-region-strip-ansi-codes)
(advice-add #'org-string-nw-p :around #'org-babel-strip-ansi-codes)
(advice-add #'org-element-interpret-data :around #'org-babel-strip-ansi-codes)
:custom
(org-edit-src-content-indentation 0)
(org-edit-src-persistent-message nil)
(org-src-preserve-indentation t)
(org-src-fontify-natively t)
(org-src-tab-acts-natively t)
(org-src-window-setup 'other-window)
(org-babel-default-header-args
'((:session . "none")
(:results . "value replace")
(:exports . "code")
(:cache . "none")
(:noweb . "no")
(:async . "yes")
(:eval . "never-export")
(:hlines . "no")
(:tangle . "no")))
(org-babel-load-languages
'((emacs-lisp . t)
(shell . t)
(python . t)
(julia . t)
(makefile . t)
(R . t)
(C . t)
(ruby . t)
(ditaa . t)
(dot . t)
(octave . t)
(sqlite . t)
(perl . t)
(screen . t)
(plantuml . t)
(lilypond . t)
(latex . t)))
:general
(:keymaps 'org-mode-map
:prefix hcps/leader-key
"m x" #'org-babel-execute-buffer
"m z" #'org-babel-tangle-block
"m Z" #'org-babel-tangle)
(:keymaps 'org-mode-map
"C-c SPC" #'org-edit-special)
(:keymaps 'org-src-mode-map
"C-c SPC" #'org-edit-src-exit)
:config
;; set correct modes for some languages
(setf (alist-get "dot" org-src-lang-modes) 'graphviz-dot
(alist-get "latex" org-src-lang-modes) 'TeX-latex))
As a great way to run Python and Julia source blocks inside org-mode
(use-package jupyter
:after ob
:straight t
:straight zmq
:straight websocket
:commands jupyter-org-interaction-mode
:custom
(org-babel-default-header-args:jupyter-julia
'((:eval . "no-export")
(:async . "yes")
(:session . "*Julia*")
(:results . "value")
(:exports . "both")
(:kernel . "julia-1.4")))
(org-babel-default-header-args:jupyter-python
'((:eval . "no-export")
(:async . "yes")
(:session . "*Python*")
(:results . "value")
(:exports . "both")
(:kernel . "python3"))))
Basic configuration about org-babel
for R
(use-package ob-R
:after ob
:straight (:type built-in)
:custom
(org-babel-default-header-args:R
'((:exports . "both"))))
Here I set some defaults I appreciate for cc-mode
(the builtin mode for all
c-like languages):
(use-package cc-mode
:straight (:type built-in)
:commands (c-mode awk-mode java-mode c++-mode)
:mode
(("\\.c\\'" . c-mode)
("\\.h\\'" . c-mode)
("\\.C\\'" . c++-mode)
("\\.H\\'" . c++-mode)
("\\.c\\+\\+\\'" . c++-mode)
("\\.h\\+\\+\\'" . c++-mode)
("\\.cpp\\'" . c++-mode)
("\\.hpp\\'" . c++-mode)
("\\.awk\\'" . awk-mode)
("\\.java\\'" . java-mode))
:preface
(defun c-indent-for-tab-command ()
(interactive)
(let ((p (point)))
(c-indent-line-or-region)
(when (= p (point))
(call-interactively #'complete-symbol))))
:hook
(((c-mode-hook c++-mode-hook java-mode-hook) . eglot-ensure)
((c-mode-hook c++-mode-hook java-mode-hook) . tree-sitter-mode))
:custom
(c-default-style
'((java-mode . "java")
(awk-mode . "awk")
(other . "linux")))
(c-doc-comment-style
'((java-mode . javadoc)
(pike-mode . autodoc)
(c-mode . doxygen)
(c++-mode . doxygen)))
(c-basic-offset 4)
:general
(:keymaps 'c-mode-base-map
"TAB" #'c-indent-for-tab-command))
As languages that are part of cc-mode
are known to using a lot of
doxygen, here’s a package that highlights it!
(use-package highlight-doxygen
:disabled
:hook
(c-mode-common-hook . highlight-doxygen-mode)
:custom-face
(highlight-doxygen-comment ((t :inherit font-lock-doc-face :background "#363230" :extend t)))
(highlight-doxygen-code-block ((t :background "#363230" :extend t))))
Better C++ font lock
(use-package modern-cpp-font-lock
:delight
(modern-c++-font-lock-mode)
:hook
(c++-mode-hook . modern-c++-font-lock-mode))
And better pre-processor highlighting
(use-package preproc-font-lock
:commands (preproc-font-lock-mode preproc-font-lock-global-mode)
:hook
((c-mode-hook c++-mode-hook) . preproc-font-lock-mode)
:custom-face
(preproc-font-lock-preprocessor-background ((t :background "#302c2b"))))
In the department of code formatting, clang-format
is a lovely tool
that can really be of great use while editing C and C++ code.
(use-package clang-format
:preface
(defun cc-format-on-save-hook ()
(when c-buffer-is-cc-mode
(clang-format-buffer)))
:custom
(clang-format-fallback-style "webkit")
:general
(:keymaps 'c-mode-base-map
:prefix hcps/leader-key
"m f" #'clang-format-region))
Suporting CUDA syntax per-se is kinda easy, as it’s a subset of C after all. The
thing is I want proper syntax highlighting for all those special keywords and
types that CUDA introduces. So, let’s install cuda-mode
:
(use-package cuda-mode
:straight
(cuda-mode
:type git
:host github
:repo "hcpsilva/cuda-mode")
:mode "\\.cu\\'"
:custom
(cuda-font-lock-keywords 'cuda-font-lock-keywords-3))
It falls back on c++-mode
by default, so we are safe here.
For R you pretty much need the ess
package, i.e. Emacs Speaks
Statistics. It provides you with everything you need from R.
(use-package ess-r-mode
:straight ess
:commands (R R-mode r-mode ess-r-mode ess-r-transcript-mode)
:preface
(defun hcps/insert-r-pipe ()
"Lets us insert the magrittr piping operator in R"
(interactive)
(just-one-space 1)
(insert "%>%")
(reindent-then-newline-and-indent))
:hook
((ess-r-mode-hook . aggressive-indent-mode)
;; (ess-r-mode-hook . tree-sitter-mode)
(inferior-ess-mode-hook . comint-fix-window-size))
:custom
(ido-enable-flex-matching t)
(ess-gen-proc-buffer-name-function #'ess-gen-proc-buffer-name:simple)
(ess-auto-width fill-column)
(ess-style 'RStudio)
:general
(:keymaps 'ess-r-mode-map
"M-RET" #'hcps/insert-r-pipe
"<tab>" #'ess-indent-or-complete)
(:keymaps 'ess-r-mode-map
:prefix hcps/leader-key
"m c" #'ess-eval-region-or-function-or-paragraph-and-step
"m r" #'ess-eval-region
"m e" #'Rd-mode-insert-skeleton
"m f" #'Rd-font
"m j" #'Rd-mode-insert-item
"m n" #'ess-eval-line-visibly-and-step
"m p" #'Rd-preview-help
"m s" #'Rd-mode-insert-section
"m v" #'ess-display-help-on-object
"m w" #'ess-switch-process
"m y" #'ess-switch-to-ESS
"m z" #'ess-switch-to-end-of-ESS))
As for shell-scripting:
(use-package sh-script
:straight (:type built-in)
:commands (shell-script-mode sh-mode)
:mode
(("\\.zsh\\'" . shell-script-mode)
("PKGBUILD\\'" . shell-script-mode))
:preface
(defconst prezto-files
'(".zlogin" ".zlogin" ".zlogout" ".zpreztorc" ".zprofile" ".zshenv" ".zshrc")
"Files that are too zsh-style files.")
(defun zsh-prezto-files ()
"Function to ease switching to zsh when dealing with a zsh file."
(if (and buffer-file-name
(member (file-name-nondirectory buffer-file-name) prezto-files))
(sh-set-shell "zsh")))
:hook
((sh-mode-hook . zsh-prezto-files)
(sh-mode-hook . tree-sitter-mode)
(sh-mode-hook . sh-electric-here-document-mode))
:general
(:keymaps 'sh-mode-map
:prefix hcps/leader-key
"m s" #'sh-set-shell
"m i c" #'sh-case
"m i f" #'sh-for
"m i i" #'sh-if
"m i s" #'sh-select
"m i w" #'sh-while
"m i o" #'sh-while-getopts
"m i u" #'sh-until
"m i F" #'sh-function
"m i I" #'sh-indexed-loop))
For shell
completion I use bash-complete
, which auto completes several
bash
functions.
(use-package bash-completion
:hook
(shell-dynamic-complete-functions . bash-completion-dynamic-complete)
:custom
(bash-completion-use-separate-processes t))
In Makefile files we have a special case: it needs tabulators to work. So, we’ll set that up.
(use-package make-mode
:straight (:type built-in)
:commands makefile-mode
:mode ("^[Mm]akefile\\'" . makefile-mode)
:config
(setq-mode-local makefile-mode indent-tabs-mode t))
PlantUML is a graph language that describes loads of different diagram types, mainly focusing on UML, of course.
(use-package plantuml-mode
:mode "\\.plantuml\\'"
:interpreter "plantuml")
Fix for the annoying keyword default indentation:
(defun fuco1/lisp-indent-function (indent-point state)
"This function is the normal value of the variable `lisp-indent-function'.
The function `calculate-lisp-indent' calls this to determine if
the arguments of a Lisp function call should be indented
specially. INDENT-POINT is the position at which the line being
indented begins. Point is located at the point to indent
under (for default indentation); STATE is the
`parse-partial-sexp' state for that position. If the current line
is in a call to a Lisp function that has a non-nil property
`lisp-indent-function' (or the deprecated `lisp-indent-hook'), it
specifies how to indent. The property value can be:
* `defun', meaning indent `defun'-style
(this is also the case if there is no property and the function
has a name that begins with \"def\", and three or more arguments);
* an integer N, meaning indent the first N arguments specially
(like ordinary function arguments), and then indent any further
arguments like a body;
* a function to call that returns the indentation (or nil).
`lisp-indent-function' calls this function with the same two arguments
that it itself received.
This function returns either the indentation to use, or nil if the
Lisp function does not specify a special indentation."
(let ((normal-indent (current-column))
(orig-point (point)))
(goto-char (1+ (elt state 1)))
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
(cond
;; car of form doesn't seem to be a symbol, or is a keyword
((and (elt state 2)
(or (not (looking-at "\\sw\\|\\s_"))
(looking-at ":")))
(if (not (> (save-excursion (forward-line 1) (point))
calculate-lisp-indent-last-sexp))
(progn (goto-char calculate-lisp-indent-last-sexp)
(beginning-of-line)
(parse-partial-sexp (point)
calculate-lisp-indent-last-sexp 0 t)))
;; Indent under the list or under the first sexp on the same
;; line as calculate-lisp-indent-last-sexp. Note that first
;; thing on that line has to be complete sexp since we are
;; inside the innermost containing sexp.
(backward-prefix-chars)
(current-column))
((and (save-excursion
(goto-char indent-point)
(skip-syntax-forward " ")
(not (looking-at ":")))
(save-excursion
(goto-char orig-point)
(looking-at ":")))
(save-excursion
(goto-char (+ 2 (elt state 1)))
(current-column)))
(t
(let ((function (buffer-substring (point)
(progn (forward-sexp 1) (point))))
method)
(setq method (or (function-get (intern-soft function)
'lisp-indent-function)
(get (intern-soft function) 'lisp-indent-hook)))
(cond ((or (eq method 'defun)
(and (null method)
(> (length function) 3)
(string-match "\\`def" function)))
(lisp-indent-defform state indent-point))
((integerp method)
(lisp-indent-specform method state
indent-point normal-indent))
(method
(funcall method indent-point state))))))))
also extra magic font lock for Lisp and Scheme
(use-package lisp-extra-font-lock
:commands (lisp-extra-font-lock-mode lisp-extra-font-lock-global-mode))
Finally, the mode’s final configuration
(use-package lisp-mode
:straight (:type built-in)
:mode
(("\\.lsp\\'" . lisp-mode)
("\\.lisp\\'" . lisp-mode)
("\\.cl\\'" . lisp-mode))
:hook
((lisp-mode-hook . aggressive-indent-mode)
(lisp-mode-hook . puni-disable-puni-mode)
(lisp-mode-hook . lispy-mode)
(lisp-mode-hook . lisp-extra-font-lock-mode))
:custom
(lisp-indent-function #'fuco1/lisp-indent-function))
Emacs version!
(use-package elisp-mode
:straight (:type built-in)
:straight elisp-slime-nav
:commands emacs-lisp-mode
:mode ("\\.el\\'" . emacs-lisp-mode)
:preface
(defun recompile-elc-on-save ()
"Recompile your elc when saving an elisp file."
(when (and (string-prefix-p user-emacs-directory (file-truename buffer-file-name))
(file-exists-p (byte-compile-dest-file buffer-file-name)))
(emacs-lisp-byte-compile)))
:hook
((after-save-hook . recompile-elc-on-save)
(emacs-lisp-mode-hook . (lambda () (run-hooks 'lisp-mode-hook))))
:config
(require 'use-package))
Start by adding pyenv.el
to deal with virtual environments
(use-package pyenv
:commands (pyenv-activate pyenv-workon))
and auto-virtualenv
(use-package auto-virtualenv
:after pyenv
:commands auto-virtualenv-set-virtualenv)
Finally, a simple yet effective Python configuration.
(use-package python
:straight (:type built-in)
:commands python-mode
:hook
((python-mode-hook . tree-sitter-mode)
(python-mode-hook . eglot-ensure)
(python-mode-hook . auto-virtualenv-set-virtualenv))
:custom
(python-flymake-command '("flake8" "-")))
As CMake is very simple, each word carries a load of meaning and importance. This little mode colors them accordingly.
(use-package cmake-mode
:mode
(("^CMakeLists\\.txt\\'" . cmake-mode)
("\\.cmake\\'" . cmake-mode)))
Also add extra colors
(use-package cmake-font-lock
:after cmake-mode
:demand t
:hook
(cmake-mode-hook . cmake-font-lock-activate))
dockerfile-mode
adds support to syntax highlighting and to build the
image directly from the buffer using C-c C-b
.
(use-package dockerfile-mode
:mode "[Dd]ockerfile\\'"
:hook
(dockerfile-mode-hook . puni-mode))
So I have syntax highlighting while editing GLPK files.
(use-package gmpl-mode
:mode "\\.mod\\'"
:hook
(gmpl-mode-hook . puni-mode))
Packages to write Julia source code in Emacs.
(use-package julia-mode
:mode "\\.jl\\'"
:preface
(defun hcps/insert-julia-pipe ()
"Lets us insert the piping operator |> in Julia"
(interactive)
(just-one-space 1)
(insert "|>")
(reindent-then-newline-and-indent))
:init
(setq inferior-julia-program (hcps/s-trim-right (shell-command-to-string "which julia")))
(defvaralias 'inferior-julia-program-name 'inferior-julia-program
"Because jupyter still uses this symbol.")
(advice-add #'julia :around (lambda (func &rest args) (set-buffer (apply func args))))
:hook
((julia-mode-hook . tree-sitter-mode)
(julia-mode-hook . aggressive-indent-mode))
:general
(:keymaps 'julia-mode-map
"M-RET" #'hcps/insert-julia-pipe))
- [ ] Interesting link
Let’s start with some basic AUCTeX
configuration
(use-package tex
:straight auctex
:commands (tex-mode plain-tex-mode texinfo-mode latex-mode doctex-mode TeX-tex-mode)
:mode ("\\.tex\\'" . TeX-latex-mode)
:hook
(((LaTeX-mode-hook TeX-mode-hook) . auto-fill-mode)
((LaTeX-mode-hook TeX-mode-hook) . puni-mode)
((LaTeX-mode-hook TeX-mode-hook) . rainbow-delimiters-mode))
:init
(setq reftex-plug-into-AUCTeX t)
:custom
(TeX-auto-save t)
(TeX-master nil)
(TeX-engine 'xetex)
(TeX-parse-self t)
(TeX-save-query nil)
(TeX-source-correlate-method 'synctex)
(TeX-output-dir "build")
(TeX-view-program-selection
'(((output-dvi has-no-display-manager) "dvi2tty")
((output-dvi style-pstricks) "dvips and gv")
(output-dvi "xdvi")
(output-pdf "xdg-open")
(output-html "xdg-open")))
:general
(:keymaps 'LaTeX-mode-map
:prefix hcps/leader-key
"m e" #'LaTeX-environment
"m s" #'LaTeX-section
"m m" #'TeX-insert-macro))
And RefTeX
to follow it
(use-package reftex
:straight (:type built-in)
:delight (reftex-mode " ref")
:commands (reftex-mode turn-on-reftex)
:hook
(LaTeX-mode-hook . turn-on-reftex)
:custom
(reftex-bibliography-commands '("bibliography" "nobibliography" "addbibresource"))
:general
(:keymaps 'LaTeX-mode-map
:prefix hcps/leader-key
"m b" #'reftex-label
"m r" #'reftex-reference
"m c" #'reftex-citation
"m t" #'reftex-toc
"m i" #'reftex-index))
So, for my LaTeX config I’ll mainly use latexmk
as it’s way simpler to
use.
(use-package auctex-latexmk
:straight
(auctex-latexmk
:type git
:host github
:repo "wang1zhen/auctex-latexmk")
:after tex
:demand t
:config
(auctex-latexmk-setup))
With latexmk
I do also use its configuration file in ~/.latexmkrc
, so
some important stuff may be defined there.
Syntax support for the Meson build system DSL (which is based from Python).
(use-package meson-mode
:commands meson
:mode "^meson\\.build\\'")
Mode recently made by a cool person online. Replaces the old and strange configuration I had before.
(use-package sxhkd-mode
:straight
(sxhkd-mode
:type git
:host github
:repo "xFA25E/sxhkd-mode")
:mode "sxhkdrc\\'"
:hook
(sxhkd-mode-hook . (lambda () (run-hooks 'conf-mode-hook))))
Just a little hook to start the desired conf-mode
when we open these
files.
(use-package conf-mode
:straight (:type built-in)
:mode
(("\\.service\\'" . conf-mode)
("\\.conf\\'" . conf-mode))
:hook
(conf-mode-hook . (lambda () (run-hooks 'prog-mode-hook))))
The newest greatest compiled language!
(use-package rust-mode
:straight t
:straight cargo
:hook
((rust-mode-hook . eglot-ensure)
(rust-mode-hook . cargo-minor-mode)))
Old language, still great for doing admin stuff in few lines.
(use-package cperl-mode
:straight (:type built-in)
:mode "\\.p[lm]\\'"
:interpreter "perl"
:commands cperl-mode
:preface
(defalias #'perl-mode #'cperl-mode "CPerl has better handling and utilities.")
:hook
(cperl-mode-hook . eglot-ensure)
:custom
(cperl-font-lock t)
(cperl-info-on-command-no-prompt t)
(cperl-clobber-lisp-bindings nil)
(cperl-indent-level 4)
:custom-face
(cperl-nonoverridable-face ((t (:inherit font-lock-builtin-face :foreground unspecified))))
;; (cperl-array-face ((t nil)))
;; (cperl-hash-face ((t nil)))
:general
(:keymaps 'cperl-mode-map
:prefix hcps/leader-key
"i" #'cperl-indent-region)
:config
(font-lock-add-keywords
'cperl-mode
'(("^#!\\/\\(?:\\w+\\/\\)*\\(\\w+\\)"
(1 'font-lock-keyword-face prepend))
("\\(\\\\\\)\\(&\\)\\([[:alnum:]_:]+\\)"
(1 'font-lock-builtin-face)
(2 'font-lock-type-face)
(3 'font-lock-function-name-face))
("\\(\\$\\)\\([[:digit:]_`]\\)[^[:alnum:]_:]"
(1 'font-lock-type-face prepend)
(2 'font-lock-builtin-face prepend))
("\\(?:^\\|[^[:alnum:]_:\\\\]\\)\\([&$*@%]+\\)\\([[:alnum:]_:]+\\)"
(1 'font-lock-type-face append)
(2 'font-lock-variable-name-face append))))
;; (font-lock-remove-keywords
;; 'cperl-mode
;; '(("\\(\\([$@%]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)" 1
;; (if (= (- (match-end 2) (match-beginning 2)) 1)
;; (if (eq (char-after (match-beginning 3)) ?{)
;; 'cperl-hash-face
;; 'cperl-array-face)
;; font-lock-variable-name-face)
;; t)
;; ("\\(\\([@%]\\|\\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
;; (if (eq (char-after (match-beginning 2)) ?%)
;; 'cperl-hash-face
;; 'cperl-array-face)
;; nil)
;; ("\\(@\\|\\$#\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
;; (1 'cperl-array-face)
;; (2 font-lock-variable-name-face))
;; ("\\(%\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
;; (1 'cperl-hash-face)
;; (2 font-lock-variable-name-face))
;; ("\\([$*]{?\\(?:\\sw+\\|::\\)+\\)" 1
;; font-lock-variable-name-face)))
)
Diagrams are cool
(use-package graphviz-dot-mode
:mode
(("\\.gv\\'" . graphviz-dot-mode)
("\\.dot\\'" . graphviz-dot-mode))
:commands (graphviz-dot-mode)
:hook
((graphviz-dot-mode-hook . aggressive-indent-mode)
(graphviz-dot-mode-hook . puni-mode))
:custom
(graphviz-dot-indent-width 4)
:general
(:keymaps 'graphviz-dot-mode-map
:prefix hcps/leader-key
"m f" #'graphviz-dot-indent-graph
"m p" #'graphviz-dot-preview))
For lexer shenanigans
(use-package bison
:straight (:type built-in)
:commands bison-mode
:load-path (lambda () (expand-file-name "bison-mode" vendor-user-dir))
:mode
(("\\.y\\'" . bison-mode)
;; ("\\.l\\'" . flex-mode)
;; ("\\.jison\\'" . jison-mode)
)
;; :custom
;; (bison-all-electricity-off t)
;; (bison-rule-separator-column 0)
;; (bison-rule-enumeration-column 0)
;; (bison-decl-type-column 0)
;; (bison-decl-token-column 0)
)
Ugh another mode that insists in putting bigger fonts everywhere…
(use-package markdown-mode
:mode "\\.md\\'"
:commands (markdown-mode gfm-mode)
:preface
(defconst markdown-electric-pairs '((?_ . ?_) (?* . ?*) (?` . ?`)))
:hook
((markdown-mode-hook . auto-fill-mode)
(markdown-mode-hook . puni-mode)
(markdown-mode-hook . hes-mode)
(markdown-mode-hook . eldoc-mode)
(markdown-mode-hook . (lambda () (whitespace-toggle-options 'lines-tail))))
:custom
(markdown-hr-display-char ?-)
(markdown-hide-markup nil)
:custom-face
(markdown-line-break-face ((t (:inherit unspecified :underline unspecified))))
(markdown-header-face ((t (:height 1.0))))
:config
(setq-mode-local markdown-mode electric-pair-pairs (append electric-pair-pairs
markdown-electric-pairs))
(dolist (num (number-sequence 1 6))
(custom-set-faces `(,(intern (format "markdown-header-face-%d" num)) ((t (:height 1.0))))))
(font-lock-remove-keywords
'markdown-mode
`((,markdown-regex-line-break
1 'markdown-line-break-face prepend))))
So I can write a decent Tree Sitter grammar.
(use-package js
:mode "\\.jsx?\\'"
:straight (:type built-in)
:commands (js-mode)
:hook
((js-mode-hook . tree-sitter-mode)
(js-mode-hook . aggressive-indent-mode)))
Here we’ll not be using js-mode
! Instead, we’ll be using
typescript-mode
with Tree Sitter atop it!
(use-package typescript-mode
:mode "\\.tsx?\\'"
:hook
(typescript-mode-hook . (lambda () (run-hooks 'js-mode-hook))))
Fucking finally
(use-package clojure-mode
:mode
(("\\.\\(clj\\|dtm\\|edn\\)\\'" . clojure-mode)
("\\.cljc\\'" . clojurec-mode)
("\\.cljs\\'" . clojurescript-mode))
:hook
((clojure-mode-hook . aggressive-indent-mode)
(clojure-mode-hook . puni-disable-puni-mode)
(clojure-mode-hook . eglot-ensure)
(clojure-mode-hook . lispy-mode))
:config
(define-clojure-indent
(defroutes 'defun)
(GET 2)
(POST 2)
(PUT 2)
(DELETE 2)
(HEAD 2)
(ANY 2)
(OPTIONS 2)
(PATCH 2)
(rfn 2)
(let-routes 1)
(context 2)))
also add extra font-locking to the mode
(use-package clojure-mode-extra-font-locking
:demand t
:after clojure-mode)
also configure CIDER
(use-package cider
:after clojure-mode
:custom
(cider-allow-jack-in-without-project t)
:general
(:keymaps 'clojure-mode-map
:prefix hcps/leader-key
"m i" #'cider-jack-in))
and clj-refactor
(use-package clj-refactor
:after clojure-mode
:hook
(clojure-mode-hook . clj-refactor-mode))
and inf-clojure
(inferior repl buffer for Clojure)
(use-package inf-clojure
:after clojure-mode
:general
(:keymaps 'clojure-mode-map
:prefix hcps/leader-key
"m R" #'inf-clojure)
:config
(setf (alist-get 'joker inf-clojure-startup-forms) "joker --no-readline"))
Yes! I’ve came full circle and now I love Lisp/Scheme, what the heck.
(use-package racket-mode
:mode "\\.rkt?\\'"
:hook
((racket-mode-hook . (lambda () (run-hooks 'lisp-mode-hook)))
(racket-mode-hook . racket-xp-mode)
(racket-repl-mode-hook . (lambda () (run-hooks 'lisp-mode-hook))))
:custom
(racket-memory-limit 4096)
(racket-show-functions '(racket-show-echo-area))
:custom-face
(racket-selfeval-face ((t (:inherit font-lock-constant-face :foreground unspecified))))
:general
(:keymaps 'racket-mode-map
:prefix hcps/leader-key
"m x" #'racket-run-and-switch-to-repl
"m l" #'racket-insert-lambda))
Yet Another Markup Language
(use-package yaml-mode
:mode
(("\\.yaml\\'" . yaml-mode)
("\\.yml\\'" . yaml-mode))
:hook
(yaml-mode-hook . puni-mode))
gengetopt
files!
(use-package ggo-mode
:straight
(ggo-mode
:type git
:host github
:repo "mkjunker/ggo-mode")
:mode "\\.ggo\\'"
:hook
(ggo-mode-hook . (lambda () (run-hooks 'prog-mode-hook))))
Like configuration files, only, I don’t know, different?
(use-package git-modes
:mode
(("\\.gitconfig\\'" . gitconfig-mode)
("\\.git/config\\'" . gitconfig-mode)
("modules/.*/config\\'" . gitconfig-mode)
("git/config\\'" . gitconfig-mode)
("\\.gitmodules\\'" . gitconfig-mode)
("/etc/gitconfig\\'" . gitconfig-mode)
("\\.gitignore\\'" . gitignore-mode)
("info/exclude\\'" . gitignore-mode)
("git/ignore\\'" . gitignore-mode)
("\\.gitattributes\\'" . gitattributes-mode)
("info/attributes\\'" . gitattributes-mode)
("git/attributes\\'" . gitattributes-mode)))
The Go programming language!
(use-package go-mode
:mode "\\.go\\'"
:hook
((go-mode-hook . eglot-ensure)
(go-mode-hook . tree-sitter-mode)))
And its weird HCL markup language
(use-package hcl-mode
:mode "\\.hcl\\'")
(use-package terraform-mode
:after hcl-mode
:mode "\\.tf\\(vars\\)?\\'")
Yeah I have no comments for this one
(use-package vimrc-mode
:mode "\\.vim\\(rc\\)?\\'")
Brazilian export!
(use-package lua-mode
:mode "\\.lua\\'"
:interpreter "lua")