§ Bootstrapping use-package
Modern emacs
is best configured - if not used from frameworks like
doom/ or spacemacs - declaratively with use-package/ macro.
;;; Declarative setup with `use-package'. (require 'package) (setq package-archives `(,@package-archives ("melpa" . "https://melpa.org/packages/") ("org" . "https://orgmode.org/elpa/"))) (package-initialize) ;; probably, to enable the autoloads... (setq package-enable-at-startup nil) ;; explicit default signature checking policy (setq package-check-signature 'allow-unsigned) ;; init 'use-package (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (eval-when-compile (require 'use-package)) (put 'use-package 'lisp-indent-function 1) (setq use-package-always-ensure t) (setq use-package-verbose t) (setq use-package-minimum-reported-time 0.01) ;; :diminish keyword (use-package diminish) ;; :bind keyword (use-package bind-key) ;; :quelpa keyword (use-package quelpa) (use-package quelpa-use-package :config (setq use-package-ensure-function 'quelpa))
§ System Packages
Those well detect guix
as a package manager.
(use-package system-packages ; :custom (system-packages-noconfirm t)) (use-package use-package-ensure-system-package)
§ Custom Variables Used in Configurations
The concrete definitions of the following vars are private and not exported. Anyways, here's their meanings:
my-init/grimoire-dir
points to the location of Grimoire - my universal entry-point for Org-mode stuff synchronized across machines.my-init/org-roam-dir
stands for the root of Org-Roam-ed files.my-init/org-download-dir
is the location of files downloaded directly into Org.my-init/org-agenda-file
is the general Org Agenda taskdumpsterdrawer.my-init/org-backlog-file
is the list of media sources to pay attention sometime.my-init/worklog-path
is a relative path to the work-related Org-Roam daily directories.my-init/org-remark-notes-file
denotes a file to store Org-Remarks.
§ Emacs core package setup
This is self-explanatory, mostly. The locale is set to default system locale.
Encoding is of course utf-8
. UI set to visual minimalism, with close to perfect
modus-themes
. Version control will be dispatched to magit
, therefore the
built-in one is off. File autosaves stored under separate distinct paths.
Access to lisp
local source files and rust
custom dynamic modules also
wired here. I might reorganize the form when have more clear view on how to
package my own stuff.
(use-package emacs :ensure nil :init (setq flycheck-disabled-checkers '(emacs-lisp-checkdoc)) (setq system-time-locale "C") (set-default 'truncate-lines t) (set-scroll-bar-mode 'nil) ;;; Path to Guix-installed packages (add-to-list 'load-path "~/.guix-profile/share/emacs/site-lisp") ;;; I also need to get all the MELPA-installed packages on (let ((default-directory "~/.emacs.d/elpa/")) (normal-top-level-add-subdirs-to-load-path)) (guix-emacs-autoload-packages) (add-to-list 'load-path (format "%s/.guix-profile/share/emacs/site-lisp" (getenv "HOME"))) ;; Emails: Mu4e from GUIX (put 'narrow-to-region 'disabled nil) (put 'downcase-region 'disabled nil) (set-face-attribute 'default nil :height 140 :family "Iosevka Extended") (set-face-attribute 'fixed-pitch nil :family "Iosevka Extended") (set-face-attribute 'variable-pitch nil :family "Iosevka Extended") ;; Agda-mode set manually: ;; (load-file (let ((coding-system-for-read 'utf-8)) ;; (shell-command-to-string "agda-mode locate"))) (let ((default-directory "~/.emacs.d/lisp-dev/")) (normal-top-level-add-subdirs-to-load-path)) ;; For Rust dynamic modules. ;; https://github.com/ubolonton/emacs-module-rs/tree/master/rs-module ;;NOTE: Subject to many possible changes/reorganizations. (add-to-list 'load-path (file-truename "~/.emacs.d/dynmods")) (when (file-exists-p (file-truename "~/.emacs.d/dynmods/rs_module.so")) (module-load (file-truename "~/.emacs.d/dynmods/rs_module.so")) (defun load-rs-module (mod-name) (rs-module/load (file-truename (format "~/.emacs.d/dynmods/%s.so" mod-name))))) :custom ;; I know I won't overload myself with warnings UNLESS I need them: (warning-minimum-level :emergency) (scroll-step 1) (inhibit-startup-screen t "Don't show splash screen") (use-dialog-box nil "Disable dialog boxes") (enable-recursive-minibuffers t "Allow minibuffer commands in the minibuffer") (indent-tabs-mode nil "Spaces!") (delete-old-versions -1) (version-control nil) (auto-save-default nil) (auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t))) (ring-bell-function 'ignore) (coding-system-for-read 'utf-8) (coding-system-for-write 'utf-8) (sentence-end-double-space nil) (default-fill-column 80) (initial-scratch-message ";; -*- lexical-binding: t -*-\n;;; Good morning, Captain!\n\n") (debug-on-quit nil) (column-number-mode 1) (reb-re-syntax 'string))
§ Appearance
Temporarily (?) external instructions for appearance:
no blinking cursor;
no visible menus;
modus themes (prefer built-in);
85% transparency level;
custom cursor color (overriden by theme).
(blink-cursor-mode 0) (menu-bar-mode -1) (tool-bar-mode -1) (require-theme 'modus-themes) (load-theme 'modus-vivendi t) (set-frame-parameter (selected-frame) 'alpha '(85 . 50)) (add-to-list 'default-frame-alist '(alpha . (85 . 50))) ;; (setq default-frame-alist ;; (append default-frame-alist ;; '((cursor-color . "MediumSlateBlue"))))
§ File backups and saving options
E.g. if a newline in the end of the file is mandatory... creo que no.
Also, commented out a hook for deleting trailing whitespaces in file lines upon saving.
Don't remember why but, perhaps, because of the artist-mode
. Less processing anyway.
(use-package files :ensure nil ;; :hook ;; (before-save . delete-trailing-whitespace) :custom (require-final-newline nil) ;; backup settings (backup-by-copying t) (backup-directory-alist `(("." . "~/.emacs.d/backups"))) (delete-old-versions t) (kept-new-versions 6) (kept-old-versions 2) (version-control t)) ; version numbers for backup files
Customization tools. Alternatively, one can use (make-temp-file "emacs-custom")
.
In order not to use customizations, set custom-file
to null-device
.
(use-package cus-edit :ensure nil :custom (custom-file (make-temp-file "emacs-custom")))
§ EasyPG Assistant
Is here for encrypting files with GnuPG
.
(use-package epa :ensure nil :custom (epg-gpg-program "gpg") (epa-pinentry-mode nil))
§ Buffer Names from Files
(use-package uniquify :ensure nil :custom (uniquify-buffer-name-style 'forward))
§ Miscellaneous
Load some of the packages from my elisp definitions.
(require 'my-misc)
§ Setup for Calculations
Shortcuts for inline metric prefix conversions for region-selected numbers. Based on a macro from My Elisp Definitions.
Elisp modules defined there are available because in the init
section for the emacs
#'use-package
form in the top I've added
their location to the 'load-path
.
Regex match removes underscore in optional formatting for Rust number.
(require 'my-math) (defun my-region/convert-zero-to-tera (start end) (interactive "r") (if (use-region-p) (let* ((regionp (buffer-substring start end)) (num (string-to-number (replace-regexp-in-string "_+" "" regionp)))) (message "%s T" (my-math/convert-metric-prefix-for num _ T 4))))) (defun my-region/convert-yocto-to-zero (start end) (interactive "r") (if (use-region-p) (let* ((regionp (buffer-substring start end)) (num (string-to-number (replace-regexp-in-string "_+" "" regionp)))) (message "%s" (my-math/convert-metric-prefix-for num y _ 6)))))
Additional units and constants used with calc
during thermal transport
studies.
If it grows beyond meaningful limits (unlikely to happen), I might move
this piece to calc.el
(use-package calc :config (setq var-ff "0.0483776900146") ; thermal transport flux conversion factor (eval-after-load "calc-units" '(progn (setq math-additional-units '((Bohr "5.29177249*10^(-11) m" "Bohr radius [ hbar^2/(m*e^2) ]" atU) (Eryd "2.1798741*10^(-18) J" "Rydberg energy [ e^2/(2*a0) ]" atU) (Ehart "4.3597482*10^(-18) J" "Hartree energy [ e^2/a0 ]" atU) (tryd "4.83776865318*10^(-17) s" "Rydberg time unit [ hbar/E_Ryd ]" atU) (thart "2.41888432659*10^(-17) s" "Hartree time unit [ hbar/E_Hart ]" atU) (vryd "1.09384563182*10^(6) m s^(-1)" "Rydberg velocity unit [ a0*E_Ryd/hbar ]" atU) (vhart "2.18769126364*10^(6) m s^(-1)" "Hartree velocity unit [ a0*E_Hart/hbar ]" atU)) math-units-table nil))))
§ Appearance tweaks
Font icons for Org sections etc.
To finish installation invoke M-x all-the-icons-install-fonts
Guix outputs a plethora of related packages when searching for all-the-icons
.
(use-package all-the-icons :config (load (expand-file-name (file-truename (format "%s/org/category-icons.el" my-init/grimoire-dir)))))
Mood-line
is a clean, minimalistic mode-line.
Moody
is an alternative, but it's less convenient.
(use-package mood-line :ensure t :config (mood-line-mode)) ;; (use-package moody ;; :ensure t ;; :config ;; (setq x-underline-at-descent-line t) ;; (moody-replace-mode-line-buffer-identification) ;; (moody-replace-vc-mode) ;; (moody-replace-eldoc-minibuffer-message-function))
In-buffer line bookmarks.
(use-package bm :ensure t :bind (("<C-f2>" . bm-toggle) ("<f2>" . bm-next) ("<S-f2>" . bm-previous)))
Golden ratio for frames and rainbows. For the latter, rainbow-mode
and -delimeters
is a yes, rainbow-identifiers
- no.
The Golden ratio toggle switch will be included in the general.el
use-package
form, since General hasn't been imported yet.
(use-package golden-ratio :ensure t) (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode)) (use-package rainbow-mode :diminish rainbow-mode :hook prog-mode)
Highlight matching parens:
(use-package paren :ensure nil :config (show-paren-mode t))
Highlight annotation keywords in both programming modes and Org:
(use-package hl-todo :hook (prog-mode . hl-todo-mode) (org-mode . hl-todo-mode) :config (setq hl-todo-highlight-punctuation ":" hl-todo-keyword-faces `(("TODO" warning bold) ("FIXME" error bold) ("HACK" font-lock-constant-face bold) ("REVIEW" font-lock-keyword-face bold) ("NOTE" success bold) ("DEPRECATED" font-lock-doc-face bold))))
§ General.el for custom shortcuts declarations
As from a while ago, when I migrated from spacemacs
to vanilla emacs,
I still use general.el
+ which-key
combo to define custom shortcuts.
However, only recently did I start refactoring the configuration, placing
shortcuts definitions for packages together with their own use-package
forms.
Throwing them altogether into general
's use-package
works too, but is
not modular nor elegant (that way one has to always refer to it when
adding/ removing/ editing/ a set of packages installed).
(use-package general :ensure t :config (general-define-key ;; replace default keybindings "C-s" 'swiper ; search for string in current buffer "M-x" '(lambda () (interactive) (counsel-M-x ""))) ; replace default M-x with ivy backend ;; "M-]" 'scheme-smart-complete) (general-create-definer my-leader-def ;; :prefix my-leader :prefix "M-SPC") (general-create-definer my-local-leader-def ;; :prefix my-local-leader :prefix "M-SPC m") (my-leader-def :states '(normal visual emacs) ;; Root "/" 'counsel-ag ;; "TAB" 'dired-sidebar-toggle-sidebar "TAB" '(switch-to-next-buffer :which-key "next buffer") ;; Selected region conversions "." '(:ignore t :which-key "Convert Selected") ".t" 'my-region/convert-zero-to-tera ".y" 'my-region/convert-yocto-to-zero ;; Windows "w" '(:ignore t :which-key "Windows") "ww" 'other-window "wh" 'split-window-below "wv" 'split-window-right "wo" 'delete-other-windows "wd" 'delete-window ;; Commands "c" '(:ignore t :which-key "Commands") "cc" 'org-capture "cf" 'flyspell-correct-word-before-point "cd" '(:ignore t :which-key "Counsel-Dash") "cda" 'dash-docs-activate-docset "cdd" 'counsel-dash-at-point "cl" 'org-store-link "ct" 'counsel-tramp "cy" '(:ignore t :which-key "Yas") "cyy" 'yas-insert-snippet "cyn" 'yas-new-snippet "cyv" 'yas-visit-snippet-file "+" '((lambda () (interactive) (my-misc/change-default-face-height-globally 20)) :which-key "+") "-" '((lambda () (interactive) (my-misc/change-default-face-height-globally -20)) :which-key "-") ;; Applications "a" '(:ignore t :which-key "Applications") "aa" '(:ignore t :which-key "AI gptel menu") "aaa" 'gptel-send "aas" 'gptel-send "aam" 'gptel-menu "aag" 'gptel "ad" 'dired "af" 'elfeed "ao" 'org-agenda ;; "ae" 'go-social-with-bitlbee "as" '(:ignore t :which-key "Shell selection") "ass" 'shell "ase" 'eshell "asa" 'ansi-term "aw" '(:ignore t :which-key "Work Calendar") "awd" '((lambda () (interactive) (let ((org-roam-dailies-directory my-init/worklog-path)) (org-roam-dailies-goto-date))) :which-key "Worklog Date") "aw." '((lambda () (interactive) (let ((org-roam-dailies-directory my-init/worklog-path)) (org-roam-dailies-goto-today))) :which-key "Worklog Today") ;; Smerge "s" '(:keymap smerge-basic-map :package smerge-mode :which-key "Smerge") ;; Toggles "t" '(:ignore t :which-key "Toggles") "tg" 'golden-ratio-mode "tl" 'toggle-truncate-lines "ts" 'toggle-scroll-bar ;; Buffers "b" '(:ignore t :which-key "Buffers") "bb" 'ivy-switch-buffer "bk" 'kill-buffer "ba" 'auto-fill-mode "bf" 'flyspell-buffer ;; Shortcuts "e" '(:ignore t :which-key "Edit") "ed" '((lambda() (interactive) (switch-to-buffer (find-file-noselect "~/.emacs.d/init.el"))) :which-key "dotemacs config") "eb" '((lambda() (interactive) (switch-to-buffer (find-file-noselect "~/.bashrc"))) :which-key "bashrc") "es" '((lambda() (interactive) (switch-to-buffer (find-file-noselect "~/.stumpwmrc"))) :which-key "stumpwm config") ;; Org-mode ;; Contains links to Grimoire "o" '(:ignore t :which-key "Open...") "ow" '(my-misc/open-link-in-eww :which-key "link in EWW") "oe" '(my-misc/open-link-in-eww :which-key "link in EWW") "ot" '((lambda() (interactive) (switch-to-buffer (find-file-noselect my-init/org-agenda-file))) :which-key "Todos and Agenda") "ob" '((lambda() (interactive) (switch-to-buffer (find-file-noselect my-init/org-backlog-file))) :which-key "Backlog") "oj" '((lambda() (interactive) (switch-to-buffer (find-file-noselect (format "%s/org/journal.org.gpg" my-init/grimoire-dir)))) :which-key "my olde Journal (for reference, no new edits)") "or" '((lambda() (interactive) (switch-to-buffer (find-file-noselect "~/Refs/phd.bib"))) :which-key "Main Bibtex file") "on" '((lambda() (interactive) (switch-to-buffer (find-file-noselect (file-truename (format "%s/papers.org" my-init/org-roam-dir))))) :which-key "Research Notes") ;; LSP-enhanced programming control "l" '(:ignore t :which-key "Language Commands") ;; NOTE: not using flycheck at this point ;; "ll" '(:keymap flycheck-command-map ;; :package flycheck ;; :which-key "Flycheck") "lm" 'imenu "lq" 'lsp-shutdown-workspace "lw" 'lsp-restart-workspace "lh" 'lsp-describe-thing-at-point "lr" 'lsp-rename "ld" 'lsp-find-definition "li" 'lsp-find-references "lp" 'lsp-ui-peek-find-references "lu" 'lsp-ui-mode))
§ Utility packages
Better menus for package-install. No guix so far.
(use-package paradox :config (paradox-enable))
company-mode
for autocompletion. Many extensions in guix.
(use-package company :ensure t :config (add-hook 'after-init-hook 'global-company-mode))
One of such extensions: a front-end with icons.
(use-package company-box :diminish t :hook (company-mode . company-box-mode))
which-key
to get useful keystroke hints.
(use-package which-key :ensure t :custom (which-key-idle-delay 0.5) (which-key-add-column-padding 2) :config (which-key-mode))
Automatically revert buffers when files on disk change.
(use-package autorevert :ensure t :diminish auto-revert-mode)
wgrep
& swiper
(use-package wgrep) (use-package swiper)
silversearcher
is a faster grep
(use-package ag :defer t :ensure-system-package (ag . silversearcher-ag) :custom (ag-highlight-search t "Highlight the current search term."))
§ Elisp Development Tools
Transliteration to ASCII package:
(use-package unidecode)
Data structures and sequence processing packages.
In principle, those are re-used through the following imports. But I leave them here explicitly.
(use-package s) (use-package dash) (use-package ht) (use-package mustache)
All of them available in Guix, no need for Quelpa-ing.
One of the outcomes of these imports is the definition of handy
threading macro found in dash.el
, e.g. ->
, ->>
and -->
.
I can start using them straight away in the following definitions.
§ Yasnippet
A load of snippets that I care by habit, but rarely use...
(use-package yasnippet :ensure yasnippet-snippets :config (setq yas-snippet-dirs (-> (format "%s/snippets" my-init/grimoire-dir) (file-truename) (list) (append yas-snippet-dirs))))
§ Kill Ring manipulations
Undo-tree
provides a more familiar undoing, ready to be used together
with evil-mode
. In order to get the kill-ring history I also plug in
the browse-kill-ring
.
(use-package undo-tree :ensure t :config (global-undo-tree-mode) :custom (undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))) (use-package browse-kill-ring :ensure t :general (my-leader-def :states '(normal visual emacs) "y" 'browse-kill-ring))
§ Magit
THE git interface like no other, nowhere...
(use-package magit :ensure t :general (my-leader-def :states '(normal visual emacs) "g" 'magit-status "M-g" 'magit-dispatch))
Together with git-gutter, to watch for changed lines in fringes:
(use-package git-gutter+ :ensure t :config (use-package git-gutter-fringe+) (global-git-gutter+-mode))
§ Completion Tandem: Ivy and Counsel
§ Ivy
The completion framework of choice.
(use-package ivy :ensure t :custom (ivy-use-virtual-buffers t) (ivy-count-format "(%d/%d) ") :config (ivy-mode 1)) (use-package ivy-yasnippet) ;; (use-package ivy-bibtex :ensure t) (use-package helm-bibtex :ensure t)
Additionally, use Ivy completion in XREF buffers (useful for output of
LSP search results to separate buffers with '#ivy-occur
C-c C-o
).
(use-package ivy-xref :ensure t :init (setq xref-show-definitions-function #'ivy-xref-show-defs))
§ Counsel
Ivy's loyal companion.
(use-package counsel :ensure t)
§ TRAMP
I only add completion support, for now.
(use-package counsel-tramp)
§ Dash Docsets
counsel-dash provides searching through Dash docsets in emacs. Many of those are snapshots of invaluable online resources.
(use-package counsel-dash ;; :custom (dash-docs-docsets-path "~/Grimoire/docsets") (dash-docs-docsets-url "https://raw.github.com/Kapeli/feeds/master") ;; (counsel-dash-docsets-url "https://raw.github.com/Kapeli/feeds/master") (dash-docs-use-workaround-for-emacs-bug nil) ; for 26.3 fixes conn bug (counsel-dash-browser-func 'browse-url) ; or 'eww :hook (c-mode . (lambda () (setq-local counsel-dash-docsets '("C")))) (c++-mode . (lambda () (setq-local counsel-dash-docsets '("C++")))) (f90-mode . (lambda () (setq-local counsel-dash-docsets '("Fortran" "MPI" "OpenMP")))) (fortran-mode . (lambda () (setq-local counsel-dash-docsets '("Fortran" "MPI" "OpenMP")))) (scheme-mode . (lambda () (setq-local counsel-dash-docsets '("R5RS")))) (sly-mode . (lambda () (setq-local counsel-dash-docsets '("Common Lisp")))) (emacs-lisp-mode . (lambda () (setq-local counsel-dash-docsets '("Emacs Lisp")))) (dockerfile-mode . (lambda () (setq-local counsel-dash-docsets '("Docker")))))
§ Projectile
It is a project management tool that uses the frameworks above.
(use-package projectile :ensure t :custom (projectile-completion-system 'ivy) (projectile-enable-caching t) :config (use-package counsel-projectile :ensure t) (counsel-projectile-mode) (projectile-load-known-projects) :diminish projectile-mode :general (my-leader-def :states '(normal visual emacs) "p" '(:keymap projectile-command-map :package projectile :which-key "Projectile (Counsel)")))
§ Programming modes
§ General syntax checks with Flycheck
(use-package flycheck :ensure t :hook (after-init . global-flycheck-mode))
§ Diagrams
Classic graphviz
diagrams specifications.
(use-package graphviz-dot-mode)
§ Markup
Generic .yaml
formatting.
(use-package yaml-mode)
Separate mode for docker
, extending on the .yaml
.
(use-package dockerfile-mode :config (add-to-list 'auto-mode-alist '("Dockerfile\\'" . dockerfile-mode)))
Common Workflows Language is a concretization of .yaml
too.
(use-package cwl-mode)
§ Gnuplot
(use-package gnuplot) (use-package gnuplot-mode)
§ Lisps
Enhancing the Lisp coding.
In case I need a lot slurp/barf-ing control over lisp forms -
I'll try out lispy
.
(use-package elec-pair :ensure nil :config (require 'elec-pair) (defun my-init/electric-pair-local-text-mode () "Advise and wrap electric pairs in text mode." (add-function :before-until electric-pair-inhibit-predicate (lambda (c) (eq c ?<))) (electric-pair-local-mode)) :hook ((prog-mode . electric-pair-local-mode) (text-mode . my-init/electric-pair-local-text-mode)))
TODO: switch from evil-cleverparens
to LispyVille.
(use-package evil-cleverparens :hook (sly-mode . evil-cleverparens-mode) (emacs-lisp-mode . evil-cleverparens-mode))
§ Emacs Lisp
Definitions' visual highlighting:
(use-package highlight-defined :ensure t :hook (emacs-lisp-mode . highlight-defined-mode)) (use-package highlight-quoted :ensure t :hook (emacs-lisp-mode . highlight-quoted-mode))
Sexy elisp form evaluation result overlay:
(use-package eros :hook (emacs-lisp-mode . eros-mode))
Suggest.el
in searching for forms
(use-package suggest)
§ Common Lisp
Sly is neat development of SLIME attitude towards consing the Lisp.
(use-package sly :config (setq inferior-lisp-program "sbcl"))
§ Python
For python development, elpy
feels Okay.
(use-package elpy :ensure t :custom (python-shell-interpreter "python") :init (progn (setenv "WORKON_HOME" (format "%s/envs/" (getenv "HOME"))) (define-key elpy-refactor-map (kbd "b") (cons (format "%slack format code" (propertize "b" 'face 'bold)) 'elpy-black-fix-code)) (elpy-enable)))
Flymake-python-pyflakes setup for code inspection.
(use-package flymake-python-pyflakes :hook (python-mode . flymake-python-pyflakes-load) :custom (flymake-python-pyflakes-executable "flake8"))
Flymake-ruff for code linting.
(use-package flymake-ruff :ensure t :hook (python-mode . flymake-ruff-load))
§ Js & Typescript
Js/Js2 mode setup instructions are a mess. The following seems to work okay.
(use-package js2-mode :config (add-to-list 'auto-mode-alist '("\\.js\\'" . js-mode)) (add-hook 'js-mode-hook 'js2-minor-mode) (add-to-list 'interpreter-mode-alist '("node" . js2-mode)))
Tide is cool Typescript IDE-like mode. Like it!
(use-package tide :ensure t :config (defun setup-tide-mode () (interactive) (tide-setup) (flycheck-mode +1) (setq flycheck-check-syntax-automatically '(save mode-enabled)) (eldoc-mode +1) (tide-hl-identifier-mode +1) (company-mode +1)) ;; aligns annotation to the right hand side (setq company-tooltip-align-annotations t) ;; formats the buffer before saving (add-hook 'before-save-hook 'tide-format-before-save) (add-hook 'typescript-mode-hook #'setup-tide-mode))
Web temlpates and snippets editing.
(use-package web-mode :config (add-to-list 'auto-mode-alist '("\\.tsx\\'" . web-mode)) (add-hook 'web-mode-hook (lambda () (when (string-equal "tsx" (file-name-extension buffer-file-name)) (setup-tide-mode)))) ;; enable typescript - tslint checker (flycheck-add-mode 'typescript-tslint 'web-mode))
§ Rust
No surprises here, all set up borrowed from the page on top of the search. Using Rustic, that integrates well with LSP.
(use-package rust-mode :ensure t) (use-package rustic :ensure t :config (setq lsp-eldoc-hook nil) (setq lsp-enable-symbol-highlighting nil) (setq lsp-signature-auto-activate nil) (setq lsp-ui-doc-enable nil) ;; (setq lsp-ui-mode-hook nil) ;; (setq rustic-compile-rustflags "-C link-arg=-s") (setq rustic-format-on-save t))
§ Haskell
Haskell-mode setup according to the tutorial:
(use-package haskell-mode :ensure t :defer t :hook (haskell-mode . hindent-mode)) ;; ;; Quite slow those ones. No need at this point. ;; ;; :config ;; (let ((my-cabal-path (expand-file-name "~/.cabal/bin"))) ;; (setenv "PATH" (concat my-cabal-path path-separator (getenv "PATH"))) ;; (add-to-list 'exec-path my-cabal-path)) ;; :custom (haskell-tags-on-save t)) (use-package hindent :after haskell-mode) (use-package company-ghci :after haskell-mode)
§ Formal Proof Systems
No much setup needed for those goodies so far, apart from their compiler installation.
The programming environments are essentially unified by the proof-general
.
(use-package proof-general) (use-package company-coq :hook (coq-mode . company-coq-mode))
§ Language Server Protocol
A great alternative to "conventional" development environments, LSP support bumps programming experience in emacs up to a next level, especially for statically compiled languages.
(use-package lsp-mode :ensure t :hook (f90-mode . lsp-deferred) (fortran-mode . lsp-deferred) (c++-mode . lsp-deferred) (c-mode . lsp-deferred) ;; (lsp-mode . lsp-ui-mode) :commands (lsp lsp-deferred) :init (setf lsp-clients-clangd-executable "/usr/bin/clangd") :custom (lsp-enable-snippet t) (lsp-auto-guess-root nil) ;; NOTE: eldoc clogging fortls trouble, switched off: (lsp-eldoc-enable-hover nil) (lsp-eldoc-enable-signature-help nil) (lsp-eldoc-prefer-signature-help t) (lsp-signature-render-all nil) (lsp-eldoc-render-all nil) (lsp-clangd-binary-path "/usr/bin/clangd") (lsp-clients-clangd-library-directories ) (setf flycheck-clang-include-path '("/usr/include")) (lsp-clients-fortls-args '("--lowercase_intrinsics" "--use_signature_help" "--variable_hover" "--hover_signature")) (lsp-rust-analyzer-cargo-watch-command "clippy") (lsp-rust-analyzer-server-display-inlay-hints t) :config (use-package lsp-ui :ensure t :config (set-face-attribute 'lsp-ui-doc-background nil :height 140 :family "Iosevka") :custom ;; lsp-ui-doc (lsp-ui-doc-enable t) (lsp-ui-doc-header t) (lsp-ui-doc-include-signature t) (lsp-ui-doc-position 'top) ;; top, bottom, or at-point (lsp-ui-doc-max-width 120) (lsp-ui-doc-max-height 30) (lsp-ui-doc-use-childframe t) (lsp-ui-doc-use-webkit nil) ;; lsp-ui-sideline (lsp-ui-sideline-enable nil) ;; lsp-ui-peek (lsp-ui-peek-enable t) (lsp-ui-peek-peek-height 25) (lsp-ui-peek-list-width 35) (lsp-ui-peek-fontify 'on-demand)) ;; never, on-demand, or always (remove-hook 'flymake-diagnostic-functions 'flymake-proc-legacy-flymake) (add-hook 'lsp-mode-hook 'yas-minor-mode) (add-to-list 'lsp-language-id-configuration '(fortran-mode . "fortran")) (add-to-list 'lsp-language-id-configuration '(f90-mode . "fortran")) (add-to-list 'lsp-language-id-configuration '(c-mode . "c")))
Clang-format for linting C++ code.
(use-package clang-format :config (load "/usr/share/emacs/site-lisp/clang-format/clang-format.el"))
§ Org-mode Setup
§ Babel Imports
Asynchronous execution of orgmode source blocks:
(use-package ob-async :ensure t)
§ Org Itself
At start, 'org-agenda-files
tracks the root of the Roam repository.
#'my-init/extend-org-agenda
allows me to add and browse current
directory/ project.
(use-package org :ensure org-contrib :init (setq org-agenda-files (list my-init/org-roam-dir)) (defun my-init/extend-org-agenda () "Extend Org agenda with files in the current directory." (interactive) (let ((dir (my-misc/my-current-dir))) (dolist (file (if (y-or-n-p "Recursive?") (directory-files-recursively dir "\\.org$") (directory-files dir t "\\.org$"))) (push file org-agenda-files)))) :config (setq org-format-latex-options (plist-put org-format-latex-options :scale 2.0)) (org-babel-do-load-languages 'org-babel-load-languages '((org . t) (emacs-lisp . t) (lisp . t) (scheme . t) (shell . t) (awk . t) (gnuplot . t) (python . t) (fortran . t) (ditaa . t))) :custom (org-image-actual-width nil) (org-babel-lisp-eval-fn #'sly-eval) (org-confirm-babel-evaluate nil) (org-startup-indented t) (org-hide-leading-stars nil) (org-enforce-todo-dependencies t) (org-agenda-todo-list-sublevels nil) (org-cycle-separator-lines -1) (org-log-repeat nil) ;; (org-extend-today-until 3) (org-agenda-span 1) (org-blank-before-new-entry '((heading . t) (plain-list-item . nil))) (org-src-tab-acts-natively nil) (org-ditaa-jar-path "~/bin/ditaa/ditaa-0.11.0-standalone.jar") (org-capture-templates '(("b" "Backlog" item (file+olp+datetree my-init/org-backlog-file "Backlog | Incoming") "- %i") ("t" "Todo" entry (file+headline my-init/org-agenda-file "Agenda") "* TODO %?\n %i\n %a") ("p" "Plain at point" plain (file+function buffer-name (lambda () (goto-char (point)))) "%i"))))
§ Exports from Org
Additional dispatches for:
ReStructured_Text
Also, path to reveal.js
.
(use-package ox-rst) (use-package ox-reveal :custom (org-reveal-root (format "file://%s/talks/_org_reveal/reveal.js" (file-truename my-init/grimoire-dir))))
§ Orgmode Tweaks
Decorating outlines with Org-Bullets.
The sample bullets' list:
default: ◉ ○ ✸ ✿
large: ♥ ● ◇ ✚ ✜ ☯ ◆ ♠ ♣ ♦ ☢ ❀ ◆ ◖ ▶
small: ► • ★ ▸
ellipsis: ▼ ↴ ⬎ ⤷ … ⋱
(use-package org-bullets :custom (org-bullets-bullet-list '("◉")) (org-ellipsis "⋱") :hook (org-mode . org-bullets-mode))
Auto-tangling feature, quite useful IMO when authoring sources within Org:
(use-package org-auto-tangle :defer t :init (setf org-auto-tangle-default t) :hook (org-mode . org-auto-tangle-mode))
§ Org Extensions
§ Edraw
Editing diagrams within Org-mode.
(use-package edraw :quelpa (edraw :fetcher github :repo "misohena/el-easydraw") :config (use-package edraw-org :after org))
§ Org-Remark
Highlights and note-taking for texts, including eww:
pages and nov
EPUBs.
(use-package org-remark :after org :ensure t :bind (("C-c m m" . #'org-remark-mark) ("C-c m o" . #'org-remark-open) ("C-c m ]" . #'org-remark-view-next) ("C-c m [" . #'org-remark-view-prev) ("C-c m r" . #'org-remark-remove) ("C-c m d" . #'org-remark-delete)) :custom (org-remark-notes-file-name my-init/org-remark-notes-file) :config (org-remark-global-tracking-mode +1) (with-eval-after-load 'eww (org-remark-eww-mode +1)) (with-eval-after-load 'nov (org-remark-nov-mode +1)) (with-eval-after-load 'info (org-remark-info-mode +1)))
§ Org-Present
Presenting inside Emacs buffers.
hide-mode-line
is recommended for full immersion, but
worked unstable for me.
(use-package org-present :ensure t :hook (org-present-mode . hide-mode-line-mode) :bind (("s-." . org-present-next) ("s-," . org-present-prev)))
§ Org-Books
Simple catalogization tool. It's registry is part of my digital garden.
(use-package org-books :custom (org-books-file (file-truename (format "%s/books_revised.org" my-init/org-roam-dir))))
§ Org-Download
Image drag-and-drop for Org-mode.
(use-package org-download :ensure t :defer t :after org :init (with-eval-after-load 'org (org-download-enable)) :custom (org-download-screenshot-method "mate-screenshot -a") (org-download-image-org-width 600) ;; :bind ;; (:map org-mode-map ;; (("s-Y" . org-download-screenshot) ;; ("s-y" . org-download-yank))) :config (setq-default org-download-image-dir my-init/org-download-dir))
§ Org-Ref
Citations management in Org.
After having adopted Org-Roam, the notes files are created per-paper and become Roam nodes.
(use-package org-ref ;; :after (org ivy-bibtex) :after (org helm-bibtex) :general (:keymaps 'org-mode-map "C-c ]" 'org-ref-insert-link) :custom (bibtex-completion-bibliography '("~/Refs/fusion.bib" "~/Refs/phd.bib" "~/Refs/cs.bib" "~/Refs/math.bib" "~/Refs/web3.bib" "~/Refs/formal.bib")) (bibtex-completion-library-path '("~/Refs/pdfs/")) (bibtex-completion-notes-path (file-truename (format "%s/research/paper-notes/" my-init/org-roam-dir))) (bibtex-completion-additional-search-fields '(keywords)) (bibtex-completion-notes-template-multiple-files "#+category: research\n#+title: ${title} (${year})\n#+auto_tangle: nil\n#+filetags: research paper_notes ${=type=}\n ,,*${author-or-editor}*\n\nSee [[cite:&${=key=}]]\n") (bibtex-completion-pdf-open-function (lambda (fpath) (call-process "atril" nil 0 nil fpath))) ;; autokey formatting: (bibtex-autokey-year-length 4) (bibtex-autokey-name-year-separator "-") (bibtex-autokey-year-title-separator "-") (bibtex-autokey-titleword-separator "-") (bibtex-autokey-titlewords 2) (bibtex-autokey-titlewords-stretch 1) (bibtex-autokey-titleword-length 5) ;; Ivy backend: (org-ref-insert-link-function 'org-ref-insert-link-hydra/body) (org-ref-insert-cite-function 'org-ref-cite-insert-ivy) (org-ref-insert-label-function 'org-ref-insert-label-link) (org-ref-insert-ref-function 'org-ref-insert-ref-link) (org-ref-cite-onclick-function (lambda (_) (org-ref-citation-hydra/body))) :init (require 'org-ref-ivy))
org-ref-prettify
formats org-ref links
(use-package org-ref-prettify :defer t :hook (org-mode . org-ref-prettify-mode))
§ Org-Roam
Provides the stuff vanilla Org is lacking to become one space killer notetaking extension for emacs. Namely, database that indexes the notes in Org-Roam repository, and a handy elisp structure defined for the Roam Nodes representation.
Forms the foundation of my digital garden.
(use-package org-roam :ensure t :custom (org-roam-directory my-init/org-roam-dir) (org-roam-db-location (file-truename (format "%s/org/org-roam.db" my-init/grimoire-dir))) ;; Daily note taking (org-roam-dailies-directory "daily/") (org-roam-dailies-capture-templates '(("d" "default" entry "* %?" :target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")))) ;; Generic capture templates. Mind the subdirs in (org-roam-capture-templates '(("d" "default" plain "%?" :target (file+head "${slug}.org" "#+title: ${title}\n#+auto_tangle: nil\n") :unnarrowed t) ("l" "Lit-Notes" plain "%?" :target (file+head "literature/${slug}.org" "#+category: books\n#+title: ${title}\n#+auto_tangle: nil\n#+filetags: read\n") :unnarrowed t) ("m" "Media" plain "%?" :target (file+head "media/${slug}.org" "#+category: media\n#+title: ${title}\n#+auto_tangle: nil\n#+filetags: media\n") :unnarrowed t) ("k" "Kata-Log" plain "%?" :target (file+head "kata-log/${slug}.org" "#+title: ${title}\n#+auto_tangle: nil\n#+filetags: kata\n") :unnarrowed t) ("p" "Projects" plain "%?" :target (file+head "projects/${slug}.org" "#+category: projects\n#+title: ${title}\n#+auto_tangle: nil\n#+filetags: project\n") :unnarrowed t) ("g" "Gaming" plain "%?" :target (file+head "gaming/${slug}.org" "#+category: prpgs\n#+title: ${title}\n#+auto_tangle: nil\n#+filetags: gaming\n") :unnarrowed t) ("a" "Art" plain "%?" :target (file+head "art/${slug}.org" "#+title: ${title}\n#+auto_tangle: nil\n#+filetags: art\n") :unnarrowed t) ("r" "Research" plain "%?" :target (file+head "research/${slug}.org" "#+category: research\n#+title: ${title}\n#+auto_tangle: nil\n#+filetags: research\n") :unnarrowed t) ("t" "Engineering & Tech" plain "%?" :target (file+head "tech/${slug}.org" "#+title: ${title}\n#+auto_tangle: nil\n#+filetags: tech\n") :unnarrowed t) ("u" "Setup & Utilities" plain "%?" :target (file+head "setup-utils/${slug}.org" "#+title: ${title}\n#+auto_tangle: nil\n#+filetags: setup\n") :unnarrowed t) ("w" "Work Files & Specific" plain "%?" :target (file+head "work/${slug}.org" "#+title: ${title}\n#+auto_tangle: nil\n#+filetags: work\n") :unnarrowed t))) :config (load (expand-file-name "~/.emacs.d/lisp-dev/my-elisp-collection/my-org.el")) (require 'my-org) (add-to-list 'display-buffer-alist '("\\*org-roam\\*" (display-buffer-in-direction) (direction . right) (window-width . 0.26) (window-height . fit-window-to-buffer))) (org-roam-db-autosync-mode) :general (my-leader-def :states '(normal visual emacs) "ar" '(:ignore t :which-key "Org-Roam") "arr" 'org-roam-node-find "arh" 'my-org/roamify-header "ari" 'org-roam-node-insert "arb" 'org-roam-buffer-toggle "arc" 'org-roam-capture "ard" 'org-roam-dailies-goto-date "ar." 'org-roam-dailies-goto-today))
§ Deft
Horizontal text-search throughout Roam repo.
(use-package deft :after org :bind ("C-c n d" . deft) :custom (deft-recursive t) (deft-use-filter-string-for-filename t) (deft-default-extension "org") (deft-directory org-roam-directory))
§ Org-Roam-UI
Mindblowing visualization of the Roam nodes relations graph.
(use-package org-roam-ui :config (setq org-roam-ui-sync-theme t org-roam-ui-follow t org-roam-ui-update-on-save t org-roam-ui-open-on-start t))
§ Org-AI
AI integration with Org mode to superpower textual tasks.
gptel
is very handy since it can be used uniformly in Emacs, not
only in org-buffers, as well as in its own buffer.
I also like its transient menu and, most importantly, working through
Ollama.ai with local models! With orca-mini
I have an ever-ready and
free assistant in Org that works on a modest laptop environment.
(use-package gptel :init (setq gptel-my-backend (gptel-make-ollama "Ollama" ;Any name of your choosing :host "localhost:11434" ;Where it's running :models '("orca-mini:latest" ;Installed models "mistral:latest" "codellama:latest" "codegemma:latest") :stream t)) :config (setq-default gptel-backend gptel-my-backend) (setq-default gptel-model "orca-mini:latest") (setq-default gptel-default-mode 'org-mode) (setq-default gptel-api-key (getenv "OPENAI_TOKEN")) :hook (org-mode . gptel-mode))
Org-AI
requires dedicated source block formatting within Org.
Not very convenient, however it can generate images, so I keep it too.
(use-package org-ai :ensure t :commands (org-ai-mode org-ai-global-mode) :init (add-hook 'org-mode-hook #'org-ai-mode) ; enable org-ai in org-mode (org-ai-global-mode) ; installs global keybindings on C-c M-a :config (setq org-ai-openai-api-token (getenv "OPENAI_TOKEN")) (setq org-ai-default-chat-model "gpt-3.5-turbo") (org-ai-install-yasnippets))
Khoj project adds AI-assistance on top of Org-Roam knowledgebase. Looks like the future of smart note-taking.
(use-package khoj :ensure t :pin melpa :bind ("C-c s" . 'khoj) :config (setq khoj-server-is-local t khoj-server-url "http://localhost:42110" khoj-org-directories (list my-init/org-roam-dir)))
§ Applications that Rock
Those packages add up to awesomeness of my Emacs setup being full-scale apps on their own.
Even more - Emacs makes possible to glue them into one-state-interoperable-soup that's oh so tasty...
E.g. I can drag into the org-mode links not only to emails, but also pinpointing telegram threads. Awesome!
§ Translations
Emacs interface to Google Translate.
(use-package google-translate :init (require 'google-translate-smooth-ui) :bind ("C-c t" . google-translate-smooth-translate))
§ EAT: Emulate a Terminal in Emacs
(use-package eat :ensure t :hook (eshell-load . eat-eshell-mode) :general (my-leader-def :states '(normal visual emacs) "ast" 'eat))
§ PDF-Tools
(use-package pdf-tools :pin manual :config (pdf-tools-install) (setq-default pdf-view-display-size 'fit-width) (define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward) :custom (pdf-annot-activate-created-annotations t "automatically annotate highlights"))
§ Nov-mode
A major-mode to read e-books within emacs.
(use-package nov :config (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)))
§ Decide
For random choices for RPGs and not only.
(use-package decide)
§ Elfeed
RSS-reader, tweaked to import feed list from Orgmode.
(use-package elfeed :ensure elfeed-org :custom ;; Entries older than 2 weeks are marked as read (elfeed-search-filter "@2-weeks-ago +unread -reddit") :config ;; FIXME: (setq elfeed-db-directory "~/Feeds/elfeed-db") (add-hook 'elfeed-new-entry-hook (elfeed-make-tagger :before "2 weeks ago" :remove 'unread)) (elfeed-org) (setq rmh-elfeed-org-files (list (file-truename (format "%s/feeds.org" my-init/org-roam-dir)) (file-truename (format "%s/podcasts.org" my-init/org-roam-dir)))))
§ Telega
THE client for telegram. 146% awesome and useful!
Also, an example where guix packages shine: server, client and unofficial contrib extensions all to be installed and kept updated easily with Guix.
(use-package telega :commands (telega) :defer t :init (setq telega-root-show-avatars '(scale rotate90)) (setq telega-chat-show-avatars '(scale rotate90)) (setq telega-use-images '(scale rotate90)) (setq telega-emoji-font-family "Iosevka Extended") ;; (setq telega-emoji-use-images t) ;; (setq telega-tdlib-max-version "1.8.4") (setq telega-server-libs-prefix "~/.guix-profile") ; to use TDLib obtained with Guix (setq telega-emoji-use-images nil) ; to fix rendering of reactions :custom (telega-mode-line-mode 1) :config (require 'ol-telega) ; <- can also play with shortened urls :general (my-leader-def :states '(normal visual emacs) "at" 'telega))
§ Mu4e
Mu4e is an email client that works as front-end for emails
fetched by offlineimap
and indexed by mu
.
That utility chain at the moment is not present in Guix,
and the setup is quite intimate to be publicly exported.
So just trust me it's there too. Mu4e
.
§ Evil-mode
Vim keystrokes are recorded on the back of my skull, exactly where the nerves start leading towards my fingertips.
Of the vanilla emacs shortcuts I know by heart only a small
subset, still navigating over my buffers with evil
- vim
emulation for emacs. And know that I am not ashamed of it,
at all!
(use-package evil :ensure t :init (setq evil-want-keybinding nil) :config (evil-set-undo-system 'undo-tree) (evil-mode 1))
evil-collection
brings predictable evil behaviour in various modes,
e.g. dired
and mu4e
.
(use-package evil-collection :after evil :ensure t :diminish t :config (evil-collection-init))
Binding keys for various keymaps in evil
can be done via
evil-leader
package. I'm not doing that at the moment, but anyways.
Check the docs for description of evil-leader
.
(use-package evil-leader)
A minor mode extension that emulates surround.vim
(use-package evil-surround :ensure t :config (global-evil-surround-mode 1))