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)))

Misc

Qml

Lenguaje declarativo usado con QT. Yo lo uso con Quickshell.

(use-package qml-mode)

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

  • Marginalia
    (use-package marginalia
      :after vertico
      :init
      (marginalia-mode 1))
    
  • Nerd Icons Completion
    (use-package nerd-icons-completion
      :after marginalia
      :config
      (nerd-icons-completion-mode)
      (add-hook 'marginalia-mode-hook
                #'nerd-icons-completion-marginalia-setup))
    

Búsqueda y navegación

Commandos que se integran con la UI de completado

  • Consult

    Paquete de comandos de Emacs mejorados para usar nuestra UI

    (use-package consult
      :custom
      (consult-preview-key 'any))
    

Actions

Acciones contextuales.

  • Embark

    Acciones contextuales para candidatos completos.

    (use-package embark
      :bind
      (("C-." . embark-act)
       ("M-." . embark-dwim)))
    
  • Embark Consult

    Integración entere Embark y Consult

    (use-package embark-consult
      :after (embark consult))
    

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)

Created: 2026-07-26 Sun 21:01