I tend to have multiple machines for different tasks: working, personal, etc… Every time I switch systems I always have to debug Emacs and install missing packages. This initial pain and frustration with starting my life with a new system is my fault. My Emacs configuration has been for a long time just an amalgamation of pieces of code I found on the internet… When I started working on the Barcelona Supercomputing Center I said “no” to myself and decided to make a portable Emacs configuration. Inspired by the likes of:
- Nicolas P. Rougier (N A N O Emacs)
- Matthew Zeng (M-EMACS)
- Snackon (Witchmacs)
- Pavel Korytov (SqrtMinusOne)
- Sophie Bosio
;; This file replaces itself with the actual
;; configuration at first run.
;; We can't tangle without org!
(require 'org)
;; Open the configuration
(find-file (concat user-emacs-directory "init.org"))
;; tangle it
(org-babel-tangle)
;; load it
(load-file (concat user-emacs-directory "init.el"))
;; finally byte-compile it
(byte-compile-file (concat user-emacs-directory "init.el"));;; -*- lexical-binding: t -*- (defun tangle-init ()
"If the current buffer is init.org the code-blocks are
tangled, and the tangled file is compiled."
(when (equal (buffer-file-name)
(expand-file-name
(concat user-emacs-directory "init.org")))
;; Avoid running hooks when tangling.
(let ((prog-mode-hook nil))
(org-babel-tangle)
(byte-compile-file (concat user-emacs-directory "init.el")))))
(add-hook 'after-save-hook 'tangle-init)(defvar custom-bindings-map '()) (setq gc-cons-percentage 0.6)
(setq gc-cons-threshold (* 50 1000 1000))
;; Set and reset threshold
(let ((old-gc-treshold gc-cons-threshold))
(setq gc-cons-threshold most-positive-fixnum)
(add-hook 'after-init-hook
(lambda () (setq gc-cons-threshold old-gc-treshold))))
;; native-comp warning
(setq native-comp-async-report-warnings-errors 'silent)
(setq byte-compile-warnings
'(not free-vars unresolved noruntime lexical make-local))
(setq which-func-update-delay 1.0)
(setq process-adaptive-read-buffering nil)
(setq read-process-output-max (* 4 1024 1024))
(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") (require 'package)
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package)
(eval-when-compile
(unless (bound-and-true-p package--initialized)
;; be sure load-path includes package directories
(when (< emacs-major-version 27)
(package-initialize)))
(require 'use-package)))
(require 'use-package-ensure)
(setq use-package-always-ensure t) (setq package-archives
'(("GNU ELPA" . "https://elpa.gnu.org/packages/")
("MELPA" . "https://melpa.org/packages/")
("ORG" . "https://orgmode.org/elpa/")
("MELPA Stable" . "https://stable.melpa.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/"))
package-archive-priorities
'(("GNU ELPA" . 20)
("MELPA" . 15)
("ORG" . 10)
("MELPA Stable" . 5)
("nongnu" . 0)))
(package-initialize)Straight is supposed to be a replacement for package. Since I am not very inclined on changing drastically to another package manager in emacs I will just have it here for testing and because of some packages that might only be available trough straight.
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name
"straight/repos/straight.el/bootstrap.el"
(or (bound-and-true-p straight-base-dir)
user-emacs-directory)))
(bootstrap-version 7))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://radian-software.github.io/straight.el/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))(setq utf-translate-cjk-mode nil)
(set-language-environment "UTF-8")
(setq locale-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8)
(set-selection-coding-system (prefer-coding-system 'utf-8))
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))(scroll-bar-mode -1)
(menu-bar-mode 0)
(tool-bar-mode 0)
(display-time-mode 1)
(display-battery-mode 1)(setq ring-bell-function 'ignore)
(setq truncate-lines t)
(setq frame-resize-pixelwise t)(fset 'yes-or-no-p 'y-or-n-p)(defun custom/kill-this-buffer ()
(interactive) (kill-buffer (current-buffer)))
(global-set-key (kbd "C-x k")
'kill-buffer-and-window)
(global-set-key (kbd "C-c k")
'kill-buffer)(defun config-visit()
(interactive)
(find-file "~/.emacs.d/init.org"))
(global-set-key (kbd "C-c e") 'config-visit)(put 'dired-find-alternate-file 'disabled nil) (setq backup-by-copying t
backup-directory-alist '(("." . "~/.emacs.d/.saves/"))
delete-old-versions t
kept-new-versions 6
kept-old-versions 2)(setq frame-title-format "%b")Tramp by default works pretty alright. The only added thing is a way to X11 forwarding trough tramp making it possible to have graphical application working as well once connected to external servers.
(use-package tramp
:ensure t
:config
(add-to-list 'tramp-methods
'("sshx11"
(tramp-login-program "ssh")
(tramp-login-args
(("-l" "%u") ("-p" "%p") ("%c")
("-e" "none") ("-X") ("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-login ("-l"))
(tramp-remote-shell-args ("-c"))
(tramp-gw-args
(("-o" "GlobalKnownHostsFile=/dev/null")
("-o" "UserKnownHostsFile=/dev/null")
("-o" "StrictHostKeyChecking=no")
("-o" "ForwardX11=yes")))
(tramp-default-port 22)))
(tramp-set-completion-function "sshx11"
tramp-completion-function-alist-ssh)
(setq tramp-default-method "ssh")
)This option is bonded to the key C-x C-u by default, but deactivated. I want to make it available since the beginning.
(put 'upcase-region 'disabled nil)Also for some reason we consider this option confusing when starting to use emacs. I guess if we think and assume the emacs way to do things, (aka anything new should have a new dedicated buffer), then one could theoretically call this option confusing. For some reason, In my head the idea of using the same buffer to open a new directory, is what makes more sense…
(put 'dired-find-alternate-file 'disabled nil)(use-package doom-themes
:ensure t
:config
(load-theme 'doom-one t)
(doom-themes-org-config))For information related with fonts and choosing fonts a great video is this one by the fantastic Protesilaos Stavrou.
;; set a default font
(when (member "Fira Code" (font-family-list))
(set-face-attribute 'default nil
:font "Fira Code"
:height 160))
(when (member "Iosevka Fixed Curly" (font-family-list))
(set-face-attribute 'default nil
:font "Iosevka Fixed Curly"
:height 160))
(when (member "Iosevka Comfy" (font-family-list))
(set-face-attribute 'default nil
:font "Iosevka Comfy"
:height 160))(use-package all-the-icons-dired
:if (display-graphic-p)
:hook (dired-mode . all-the-icons-dired-mode))All codes where searched here: Unicode searcher
(global-prettify-symbols-mode 1)
(defun add-pretty-lambda ()
(setq prettify-symbols-alist
'(
("[ ]" . 9744)
("[X]" . 9745)
("lambda" . 955)
("epsilon" . 603)
("->" . 8594)
("<-" . 8592)
(":-" . 8592)
("!sum" . 8721)
("<=" . 8804)
(">=" . 8805)
("=>" . 8658)
("#+BEGIN_SRC" . 955)
("#+END_SRC" . 955)
("#+begin_src" . 955)
("#+end_src" . 955))))
(add-hook 'prog-mode-hook 'add-pretty-lambda)
(add-hook 'org-mode-hook 'add-pretty-lambda)Olivetti centers text when editing.
(use-package olivetti
:defer t
:bind (:map custom-bindings-map ("C-c o" . olivetti-mode))
:config
(setq olivetti-style t)
(olivetti-set-width 80))(use-package writeroom-mode
:bind (:map custom-bindings-map ("<f1>" . writeroom-mode))
:defer t)(setq inhibit-startup-screen t)In case you do not know the reason for such an initial
;; https://www.youtube.com/watch?v=NfjsLmya1PI
(setq initial-scratch-message
";; Present Day, Present Time... 🯅 🯆 🯇 🯈\n")(use-package dashboard
:ensure t
:config
(dashboard-setup-startup-hook)
(setq dashboard-center-content t)
(setq dashboard-banner-logo-title "G A F A N H O T O")
(setq dashboard-startup-banner "~/.emacs.d/grasshopper.png")
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(setq initial-buffer-choice (lambda () (get-buffer "*dashboard*"))))Changing the colors of the gdb cursor/mark/line…
(require 'nadvice)
(defvar gud-overlay
(let ((ov (make-overlay (point-min) (point-min))))
(overlay-put ov 'face
'(:background "#FFB6C1" :foreground "black" :weight bold))
ov)
"Overlay used to highlight the current line in GUD buffers.")
(defun my-gud-highlight (true-file line)
"Highlight the current execution line and recenter the window."
(let ((ov gud-overlay)
(bf (gud-find-file true-file)))
(with-current-buffer bf
(goto-char (point-min))
(forward-line (1- line))
(move-overlay ov (line-beginning-position)
(line-end-position)
(current-buffer))
(when-let ((win (get-buffer-window bf)))
(with-selected-window win
(recenter))))))
(defun my-gud-clear-overlay ()
"Remove the GUD overlay when GDB exits or is killed."
(when (overlayp gud-overlay)
(delete-overlay gud-overlay)))
(advice-add 'gud-display-line :after #'my-gud-highlight)
;; Clean up the overlay when GDB finishes or buffer is killed
(add-hook 'gud-mode-hook
(lambda ()
(add-hook 'kill-buffer-hook #'my-gud-clear-overlay nil t)
(when (process-live-p (get-buffer-process (current-buffer)))
(set-process-sentinel
(get-buffer-process (current-buffer))
(lambda (proc _event)
(unless (process-live-p proc)
(my-gud-clear-overlay)))))))(use-package dired
:ensure nil
:hook
(dired-mode . dired-hide-details-mode))(use-package dired-subtree
:ensure t
:config
(setq dired-subtree-use-backgrounds nil)
(define-key dired-mode-map [tab] 'dired-subtree-toggle))A terminal based document reader and browser.
(use-package w3m
:ensure t)This are just utilities that are useful to me at work.
(when (file-exists-p "~/.emacs.d/elisp/work-lisp.el")
(load-file "~/.emacs.d/elisp/work-lisp.el"))(use-package vertico
:config
(vertico-mode 1)
; Show more candidates
(setq vertico-count 25
read-extended-command-predicate
'command-completion-default-include-p
; Ignore case of file names
read-file-name-completion-ignore-case t
; Ignore case in buffer completion
read-buffer-completion-ignore-case t
; Ignore case in completion
completion-ignore-case t))(use-package vertico-posframe
:config
(vertico-posframe-mode 1)
(setq vertico-posframe-width 90
vertico-posframe-height vertico-count))(use-package corfu
:custom
;; Enable auto completion
(corfu-auto t)
;; Enable cycling for `corfu-next/previous'
(corfu-cycle t)
;; No delay
(corfu-auto-delay 0)
;; Start when this many characters have been typed
(corfu-auto-prefix 2)
;; Short delay
(corfu-popupinfo-delay 0.5)
;; Preselect the prompt
(corfu-preselect 'prompt)
;; Modes to exclude
(global-corfu-modes '((not gud-mode gdb-mode comint-mode) t))
:init
(global-corfu-mode))
;; Do not show a "no match" message when there is no
;; possible match. Simply stop showing.
;; Adding this because a lot of time the "no match"
;; message does not dissapear by itself, and I have to
;; press C-g to remove it.
(setq corfu-quit-no-match t)
(use-package emacs
:init
;; TAB cycle if there are only few candidates
;; (setq completion-cycle-threshold 3)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
(setq tab-always-indent 'complete)
;; Emacs 30 and newer: Disable Ispell completion
;; function. As an alternative,
;; try `cape-dict'.
(setq text-mode-ispell-word-completion nil)
;; Emacs 28 and newer: Hide commands in M-x
;; which do not apply to the current
;; mode. Corfu commands are hidden, since
;; they are not used via M-x. This
;; setting is useful beyond Corfu.
(setq read-extended-command-predicate
#'command-completion-default-include-p))It’s helpful to know what key combos are available whenever I’m typing something!
(use-package which-key
:ensure t
:config (which-key-mode))(use-package marginalia
:bind (:map minibuffer-local-map
("M-A" . marginalia-cycle))
:init
(marginalia-mode))(use-package helpful
:bind (:map custom-bindings-map
("C-h f" . #'helpful-function)
("C-h v" . #'helpful-variable)
("C-h k" . #'helpful-key)
("C-h x" . #'helpful-command)
("C-h d" . #'helpful-at-point)
("C-h c" . #'helpful-callable)))Code snippets to program and other predefined blocks
(use-package yasnippet
:ensure t
:config
(yas-global-mode 1)) (use-package yasnippet-snippets
:ensure t) (use-package haskell-snippets
:defer t)(use-package pdf-tools
:ensure t
:custom (pdf-annot-activate-created-annotations
t "automatically annotate highlights")
:config
(pdf-tools-install)
(add-hook 'pdf-view-mode-hook #'pdf-view-themed-minor-mode))Just some lorem ipsum in your buffer
(use-package lorem-ipsum)Vterm is possibly the best terminal option for emacs. The winning factor over other options is the speed it works really well with minimal configuration.
;; Make sure that cmake, libtool, libtool-bin exists
(use-package vterm
:ensure t
:config
(setopt vterm-tramp-shells '(("ssh" "/bin/bash")
("sshx11" "/bin/bash")
("docker" "/bin/sh")))
)For some reason it was quite difficult to open vterm trough a tramp/dired connection to the sdf server… This for sure due to my lack of knowledge… This patch allows vterm to “just work” on the sdf server.
(defun my-vterm--get-shell-override (orig-fun &rest args)
"Override shell path for sdf.org."
(if (and (ignore-errors (file-remote-p default-directory))
(string-match-p "sdf\\.org" default-directory))
"/usr/pkg/bin/bash"
(apply orig-fun args)))
(advice-add 'vterm--get-shell :around #'my-vterm--get-shell-override)
;; Detect BSD systems via TRAMP and set system-type to avoid iutf8 flag
(defun my-vterm-bsd-compatibility (orig-fun &rest args)
"Detect BSD systems via TRAMP and pretend
we're on berkeley-unix to avoid stty -iutf8."
(let ((system-type (if (and (featurep 'tramp)
(tramp-tramp-file-p default-directory))
(let* ((vec
(tramp-dissect-file-name default-directory))
(uname
(tramp-get-connection-property
vec "uname" "")))
(if (string-match-p "BSD" uname)
'berkeley-unix
system-type))
system-type)))
(apply orig-fun args)))
(advice-add 'vterm :around #'my-vterm-bsd-compatibility)The only problem with vterm is that it does not operate so well by default with emacs. Meaning that there is no directory tracking for example. Another important feature that I would expect by default would be for a shell function that could directly open a file in a buffer on the current emacs session.
(setq vterm-printf-function
"vterm_printf() {
if [ -n \"$TMUX\" ] \\
&& { [ \"${TERM%%-*}\" = \"tmux\" ] \\
|| [ \"${TERM%%-*}\" = \"screen\" ]; }; then
printf \"\\ePtmux;\\e\\e]%s\\007\\e\\\\\" \"$1\"
elif [ \"${TERM%%-*}\" = \"screen\" ]; then
printf \"\\eP\\e]%s\\007\\e\\\\\" \"$1\"
else
printf \"\\e]%s\\e\\\\\" \"$1\"
fi
}")(setq vterm-cmd-function
"vterm_cmd() {
local vterm_elisp
vterm_elisp=\"\"
while [ $# -gt 0 ]; do
vterm_elisp=\"$vterm_elisp\"\"\$(printf '\"%s\" ' \"\$(printf \"%s\" \"\$1\" | sed -e 's|\\\\|\\\\\\\\|g' -e 's|\"|\\\\\"|g')\")\"
shift
done
vterm_printf \"51;E\$vterm_elisp\"
}")(setq vterm-say-function
"say() {
vterm_cmd message \"%s\" \"$*\"
}")(setq vterm-find-file-function
"find_file() {
local localpath tramp_prefix host
localpath=$(realpath \"${@:-.}\")
if [ -n \"$SSH_CONNECTION\" ]; then
if [ -n \"$ORIGINAL_HOST\" ]; then
host=\"$ORIGINAL_HOST\"
else
host=$(hostname -s)
fi
tramp_prefix=\"/sshx11:${USER}@${host}:\"
say \"${tramp_prefix}\"
say \"${tramp_prefix}${localpath}\"
vterm_cmd find-file \"${tramp_prefix}${localpath}\"
else
vterm_cmd find-file \"$localpath\"
fi
}")(setq vterm-config
(concat vterm-printf-function "\n\n"
vterm-cmd-function "\n\n"
vterm-say-function "\n\n"
vterm-find-file-function "\n"))(defun load-remote-vterm-config (&optional path)
"Load the vterm configuration silently on remote vterm shells.
If PATH is provided and non-empty, export ORIGINAL_HOST with that value."
(when (and (derived-mode-p 'vterm-mode)
(file-remote-p default-directory))
;; Disable echo for silent injection.
(vterm-send-string "stty -echo && clear")
(vterm-send-return)
(let ((config vterm-config))
(when (and path (not (string= path "")))
(setq config (concat "export ORIGINAL_HOST=\"" path "\"\n" config)))
(vterm-send-string config)
(vterm-send-return))
(vterm-send-string "stty echo && clear")
(vterm-send-return)
))
(add-hook 'vterm-mode-hook #'load-remote-vterm-config)(add-to-list 'vterm-eval-cmds
'("rename-buffer" rename-buffer))Eshell is a pretty nice terminal. But it needs some tweaks to make it a little bit more comfortable.
(setq eshell-prompt-function
(lambda nil
(concat
(if (string= (eshell/pwd) (getenv "HOME"))
(propertize "~" 'face `(:foreground "#99CCFF"))
(replace-regexp-in-string
(getenv "HOME")
(propertize "~" 'face `(:foreground "#99CCFF"))
(propertize (eshell/pwd) 'face
`(:foreground "#99CCFF"))))
(if (= (user-uid) 0)
(propertize " α " 'face `(:foreground "#FF6666"))
(propertize " λ " 'face `(:foreground "#A6E22E"))))))
(setq eshell-highlight-prompt nil)(defalias 'open 'find-file-other-window)
(defalias 'clean 'eshell/clear-scrollback) (defun eshell-other-window ()
"Create or visit an eshell buffer."
(interactive)
(if (not (get-buffer "*eshell*"))
(progn
(split-window-sensibly (selected-window))
(other-window 1)
(eshell))
(switch-to-buffer-other-window "*eshell*")))
(global-set-key (kbd "<C-escape>") 'eshell-other-window)(use-package magit
:ensure t
:bind (("C-c m" . magit-status)))(use-package markdown-mode
:defer t)Sometimes I do edit the cron tab. It is helpful to make some jobs run during the night.
(defun crontab-e ()
"Run `crontab -e' in a emacs buffer."
(interactive)
(with-editor-async-shell-command "crontab -e"))(use-package erc
:ensure t)bib files are not easy to manage on their own, not because of complexity, but because editing them one by one can become quite a tedious task. For that reason I started trying to use ebib as my bibliography data base.
(use-package ebib
:ensure t
:config
(setq ebib-preload-bib-files
(directory-files "~/Org/bib" t "\\.bib$"))It is helpful to set this variable to nil, otherwise emacs will attempt to use an external program called xpdf to open the file associated with your paper. If you set it to nil it will open all files with the default emacs viewer.
(setq ebib-file-associations nil))(defun lock-screen ()
"Lock screen using (zone) and xtrlock
calls M-x zone on all frames and runs xtrlock"
(interactive)
(save-excursion
(set-process-sentinel
(start-process "xtrlock" nil "xtrlock")
#'(lambda (process event)
(zone-leave-me-alone)))
(zone-when-idle 1)))vimdiff is a really good tool to diff two files and observe what changed. Emacs by default can create diffs, but it does not create a side by side diff like vimdiff does.
(use-package vdiff
:ensure t)I am horrible at natural languages, and since I have to use them daily to communicate, I desperately require tools to aid me. Emacs has a couple of packages for spelling and syntax.
(use-package flyspell
:ensure t
:config
(add-hook 'text-mode-hook 'flyspell-mode))(use-package ispell
:ensure t
:config
(setq ispell-program-name "aspell")
(setq ispell-dictionary "english")
(global-set-key (kbd "C-<f8>")
'flyspell-check-previous-highlighted-word))(use-package org
:ensure nil
:defer t
:hook (org-mode . writeroom-mode)
:config
;; Start up any org file with pretty latex images
(setq org-startup-with-latex-preview t)
(plist-put org-format-latex-options :scale 1.8)
;; All images showing
(setq org-startup-with-inline-images t)
;; Org tempo templates
(require 'org-tempo)
(setq org-structure-template-alist
'(("el" . "src emacs-lisp")
("sh" . "src shell")
("py" . "src python :results output :exports both")
("pys" . "src python :session :results output :exports both")
("C" . "src C :results output :exports both")
("ft" . "src fortran")
("cl" . "src lisp")
("hs" . "src haskell :results value :exports both")
("pl" . "src prolog :results value :exports both")
("js" . "src js :results output")
("r" . "src R :results output :exports both")
))
;; Babel and the polyglot configuration
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(shell . t)
(python . t)
(C . t)
(haskell . t)
(js . t)
(prolog . t)
(R . t)
(fortran . t)
))
)(use-package org-agenda
:ensure nil
:config
(global-set-key (kbd "C-c a") 'org-agenda)
(custom-set-variables
'(org-directory "~/Org/agenda")
'(org-agenda-files (list org-directory))))(use-package org-appear
:commands (org-appear-mode)
:hook (org-mode . org-appear-mode)
:config
; Must be activated for org-appear to work
(setq org-hide-emphasis-markers t)
; Show bold, italics, verbatim, etc.
(setq org-appear-autoemphasis t
; Show links
org-appear-autolinks t
; Show sub- and superscripts
org-appear-autosubmarkers t))(use-package org-fragtog
:after org
:hook (org-mode . org-fragtog-mode))(setq org-image-actual-width nil)Org mode by default does not necessarily look ugly, but I do prefer to use other bullet icons.
(use-package org-bullets
:ensure t
:init
(setq org-bullets-bullet-list
'("ꖜ" "•" "❉" "⨿" "ᖷ"))
(setq org-todo-keywords
'((sequence "☛ TODO(t)" "➤ NEXT(n)" "⚗ MEETING(m)"
"|" "✔ DONE(d)" "⮼ BACKLOG(b)")
(sequence "∞ WAITING(w)" "|" "✘ CANCELED(c)")
(sequence "∞ READING(r)"
"∞ VIEWING(v)"
"𝅘𝅥𝅮 LISTENING(l)"
"░ WATCHLIST(a)"
"|" "◤ FINISHED(f)")))
(setq org-todo-keyword-faces
'(("✔ DONE" . (:foreground "gray"))))
:config
(add-hook 'org-mode-hook
(lambda () (org-bullets-mode 1)))
(setq org-ellipsis "▼"))I do enjoy the whole habit of doing pomodoros. It helps me maintain some focus while working.
(use-package org-pomodoro
:ensure t
:commands (org-pomodoro)
:config
(setq org-pomodoro-play-sounds nil)
(setq alert-user-configuration (quote
((((:category . "org-pomodoro"))
libnotify nil)))))I was not able to personalise pomodoro urgency label, and neither the app and icon information. For now this is small hack makes notifications appear even when I am using my emacs on full-screen and it also shows the icon and application name correctly.
(with-eval-after-load 'org-pomodoro
(defun gmp-pomodoro-notification (title message &optional sound)
(require 'notifications)
(notifications-notify
:title title
:body message
:urgency 'critical
:app-name "emacs"
:app-icon "/usr/share/icons/hicolor/scalable/apps/emacs.svg"))
(advice-add 'org-pomodoro-notify :override #'gmp-pomodoro-notification))doing presentations with org and reveal.js
(use-package ox-reveal
:ensure ox-reveal
:config
(setq org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")
(setq org-reveal-mathjax t))(use-package org-roam
:ensure t
:custom
(org-roam-directory (file-truename "~/Org/roam"))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
;; Dailies
("C-c n j" . org-roam-dailies-capture-today))
:config
;; If you're using a vertical completion framework,
;; you might want a more informative completion interface
(setq org-roam-node-display-template
(concat "${title:*} "
(propertize "${tags:10}" 'face 'org-tag)))
(org-roam-db-autosync-mode)
;; If using org-roam-protocol
(require 'org-roam-protocol))(use-package org-roam-ui
:after org-roam
: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))(setq org-confirm-babel-evaluate nil) (use-package lsp-mode
:ensure t
:init
(setq lsp-keymap-prefix "C-c l")
:hook
((web-mode . lsp)
(lsp-mode . lsp-enable-which-key-integration))
:commands lsp
:config
(lsp-register-client
(make-lsp-client
:new-connection
(lsp-tramp-connection "clangd")
:major-modes '(c-mode c++-mode)
:remote? t
:server-id 'clangd-remote)))(use-package lsp-ui
:commands lsp-ui-mode
:config
(setq lsp-ui-doc-enable nil)
(setq lsp-ui-doc-header t)
(setq lsp-ui-doc-include-signature t)
(setq lsp-ui-doc-border (face-foreground 'default))
(setq lsp-ui-sideline-show-code-actions t)
(setq lsp-ui-sideline-delay 0.05))(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((c++-mode c-mode) "/apps/clang/latest/bin/clangd")))(load-file "~/.emacs.d/elisp/llvm-ir-mode-get.el")
(llvm-mode-get)
(when (file-directory-p "~/.emacs.d/llvm-mode/")
(load "~/.emacs.d/llvm-mode/llvm-mode.el")
(load "~/.emacs.d/llvm-mode/llvm-mir-mode.el")
(load "~/.emacs.d/llvm-mode/tablegen-mode.el"))(use-package cmake-mode
:ensure t)(use-package lean4-mode
:ensure lean4-mode
:straight (lean4-mode
:type git
:host github
:repo "leanprover/lean4-mode"
:files ("*.el" "data"))
:commands (lean4-mode))(use-package rust-mode
:ensure t)I use Haskell mode to program, It is pretty well documented.
(let ((my-ghcup-path (expand-file-name "~/.ghcup/bin")))
(setenv "PATH" (concat my-ghcup-path ":" (getenv "PATH")))
(add-to-list 'exec-path my-ghcup-path)) (use-package haskell-mode
:defer t
:hook (haskell-mode . haskell-doc-mode)
:config
(custom-set-variables
'(haskell-tags-on-save t)
'(tags-revert-without-query 1)
'(haskell-process-suggest-remove-import-lines t)
'(haskell-process-auto-import-loaded-modules t)
'(haskell-process-log t)
'(haskell-process-type 'stack-ghci)
)
(define-key haskell-mode-map (kbd "C-c C-l")
'haskell-process-load-or-reload)
)I use haskell mainly, but I believe it should be interesting to also be proficient in ocaml.
(use-package tuareg
:ensure t
:config
(add-to-list 'exec-path "~/.opam/default/bin"))Some extra configuration is needed to make this work properly…
(use-package utop
:ensure t
:config
(add-hook 'tuareg-mode-hook #'utop-minor-mode)
(setq utop-command "opam config exec -- dune utop . -- -emacs"))(use-package racket-mode
:ensure t)Prolog is a very interesting programming language, at least for me. A very good document to know more about this system is: The Power Of Prolog written and maintained by Markus Triska. Previously I was using an emacs prolog mode suggested by Markus and developed by Stefan Bruda. This mode stopped working for me on the second week of august of 2024. Since it is an old major mode, and I don’t believe it is or will be maintained I am switching back to the default prolog major mode.
(setq auto-mode-alist (append '(("\\.pl$" . prolog-mode)
("\\.pro$" . prolog-mode))
auto-mode-alist))Using SWI as the prolog system, at some point I would like to also be able to use scryer, but for now swi is probably one of the best options.
(when (executable-find "swipl")
(message "SWI-Prolog exists on path, using it!")
(setq prolog-system 'swi
prolog-program-switches
'((swi ("-G128M" "-T128M" "-L128M" "-O"))
(t nil))))ediprolog for prolog evaluation on all buffers! It is quite useful to play around with prolog systems in different contexts. In way it can convert any emacs buffer into a literate programming buffer.
(use-package ediprolog
:ensure t
:config
;; Scryer prolog is a pretty nice prolog system
(setq ediprolog-system 'swi)
(setq ediprolog-program (executable-find "swipl"))
;; (when (executable-find "scryer-prolog")
;; (setq ediprolog-system 'scryer)
;; (setq ediprolog-program (executable-find "scryer-prolog")))
(global-set-key [f10] 'ediprolog-dwim))show term
(when (file-exists-p "~/scryer-prolog/tools/showterm.el")
(load "~/scryer-prolog/tools/showterm.el")
(global-set-key [f12] 'showterm))(use-package ob-prolog
:ensure t)Python mode for python files
(use-package python
:interpreter ("python3" . python-mode)
:ensure t
:config
(setq python-shell-interpreter "python3"))(use-package pyvenv
:ensure t)(use-package ein
:ensure t)(use-package ess
:ensure t)(use-package typescript-mode
:ensure t
:mode "\\.ts\\'"
:hook (typescript-mode . lsp-deferred))(use-package js2-mode
:ensure t
:mode (("\\.js\\'" . js2-mode)
("\\.cjs\\'" . js2-mode))
:hook (js2-mode . lsp-deferred))
(add-hook 'javascript-mode #'js2-mode)(when
(file-directory-p
"~/.local/share/SuperCollider/downloaded-quarks/scel/el/")
(add-to-list
'load-path
"~/.local/share/SuperCollider/downloaded-quarks/scel/el/")
(require 'sclang))(use-package glsl-mode
:ensure t
:mode ("\\.fs\\'" "\\.vs\\'" "\\.glsl\\'"))(use-package cobol-mode
:ensure t)(use-package nasm-mode
:ensure t
:config
(add-to-list 'auto-mode-alist '("\\.\\(asm\\|s\\|S\\)$" . nasm-mode)))(define-minor-mode custom-bindings-mode
"A mode that activates custom keybindings."
:init-value t
:keymap custom-bindings-map)