Mi configuración literaria de GNU Emacs
Índice
Inicialización
Todo lo que necesita ser evaluado al momento en que se lanza Emacs
Comportamiento General
Opciones regulares, todas seleccionadas para una experiencia más optima computando con GNU Emacs.
(save-place-mode 1)
(pixel-scroll-precision-mode 1)
(recentf-mode 1)
(setq recentf-exclude
'("straight/build/"
"eln-cache/"
"autosaves/"
"tmp/"
".cache/"))
(setq enable-recursive-minibuffers t)
(global-display-line-numbers-mode 1)
(setq display-line-numbers-type 'relative)
Tabs de 8 caracteres, la única forma valida de estilizar el código.
(setq-default tab-width 8)
(setq-default indent-tabs-mode t)
Archivos y Backups
Por defecto Emacs tira su basura (backups y auto saves) por todos lados. Le pedimos que pare.
(setq backup-directory-alist
`(("." . ,(expand-file-name "backups" user-emacs-directory))))
(setq auto-save-file-name-transforms
`((".*" ,(expand-file-name "auto-saves/" user-emacs-directory) t)))
(setq create-lockfiles nil)
Apariencia
Emacs por defecto parece hecho en los 90's (porque lo es). Aquí se soluciona eso.
Opciones básicas
Lo mínimo para que Emacs se vea más limpio.
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(fringe-mode 0)
(setq-default cursor-type '(bar . 2))
(blink-cursor-mode 0)
(setq-default truncate-lines t)
(setq-default word-wrap nil)
(setq use-file-dialog nil)
(setq use-dialog-box nil)
(setq pop-up-windows nil)
(setq indicate-empty-lines nil)
(setq cursor-in-non-selected-windows nil)
Icons
Instalar all-the-icons y su integración con dired, no tiene mucha ciencia
(use-package all-the-icons)
(use-package all-the-icons-dired
:hook (dired-mode . all-the-icons-dired-mode))
Mode-line
No tengo.
(setq-default mode-line-format nil)
N Λ N O theme
Cargamos el tema N Λ N O con nuestra propia paleta de colores generada con matugen.
(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
(require 'nano-reload-theme)
(use-package nano-theme
:straight (nano-theme :type git :host github :repo "rougier/nano-theme")
:init
(load (expand-file-name "nano-theme-colors.el" user-emacs-directory) t)
:config
(nano-reload-theme))
Faces personalizadas
Personalizar las faces de Emacs independientemente del tema. Todo esto corre con un hook que se configura mas tarde.
(defun my/apply-custom-faces ()
(let ((ln-color (face-foreground 'line-number nil t)))
(set-face-attribute 'org-document-title nil
:height 1.4
:foreground (face-foreground 'default nil t)
:inherit 'default)
;; line numbers
(set-face-attribute 'line-number nil
:background (face-background 'default nil t))
(set-face-attribute 'line-number-current-line nil
:background (face-background 'default nil t))
(set-face-attribute 'line-number-current-line nil
:foreground (face-foreground 'default) :weight 'bold)
;; headings
(set-face-attribute 'org-level-1 nil
:weight 'bold
:height 1.25)
(set-face-attribute 'org-level-2 nil
:height 1.15)
(set-face-attribute 'org-level-3 nil
:height 1.10)
;; monospace
(set-face-attribute 'org-block nil
:inherit 'fixed-pitch)
(set-face-attribute 'org-code nil
:inherit 'fixed-pitch)
(set-face-attribute 'org-table nil
:inherit 'fixed-pitch)
(set-face-attribute 'region nil
:inverse-video t))
(set-face-attribute 'italic nil
:slant 'italic))
Fuentes
Las hermosas fuentes que estas viendo ahora mismo (Si estas usando esta configuración),
Iosevka Fixed y Iosevka Etoile.
Función my/font-setup
Esta función corre con el mismo hook que la anterior. Esta se encarga de configurar nuestras fuentes.
(defun my/font-setup ()
;; fonts
(set-face-attribute 'default nil
:family "Iosevka Fixed"
:height 140)
(set-face-attribute 'fixed-pitch nil
:family "Iosevka Fixed"
:height 140)
(set-face-attribute 'variable-pitch nil
:family "Iosevka Etoile"
:height 140)
;; italics
(set-face-attribute 'font-lock-comment-face nil
:slant 'italic)
(set-face-attribute 'font-lock-keyword-face nil
:slant 'italic)
(set-face-attribute 'org-meta-line nil
:inherit 'fixed-pitch)
(set-face-attribute 'org-special-keyword nil
:inherit 'fixed-pitch)
(set-face-attribute 'org-property-value nil
:inherit 'fixed-pitch))
Otras cosas
Unas cuantas cosas con relación a las fuentes, como el paquete mixed-pitch.
(add-to-list 'default-frame-alist
'(font . "Iosevka Fixed"))
(use-package mixed-pitch
:hook (org-mode . mixed-pitch-mode)
:custom
(mixed-pitch-set-height nil))
El famoso hook (my/frame-setup)
Este es el famoso del que hablaba. my/font-setup y my/apply-custom-faces son evaluadas cada vez
que se crea un frame (Una ventana de Emacs al nivel del OS)
(defun my/setup-frame (frame)
(with-selected-frame frame
(my/font-setup)
(my/apply-custom-faces)))
(add-hook 'after-make-frame-functions #'my/setup-frame)
(unless (daemonp)
(my/setup-frame (selected-frame)))
Edición
Opciones que cambian la forma de interactuar con el buffer de texto
Volverse EVIL
EVIL, Extensible Vi Layer, por sus siglas en Ingles.
Ningún hombre es perfecto. Oh! glorioso RMS perdoname, porque he caído en la tentación de la edición modal.
Seriamente, esta parte es bastante sencilla. Solo instala evil, evil-collection y configura unas cuantas
opciones.
(use-package evil
:init
(setq evil-want-integration t
evil-want-keybinding nil
evil-vsplit-window-right t
evil-split-window-below t
evil-mode-line-format nil)
:config
(evil-set-undo-system 'undo-redo)
(evil-mode 1))
(use-package evil-collection
:after evil
:config
(evil-collection-init))
Cursors multiples
Si un cursor es bueno, que es mejor?
(use-package multiple-cursors)
Edición structural
Cuando editas lenguajes basados en S-expressions, es bastante útil que tu editor lo sepa
(use-package paredit
:hook ((scheme-mode . paredit-mode) (emacs-lisp-mode . paredit-mode)))
Keybinds
Keybinds personales usando general.el y which-key.
setup de general.el
Instalación y configuración usando EVIL.
(use-package general
:config
(general-evil-setup)
(general-create-definer i/leader-keys
:states '(normal insert visual emacs)
:keymaps 'override
:prefix "SPC"
:global-prefix "M-SPC"))
Which-key
Muestra keybinds después de 0.5 segundos.
(use-package which-key
:init
(which-key-mode 1)
:config
(setq which-key-idle-delay 0.5))
Keybinds generales (eh, eh, entiendes?)
Configurando mis keybinds con general.el.
Misceláneo
Las que no cabían en otro lugar.
(i/leader-keys
"TAB TAB" '(comment-line :wk "comment line")
"SPC" '(execute-extended-command :wk "M-x")
"/" '(consult-line :wk "search buffer")
"c" '(compile :wk "compile"))
Archivos
Keybinds relacionadas con archivos.
Prefijo: "f"
(i/leader-keys
"f" '(:ignore t :wk "files")
"fr" '(consult-recent-file :wk "recent files")
"fd" '((lambda ()
(interactive)
(find-file "~/.emacs.d/config.org"))
:wk "edit config.org")
"ff" '(find-file :wk "find files")
"fj" '((lambda ()
(interactive)
(dired-jump))
:wk "open current directory in dired"))
Evaluación
Evaluar cosas.
Prefijo: "e"
(i/leader-keys
"e" '(:ignore t :wk "eval")
"eb" '(eval-buffer :wk "eval buffer")
"ed" '(eval-defun :wk "eval defun containing or after point")
"ee" '(eval-expression :wk "eval expression")
"er" '(eval-region :wk "eval region")
"ec" '(my/reload-config :wk "eval init.el"))
Ventanas
Keybinds relacionadas con ventanas de Emacs (splits).
Prefijo: "w"
(i/leader-keys
"w" '(:ignore t :wk "operate on windows")
"wh" '(windmove-left :wk "left")
"wj" '(windmove-down :wk "down")
"wk" '(windmove-up :wk "up")
"wl" '(windmove-right :wk "right")
"wv" '(split-window-right :wk "vertical split")
"ws" '(split-window-below :wk "horizontal split")
"wd" '(delete-window :wk "delete window")
"wo" '(delete-other-windows :wk "only window"))
Buffers
Keybinds relacionadas con buffers
Prefijo: "b"
(i/leader-keys
"b" '(:ignore t :wk "buffer")
"bb" '(consult-buffer :wk "switch buffer")
"bk" '(kill-buffer :wk "kill buffer")
"bn" '(next-buffer :wk "next buffer")
"bp" '(previous-buffer :wk "previous buffer")
"br" '(revert-buffer :wk "reload buffer"))
Ayuda
funciones "describe-xyz". Emacs es el editor auto-documentado después de todo.
Prefijo: "h"
(i/leader-keys
"h" '(:ignore t :wk "help")
"hf" '(describe-function :wk "describe function")
"hv" '(describe-variable :wk "describe variable"))
Alternar
Alterna cosas.
Prefijo: "t"
(i/leader-keys
"t" '(:ignore t :wk "toggle")
"tl" '(display-line-numbers-mode :wk "toggle line numbers")
"tt" '(toggle-truncate-lines :wk "truncate lines")
"tv" '(vterm-mode :wk "toggle vterm"))
Soporte de lenguajes
Language specific features. Configuraciones especificas a un lenguaje de programación
Bajo nivel
C
El rey de los lenguajes. Solo hay que seleccionar el estilo del kernel de Linux
(add-hook 'c-mode-hook
(lambda ()
(c-set-style "linux")))
Odin
Un lenguaje más de nicho que C. Modo:
(use-package odin-mode
:straight (:host github
:repo "mattt-b/odin-mode")
:mode "\\.odin\\'")
Estilo:
(add-hook 'odin-mode-hook
(lambda ()
(setq-local tab-width 8)
(setq-local js-indent-level 8)
(setq-local indent-tabs-mode t)))
Lisp-like
Geiser
Herramienta para gestionar REPLs dentro de Emacs
(use-package geiser
:config
(setq geiser-default-implementation 'guile))
Guile scheme
Integración de Guile en Geiser, Una implementación libre de scheme. Usado en Guix.
(use-package geiser-guile
:after geiser)
Indent options
Lisp es la única clase de lenguaje al que le acepto un estilo de 2 espacios.
(add-hook 'scheme-mode-hook
(lambda ()
(setq-local indent-tabs-mode nil)
(setq-local tab-width 2)
(setq-local lisp-body-indent 2)
(setq-local lisp-indent-offset 2)))
Proyectos y terminales
Projectile
Administrador de proyectos.
(use-package projectile
:ensure t
:init
(setq projectile-project-search-path '("~/programming/"))
:config
(projectile-mode 1))
Magit
Un client de git para interacción fácil y eficiente.
(use-package magit
:config
(i/leader-keys
"g" '(magit-status t :wk "git")))
Vterm & Vterm-Toggle
La terminal vterm y vterm-toggle para acceso rápido. vterm-toggle alterna un buffer the vterm un tercio del tamaño de la pantalla.
(use-package vterm)
(use-package vterm-toggle
:after vterm
:config
(setq vterm-toggle-fullscreen-p nil)
(add-to-list 'display-buffer-alist
'((lambda (buffer-or-name _)
(let ((buffer (get-buffer buffer-or-name)))
(with-current-buffer buffer
(or (equal major-mode 'vterm-mode)
(string-prefix-p vterm-buffer-name (buffer-name buffer))))))
(display-buffer-reuse-window display-buffer-at-bottom)
;;(display-buffer-reuse-window display-buffer-in-direction)
;;display-buffer-in-direction/direction/dedicated is added in emacs27
;;(direction . bottom)
;;(dedicated . t) ;dedicated is supported in emacs27
(reusable-frames . visible)
(window-height . 0.3))))
Org mode
De las mejores funciones de Emacs, solo superada por el potencial de decir "Use Emacs btw."
Núcleo
Cosas indispensables para como escribo Org.
(require 'org-tempo)
(use-package toc-org
:config
(add-hook 'org-mode-hook #'toc-org-mode))
Apariencia
Mejorar la apariencia de Org.
Org bullets
Crea decoraciones bonitas para los headers.
(use-package org-bullets
:hook (org-mode . org-bullets-mode)
:config
(setq org-bullets-bullet-list '("★" "☆" "✦" "✧")))
Hide markup
Esconde la sintaxis de org. No mucho que decir.
(use-package org-appear
:ensure t
:hook (org-mode . org-appear-mode)
:init
(setq org-hide-emphasis-markers t
org-link-descriptive t
org-pretty-entities t))
Agenda
La forma en que me (org)anizo.
(setq org-directory (expand-file-name "~/roam/"))
(setq org-agenda-files (list (expand-file-name "~/roam/agenda.org")
(expand-file-name "~/roam/todos.org")))
(setq org-log-done 'time)
(setq org-agenda-custom-commands
'(("s" "Estar sentado" tags-todo "sentado")
("m" "Moverme" tags-todo "movimiento")
("d" "Agenda del día" agenda "")))
(setq org-agenda-timegrid-use-ampm t)
Org roam
Forma no jerárquica de organizar mis notas.
(use-package org-roam
:config
(unless (file-exists-p (expand-file-name "~/roam"))
(make-directory (expand-file-name "~/roam")))
(setq org-roam-directory (file-truename "~/roam"))
(org-roam-db-autosync-mode))
Keybinds
Keybinds usando general.el (Véase la sección "Keybinds")
(i/leader-keys
"m" '(:ignore t :wk "org")
"ma" '(org-agenda :wk "agenda")
"ms" '(org-time-stamp :wk "time stamp")
"me" '(org-export-dispatch :wk "export dispatch")
"mi" '(org-toggle-item :wk "toggle item")
"mt" '(org-todo :wk "todo")
"mb" '(org-babel-tangle :wk "tangle")
"mT" '(org-todo-list :wk "todo list"))
Completado
Hacer que Emacs te ayude a escribir.
Mini-buffer
Completado
Paquetes núcleo para el completado en el minibuffer
- Vertico
Provee la UI
(use-package vertico :init (vertico-mode 1)) - Savehist
Guarda la historia a través de múltiple secciones
(use-package savehist :init (savehist-mode 1)) - Orderless
Hace las opciones más flexibles en el momento del completado
(use-package orderless :custom (completion-styles '(orderless basic)) (completion-category-defaults nil) (completion-category-overrides '((file (styles partial-completion)))))
Anotaciones
Información adicional
Búsqueda y navegación
Commandos que se integran con la UI de completado
In-buffer completion
Corfu hace de backend y cape de fronted.
(use-package corfu
:ensure t
:init
(global-corfu-mode)
:custom
(corfu-auto t)
(corfu-auto-delay 0.2)
(corfu-auto-prefix 1)
(corfu-cycle t))
(use-package cape
:ensure t
:init
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-file))
(defun my/corfu-capf-setup ()
(setq-local completion-at-point-functions
(list
(cape-capf-super
#'eglot-completion-at-point
#'cape-dabbrev
#'cape-file))))
(add-hook 'eglot-managed-mode-hook #'my/corfu-capf-setup)
Prose
Cosas para escribir lenguaje natural.
Corrección ortográfica
parra ezkribir vien.
Configura hunspell con Ingles y Español.
(with-eval-after-load "ispell"
;; Configure `LANG`, otherwise ispell.el cannot find a 'default
;; dictionary' even though multiple dictionaries will be configured
;; in next line.
(setenv "LANG" "es_PA")
(setq ispell-program-name "hunspell")
(setq ispell-dictionary "en_US,es_PA")
(ispell-set-spellchecker-params)
(ispell-hunspell-add-multi-dic "en_US,es_PA")
(setq ispell-personal-dictionary "~/.hunspell_personal")
(unless (file-exists-p ispell-personal-dictionary)
(write-region "" nil ispell-personal-dictionary nil 0)))
(add-hook 'text-mode-hook #'flyspell-mode)
Utilidades
Cosas misceláneas.
Funciones
Funciones de conveniencia para mí.
(defun my/reload-config ()
(interactive)
(mapc #'disable-theme custom-enabled-themes)
(load-file user-init-file)
(run-hook-with-args 'after-make-frame-functions
(selected-frame)))
Paquetes
Paquetes que no caben en ningún otro lado.
(use-package simple-httpd
:ensure t)
(use-package htmlize)