;;; init.el --- Minimal Emacs Config for GPUL Talk  -*- lexical-binding: t; -*-
 
;;; Commentary:
;; Built from the talk's org-mode notes via org-babel-tangle.
 
;;; Code:

Qué es Emacs?

Emacs es un editor de texto extensible, personalizable, auto-documentado y en tiempo real

Pero, qué significa esto en la práctica?
Emacs no es solo un editor: es una máquina Lisp con interfaz gráfica que puedes moldear a tu gusto.

Todo en Emacs es:

  • Un comando
  • Un buffer
  • Una función

Por qué la gente usa Emacs

  • Longevidad: configuraciones de hace décadas siguen funcionando
  • Hackabilidad: todo es personalizable
  • Un entorno para todo: edición, notas, git, archivos, terminal…

El modelo daemon/client

Emacs puede ejecutarse como un daemon en segundo plano. Te conectas a él con emacsclient:

emacs --daemon          # Iniciar el daemon
emacsclient -c          # Abrir una nueva ventana gráfica conectada al daemon
emacsclient -t          # Abrir en terminal
emacsclient FILE        # Abrir un archivo en una ventana existente
  • Inicio instantáneo: el daemon ya está corriendo, las ventanas abren al momento
  • Estado compartido: todas las ventanas comparten buffers, historial, etc.
  • Sesión persistente: cierras una ventana, tu trabajo sigue ahí

Puedes añadir emacs --daemon al inicio del sistema y usar emacsclient como $EDITOR.

Cómo hablar con Emacs

Las teclas invocan funciones, no acciones.
M-x es el prompt para llamar funciones.
Los atajos de teclado son simplemente accesos directos a funciones.

“No estás pulsando teclas. Estás invocando funciones.”

TeclaComandoDescripción
M-xexecute-extended-commandLlamar cualquier función por nombre
C-gkeyboard-quitCancelar / pánico universal
C-hhelp-commandSistema de ayuda
C-x(prefijo)Comandos globales del sistema

El sistema de ayuda

TeclaComandoDescripción
C-h kdescribe-key¿Qué hace esta tecla?
C-h fdescribe-functionDocumentación de una función
C-h vdescribe-variableDocumentación de una variable
C-h mdescribe-mode¿En qué modo estoy? ¿Qué teclas funcionan?
C-h bdescribe-bindingsTodos los atajos del buffer actual
C-h aapropos-commandBuscar comandos por palabra clave

“Emacs es auto-documentado. Solo tienes que aprender a hacerle preguntas.”

Buffers, ventanas y frames

TeclaComandoDescripción
C-x bswitch-to-bufferCambiar de buffer
C-x kkill-bufferCerrar buffer
C-x 2split-window-belowDividir horizontalmente
C-x 3split-window-rightDividir verticalmente
C-x 0delete-windowCerrar ventana actual
C-x 1delete-other-windowsQuedarse solo con esta
C-x oother-windowMoverse a la siguiente

Emacs no tiene pestañas. Tiene buffers y vistas de buffers.

Dónde va el código Lisp?

Tu archivo principal de configuración es ~/.emacs.d/init.el, que se carga al iniciar Emacs.

~/.emacs.d/init.el       # Configuración principal
~/.emacs.d/early-init.el # Se ejecuta antes de init.el (para UI, GC, etc.)

No hace falta reiniciar Emacs. Puedes ejecutar código Lisp en vivo:

Tecla/ComandoQué hace
C-x C-eEvaluar expresión antes del cursor
M-x eval-bufferEvaluar todo el buffer
M-x eval-regionEvaluar la región seleccionada
M-:Evaluar expresión en el minibuffer
M-x ielmModo interactivo de Emacs Lisp (REPL)

.dir-locals.el - Configuración por directorio

Coloca un archivo .dir-locals.el en cualquier directorio para establecer variables solo para ese proyecto:

 
;; .dir-locals.el
((nil . ((indent-tabs-mode . nil)
         (fill-column . 80)))
 (python-mode . ((python-indent-offset . 2))))

Útil para: indentación por proyecto, estilos de código diferentes por repositorio, estándares de equipo.

Lo básico de Lisp

;; Esto es un comentario
 
;; Establecer una variable
(setq nombre-de-variable valor)
 
;; Llamar a una función
(nombre-de-función arg1 arg2)
 
;; Una lista (estructura de datos)
'(item1 item2 item3)
 
;; Definir una función
(defun mi-función (arg)
  "Cadena de documentación."
  (hacer-algo arg))

setq vs modos

;; setq establece una variable
(setq inhibit-startup-message t)
 
;; Un modo es una función, llámala con -1 para desactivar, 1 para activar
(tool-bar-mode -1)
(global-display-line-numbers-mode 1)

Primera configuración: Limpiar la interfaz

Empezamos con un Emacs limpio (emacs -q) y quitamos el ruido visual:

;; Remove startup screen
(setq inhibit-startup-message t)
 
;; Remove UI elements
(scroll-bar-mode -1)        ; No scrollbar
(tool-bar-mode -1)          ; No toolbar
(tooltip-mode -1)           ; No tooltips
(menu-bar-mode -1)          ; No menu bar
 
;; Give some breathing room
(set-fringe-mode 10)
 
;; Visual bell instead of sound
(setq visible-bell t)

Números de línea

;; Show column number in modeline
(column-number-mode)
 
;; Show line numbers
(global-display-line-numbers-mode t)
 
;; Disable line numbers for certain modes
(dolist (mode '(org-mode-hook
                term-mode-hook
                shell-mode-hook
                eshell-mode-hook))
  (add-hook mode (lambda () (display-line-numbers-mode 0))))

Gestión de paquetes

Emacs tiene un gestor de paquetes integrado. Hay que decirle dónde encontrar paquetes:

;; Add package repositories
(setq package-archives
      '(("melpa" . "https://melpa.org/packages/")
        ("org" . "https://orgmode.org/elpa/")
        ("nongnu" . "https://elpa.nongnu.org/nongnu/")
        ("elpa" . "https://elpa.gnu.org/packages/")))
 
;; Initialize the package system
(package-initialize)

use-package: Configuración declarativa

use-package es una macro que hace la configuración de paquetes más limpia:

;; Bootstrap use-package
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
(require 'use-package-ensure)
(setq use-package-always-ensure t)
(eval-when-compile (require 'use-package))

Sintaxis básica:

(use-package nombre-del-paquete
  :ensure t                          ; Instalar si no está presente
  :defer t                           ; Carga diferida
  :init (código-antes-de-cargar)     ; Se ejecuta antes de cargar
  :config (código-después-de-cargar) ; Se ejecuta después de cargar
  :bind ("C-x g" . algún-comando)   ; Establecer atajo de teclado
  :hook (algún-modo . modo-paquete) ; Activar en ciertos modos
  :custom (alguna-opción "valor"))  ; Establecer variables custom

No estás configurando tu editor. Lo estás programando.

Evil-mode

Atajos de teclado de Vim en Emacs, lo mejor de los dos mundos:

(use-package evil
  :ensure t
  :init
  (setq evil-want-keybinding nil)    ; For evil-collection
  :config
  (evil-mode 1))
 
;; Evil bindings for many Emacs modes
(use-package evil-collection
  :ensure t
  :after evil
  :config
  (evil-collection-init))

Emacs no es dogmático. Tú construyes tu propio editor.

Tema, modeline y fuentes

Tema

;; Theme
(use-package modus-themes
  :ensure t
  :init
  (setq modus-themes-italic-constructs t
        modus-themes-bold-constructs t
        modus-themes-mixed-fonts t
        modus-themes-org-blocks 'gray-background)
  :config
  (load-theme 'modus-vivendi :no-confirm))

Otros temas populares: doom-themes, gruvbox-theme, catppuccin-theme, ef-themes

Modeline

;; Modeline
(use-package doom-modeline
  :ensure t
  :init (doom-modeline-mode 1)
  :custom (doom-modeline-height 28))
 
(use-package nerd-icons
  :ensure t)

Font

;; Fonts
(set-face-attribute 'default nil
                    :font "SauceCodePro Nerd Font"
                    :height 110)
 
(set-face-attribute 'variable-pitch nil
                    :font "Noto Sans"
                    :height 110
                    :weight 'regular)

Completado en el minibuffer

Aquí es donde Emacs se vuelve mucho más usable. El minibuffer es donde escribes comandos, nombres de archivo, etc.

Vertico

;; Vertical completion UI
(use-package vertico
  :ensure t
  :custom
  (vertico-count 13)
  (vertico-resize t)
  :config
  (vertico-mode))

History

;; Remember minibuffer history
(use-package savehist
  :init (savehist-mode))

Orderless

;; Flexible matching — type "buff switch" instead of "switch-to-buffer"
(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic)))

Marginalia

;; Rich annotations (keybindings, file sizes, etc.)
(use-package marginalia
  :ensure t
  :init (marginalia-mode))

Consult

;; Enhanced commands with live preview
(use-package consult
  :ensure t
  :bind (("C-s" . consult-line)       ; Better in-buffer search
         ("C-x b" . consult-buffer))) ; Better buffer switch with preview

Which-key - Descubrir atajos de teclado

Pulsa una tecla de prefijo y mira qué opciones hay disponibles:

(use-package which-key
  :ensure t
  :config
  (which-key-mode)
  (setq which-key-idle-delay 0.5))    ; Show after 0.5 seconds

Pulsa C-x y espera — verás todas las continuaciones disponibles.

Otros ajustes útiles

;; Ask y/n instead of yes/no
(setq use-short-answers t)
 
;; Smooth scrolling
(setq scroll-margin 8
      scroll-step 1
      scroll-conservatively 10000)
 
;; Tabs as spaces, 4 spaces wide
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
 
;; Auto-close brackets
(electric-pair-mode t)
 
;; Backup files in a single directory
(setq backup-directory-alist '(("." . "~/.emacs.d/backup")))

Org-mode

Org-mode es un sistema de texto plano para organizar tu vida: notas, tareas, agendas, documentos…

Todo en texto plano. Documentos literate. “Tu vida en archivos de texto.”

(setq org-todo-keywords
  '((sequence "TODO(t)" "PROG(p)" "|" "DONE(d)" "CANCELED(c)")))

Org Agenda

(setq org-agenda-files '("~/projects/gpul/emacs-talk/demo/org/"))
(setq org-agenda-span 14)
(setq org-agenda-start-with-log-mode t)
(setq org-log-done 'time)

Configuración visual de Org

;; Nicer ellipsis for folded headings
(setq org-ellipsis " ▾")
 
;; Indent content under headings
(add-hook 'org-mode-hook #'org-indent-mode)
 
;; Center text for better reading
(use-package visual-fill-column
  :ensure t
  :hook (org-mode . (lambda ()
                      (setq visual-fill-column-width 100
                            visual-fill-column-center-text t)
                      (visual-fill-column-mode 1))))
 
;; Keybinding for agenda
(global-set-key (kbd "C-c a") 'org-agenda)

Comandos clave de Org

TeclaDescripción
C-c C-tCambiar estado TODO
C-c C-sProgramar (schedule)
C-c C-dEstablecer fecha límite
C-c aAbrir agenda
C-c C-eExportar

Org-roam: Tu segundo cerebro

El método Zettelkasten aplicado a Emacs: notas interconectadas con enlaces bidireccionales para gestión del conocimiento personal.

(use-package org-roam
  :ensure t
  :custom
  (org-roam-directory (file-truename "~/projects/gpul/emacs-talk/demo/roam/"))
  :bind (("C-c n f" . org-roam-node-find)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n l" . org-roam-buffer-toggle))
  :config
  (org-roam-db-autosync-mode))

Magit - Interfaz de Git

La mejor interfaz de Git que existe.

(use-package magit
  :ensure t
  :bind ("C-x g" . magit-status))

Con C-x g abres magit-status, donde puedes hacer staging de hunks (no solo archivos enteros), commits, git blame, y mucho más, todo sin salir de Emacs.

Dired - Editor de directorios

No es un gestor de archivos. Es un buffer Lisp que controla archivos.

Se abre con C-x d o M-x dired. Muestra el listado de un directorio como un buffer normal — navegas y operas sobre archivos usando atajos de teclado.

TeclaDescripción
+Crear un nuevo directorio
dMarcar archivo para borrar
mMarcar archivo
uDesmarcar archivo
xEjecutar acciones marcadas (borrar, etc.)
RRenombrar / mover archivo
CCopiar archivo
DBorrar archivo inmediatamente
(Alternar detalles (permisos, tamaño, etc.)

Dired con Evil y Wdired

Con Evil, la navegación cambia respecto al Emacs por defecto:

EmacsEvilDescripción
RETl / RETAbrir archivo o directorio
^hSubir al directorio padre
n / pj / kMoverse abajo / arriba
ggrRefrescar el buffer

Pulsa C-x C-q para entrar en modo Writable Dired. Los nombres de archivo se convierten en texto editable — renombra archivos editando el buffer, luego C-c C-c para aplicar.

Un ejemplo perfecto de la filosofía Emacs: todo es un buffer, y los buffers son editables.

(setq dired-listing-switches
      "-l --almost-all --human-readable --group-directories-first")
 
;; Vim-style h/l navigation in Dired (evil-collection doesn't set these)
(with-eval-after-load 'dired
  (evil-define-key 'normal dired-mode-map
    "h" 'dired-up-directory
    "l" 'dired-find-file))

Tramp - Acceso remoto transparente

Edita archivos en cualquier lugar como si fuesen locales.

/ssh:user@host:/path/to/file
/sudo::/etc/hosts

“Estoy editando un archivo en un servidor remoto, y a Emacs le da igual.”

Cierre

  • Emacs es una inversión a largo plazo
  • Crece contigo
  • Nunca “terminas” de configurarlo

Recursos