Configuración de Emacs paso a paso (01)

Primera entrega: Como organizar los ficheros de configuración.

/images/elogo_round.png

En esta serie de artículos describiré mi configuración del editor Emacs (concretamente GNU Emacs) paso a paso.

Llevo años usando Emacs en el trabajo, pero sin haber profundizado demasiado en su estudio. Cuando tenía una necesidad buscaba una solución en la red y retocaba mi fichero de configuración a toda prisa. Funcionaba, pero mi configuración era un pastiche infumable.

Gracias a las referencias que pongo al final del artículo, y en especial a la serie de videos del señor Zamansky (C’est la Z) he organizado mi fichero de configuración y añadido bastantes cosas nuevas que no conocía.

En este primer artículo dejaremos lista una configuración basica separada en dos ficheros. El fichero ~/.emacs.d/init.el rara vez volveremos a tocarlo y toda la configuración la haremos en el fichero ~/.emacs.d/myinit.org.

Avisos

Si ya estás usando Emacs haz un backup de tu configuración antes de enredar con ella. O mejor aún, controla tus ficheros de configuración con git.

Solo uso Linux, antes usaba Windows en el trabajo pero ahora uso Linux para todo, si usas Windows o Mac es posible que tengas que adaptar cosas para tu S.O.

Ficheros de configuración

Lo que nos proponemos es controlar toda la configuración de nuestro editor con dos ficheros:

~/.emacs.d/init.el
Contiene la configuración mínima de Emacs: las secciones que Emacs completa automáticamente, la declaración de las fuentes de paquetes y la configuración inicial de la gestión de paquetes de nuestro editor.
~/.emacs.d/myinit.org
Contiene toda nuestra configuración organizada en un fichero org-mode
Nota
Si no quieres seguir el artículo paso a paso y no tienes ninguna configuración previa para tu editor Emacs puedes ir a la sección Ficheros para descargar y asegurarte de dejar los ficheros init.el y myinit.org en el directorio ~/.emacs.d. ¡Ojo! esto hará que pierdas tu configuración previa.

Si tenemos nuestro editor Emacs recién instalado no tendremos ningún fichero de configuración en nuestro directorio $HOME.

Podemos hacer un pequeño cambio de configuración y salvar nuestras opciones:

  • Menú: Options → Set Default Font: Aumentamos el tamaño del tipo de fuente a 14 puntos por ejemplo
  • Menu: Options → Save Options: Salvamos nuestras opciones

Emacs salvará las opciones en el fichero ~/.emacs que tendrá el siguiente contenido:

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "DejaVu Sans Mono" :foundry "PfEd" :slant normal :weight normal :height 143 :width normal)))))

Este es nuestro primer fichero de configuración. El fichero está escrito en elisp, una variante del lenguaje LISP que usa Emacs.

No debemos tocar las dos secciones que aparecen en el fichero, estas secciones las manipula automáticamente el editor y no deberíamos enredar con ellas sin saber muy bien lo que hacemos. A pesar de esta advertencia te voy a proponer un cambio en la sección custom-set-faces para nuestro fichero init.el definitivo. En mi instalación de Emacs no se resaltaba la region (el texto selecionado en Emacs se llama region) Si te pasa lo mismo te propongo que cambies la sección custom-set-faces por la siguiente:

(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "DejaVu Sans Mono" :foundry "PfEd" :slant normal :weight normal :height 143 :width normal))))
 '(region ((t (:background "light sea green" :distant-foreground "gtk_selection_fg_color")))))

Emacs puede leer su configuración inicial de este fichero ~/.emacs y alternativamente puede usar el fichero ~/.emacs.d/init.el. En el directorio ~/.emacs.d/ vamos a tener otros ficheros a medida que vayamos completando la configuración de nuestro editor. A mi me parece más limpio tener toda la configuración de Emacs en este directorio. Así que simplemente movemos/renombramos el fichero ~/.emacs a la nueva ubicación ejecutando:

1
2
cd
mv .emacs .emacs.d/init.el

Cerramos nuestro editor Emacs y volvemos a abrirlo para comprobar que lee correctamente el fichero de configuración ~/.emacs.d/init.el (deberíamos ver el tipo de letra de 14 puntos)

Ficheros de configuración propuestos

myinit.org

Antes de nada vamos a crear el fichero ~/.emacs.d/myinit.org para que no de error la carga del init.el. Lo crearemos con un contenido mínimo:

#+startup: overview

* Interface tweaks
** Some GUI optimizations
#+begin_src emacs-lisp
  (setq inhibit-startup-message t) ; Eliminate FSF startup msg
#+end_src

El fichero solo tiene una linea de configuración para Emacs (la linea resaltada) que inhibe la pantalla de arranque del editor.

Este fichero está escrito en org-mode, lo hacemos así por que a medida que avancemos verás que queda mucho más limpio y fácil de entender. En esta serie no vamos a entrar en detalles de org-mode pero puedes investigar por tu cuenta. org-mode es una herramienta potentísima y por si solo ya sería una buena razón para usar Emacs

init.el

Ahora modificamos nuestro fichero ~/.emacs.d/init.el. Vamos a añadir dos secciones: una que configura la instalación de paquetes y una sección que se encarga de leer el resto de la configuración desde el fichero myinit.org.

El fichero init.el definitivo es el siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "DejaVu Sans Mono" :foundry "PfEd" :slant normal :weight normal :height 143 :width normal))))
 '(region ((t (:background "light sea green" :distant-foreground "gtk_selection_fg_color")))))

;;----------------------------------------------------------------------
;; Package management
;; MELPA and others
(require 'package)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.org/packages/") t)
(add-to-list 'package-archives
             '("gnu" . "http://elpa.gnu.org/packages/") t)
;;  (add-to-list 'package-archives '("marmalade" . "https://marmalade-repo.org/packages/") t)
(setq package-initialize-at-startup nil)
(package-initialize)

;; Set use-package install
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

;;------------------------------------------------------------
;; Load org-configuration file
(org-babel-load-file (expand-file-name "~/.emacs.d/myinit.org"))

En las lineas 18-25 configuramos los depósitos de paquetes para Emacs en internet. Hay tres depósitos principales de paquetes para Emacs:

GNU Elpa
El depósito oficial de Emacs
Melpa
Un depósito alternativo con muchos más paquetes que el oficial, y con actualizaciones más frecuentes
Marmalade
Era otro depósito alternativo, pero está inactivo desde hace tiempo.

En las lineas 28-30 instalamos (si no está instalado previamente) nuestro primer paquete para Emacs: use-package.

use-package es un paquete para gestionar la instación y configuración de paquetes en Emacs, una verdadera joya. Los ficheros de configuración quedan simplificados, limpios y claros.

Por último en la linea 34 cargamos nuestro fichero myinit.org.

Con esto hemos terminado de configurar nuestro fichero ~/.emacs.d/init.el, es posible que no tengamos que volver a tocarlo nunca.

Ahora si detenemos nuestro Emacs y volvemos a arrancarlo veremos (abajo de todo, en la linea de estado) que Emacs se conecta a internet, descarga el paquete use-package y procede a instalarlo.

Información
Si volvemos a abrir el fichero init.el veremos que Emacs mantiene una lista con los paquetes instalados. No debemos editarla

Dependiendo de la versión de Emacs que estés utilizando puede que veas un error de GPG por no poder verificar la firma de los paquetes de Elpa. De hecho ningún paquete de Elpa estará disponible para instalación. Lo solucionaremos en la siguiente sección.

Ampliando la configuración

Vamos a completar la configuración inicial en el fichero ~/.emacs.d/myinit.org

En este paso vamos a introducir muchos pasos de golpe. No vamos a detallar todos, puedes ver los comentarios en el propio fichero y eliminar (o comentar) los cambios que no te convenzan.

Ya comentamos que el fichero está escrito usando org-mode. Las secciones en org-mode se marcan con uno o varios asteriscos y se puede plegar y desplegar en Emacs pulsando tabulador en el título de la sección.

La primera linea (linea 1) del fichero es un preamble de org_mode para indicar como debe presentar las secciones desplegadas al abrir el fichero.

Del resto de lineas, lo único que Emacs interpretará como comandos de configuración son las partes encerradas entre indicadores begin_src y end_src el resto, los títulos de sección y los textos añadidos, son solo para organizar el fichero de configuración y dar aclaraciones.

Las primeras secciones hasta la linea hasta la linea 52 hacen ajustes variados al interfaz de usuario, fijan la codificación preferida a utf-8, establecen algunos atajos de teclado útiles (por ejemplo esc-esc-c cargará este fichero myinit.org en el editor), y hacen que el realzado de sintaxis esté activado por defecto.

A partir de ahí definimos tres funciones en elisp y les asignamos un atajo de teclado.

Kill Buffer Quick de las lineas 53 a la 64 define una función para matar el buffer (fichero) que estamos editando sin tener que recorrer todo el diálogo por defecto en Emacs y lo asocia a Ctrl-Supr

Wonderful Bubble Buffer Mantiene un listado de ficheros recientes por el que podemos movernos con la tecla F8 (cuando visitamos un buffer asciende en la lista como una burbuja) Siempre puedes moverte normalmente por los buffers abiertos con Shift-PgUp y Shift-PgDown que definimos en la sección de Shortcuts

parent matching with % Nos permite saltar al parentesis asociado con el que señale el cursor sin más que pulsar % (imitando a otros editores como Vim)

A continuación tenemos una seccion dedicada a use-package en esta sección solucionamos el error de las nuevas claves GPG de Elpa instalando un paquete con las nuevas claves (para lo cual desactivamos un momento la verificación de claves). E instalamos otro paquete que nos permitirá especificar en el futuro si hay paquetes de sistema que sean dependencias necesarias para nuestras ampliaciones de Emacs. Además instalamos try para poder probar paquetes Emacs sin tocar la configuración ni afectarla con la prueba.

Por último, y adelantándonos un poco a los acontecimientos, añadimos una sección para la configuración de org-mode e instalamos org-bullets, una vez instalado este paquete verás que el fichero myinit.org se ve de otra manera en Emacs.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#+startup: overview

* Interface tweaks
** Some GUI optimizations
   #+begin_src emacs-lisp
     (setq inhibit-startup-message t) ; Eliminate FSF startup msg
     (setq frame-title-format "%b")   ; Put filename in titlebar
     ;; (setq visible-bell t)            ; Flash instead of beep
     (set-scroll-bar-mode 'right)     ; Scrollbar placement
     (show-paren-mode t)              ; Blinking cursor shows matching parentheses
     (electric-pair-mode t)           ; electric-pair-mode on
     (setq column-number-mode t)      ; Show column number of current cursor location
     (mouse-wheel-mode t)             ; wheel-mouse support
     (setq fill-column 78)
     (setq auto-fill-mode t)                   ; Set line width to 78 columns...
     (setq-default indent-tabs-mode nil)       ; Insert spaces instead of tabs
     (global-set-key "\r" 'newline-and-indent) ; turn autoindenting on
     ;(set-default 'truncate-lines t)          ; Truncate lines for all buffers
   #+end_src

** Set encoding
   Use utf-8 please
   #+begin_src emacs-lisp
     ;; Set encoding
     (prefer-coding-system 'utf-8)
   #+end_src

** Some shortcuts
   Useful shortcuts
   #+begin_src emacs-lisp
     (global-set-key (kbd "\e\ec")
                     (lambda () (interactive) (find-file "~/.emacs.d/myinit.org"))
                     )

     (global-set-key [C-tab] 'hippie-expand)                    ; expand
     (global-set-key [C-kp-subtract] 'undo)                     ; [Undo]
     (global-set-key [C-kp-multiply] 'goto-line)                ; goto line
     (global-set-key [C-kp-add] 'toggle-truncate-lines)         ; truncate lines
     (global-set-key [C-kp-divide] 'delete-trailing-whitespace) ; delete trailing whitespace
     (global-set-key [C-kp-decimal] 'completion-at-point)       ; complete at point
     (global-set-key [C-M-prior] 'previous-buffer)              ; previous-buffer
     (global-set-key [C-M-next] 'next-buffer)                   ; next-buffer
   #+end_src

** Syntax highlight
   Set maximum colors
   #+begin_src emacs-lisp
     (cond ((fboundp 'global-font-lock-mode)        ; Turn on font-lock (syntax highlighting)
            (global-font-lock-mode t)               ; in all modes that support it
            (setq font-lock-maximum-decoration t))) ; Maximum colors
   #+end_src

** Kill buffer quick
   Kill current buffer without questions
   #+begin_src emacs-lisp
     ;;------------------------------------------------------------
     ;; Kill current buffer with C-Supr
     (defun geosoft-kill-buffer ()
       ;; Kill default buffer without the extra emacs questions
       (interactive)
       (kill-buffer (buffer-name))
       (set-name))
     (global-set-key [C-delete] 'geosoft-kill-buffer)
   #+end_src

** Wonderful bubble-buffer
   Switch to most recent buffers with F8
   #+begin_src emacs-lisp
     ;;------------------------------------------------------------
     ;; The wonderful bubble-buffer
     (defvar LIMIT 1)
     (defvar time 0)
     (defvar mylist nil)
     (defun time-now ()
     (car (cdr (current-time))))
     (defun bubble-buffer ()
     (interactive)
     (if (or (> (- (time-now) time) LIMIT) (null mylist))
         (progn (setq mylist (copy-alist (buffer-list)))
                (delq (get-buffer " *Minibuf-0*") mylist)
                (delq (get-buffer " *Minibuf-1*") mylist)))
     (bury-buffer (car mylist))
     (setq mylist (cdr mylist))
     (setq newtop (car mylist))
     (switch-to-buffer (car mylist))
     (setq rest (cdr (copy-alist mylist)))
     (while rest
       (bury-buffer (car rest))
       (setq rest (cdr rest)))
     (setq time (time-now)))
     (global-set-key [f8] 'bubble-buffer)
   #+end_src

** parent matching with %
   Jump to asociated parent with '%' same as other editors
   #+begin_src emacs-lisp
     ;;------------------------------------------------------------
     ;; Use % to match various kinds of brackets...
     ;; See: http://www.lifl.fr/~hodique/uploads/Perso/patches.el
     (global-set-key "%" 'match-paren)   ; % key match parents
     (defun match-paren (arg)
       "Go to the matching paren if on a paren; otherwise insert %."
       (interactive "p")
       (let ((prev-char (char-to-string (preceding-char)))
             (next-char (char-to-string (following-char))))
         (cond ((string-match "[[{(<]" next-char) (forward-sexp 1))
               ((string-match "[\]})>]" prev-char) (backward-sexp 1))
               (t (self-insert-command (or arg 1))))))
   #+end_src

* use-package
** use-package tips
   Some notes about *use-package*
   - *:ensure* if true will install the package if not installed
     It won't update packages. See auto-package-update for keeping all
     packages up to date
   - *:init* keyword to execute code before a package is loaded. It
     accepts one or more foorms, up to the next keyword
   - *:config* can be used to execute code after a package is loaded.
     In cases where loading is done lazily (see more about autoloading
     below), this execution is deferred until after the autoload
     occurs
   - *:bind*
   - *bind-keymap*
   - *:mode* and *:interpreter*
   - *:magic*
   - *:hook*
   - *:if*

** helpers =gnu-elpa-keyring-update= Avoids GPG errors in emacs version prior
   to 26.3 And =use-package-ensure-system-package= gives a warning
   when needed system packages are missing
   #+begin_src emacs-lisp
     (unless (package-installed-p 'gnu-elpa-keyring)
       (setq package-check-signature nil)
       (use-package gnu-elpa-keyring-update
         :ensure t)
       (setq package-check-signature 'allow-unsigned))
     (use-package use-package-ensure-system-package
       :ensure t)
   #+end_src

** try
   To try package without definitive installation
   #+begin_src emacs-lisp
     (use-package try
       ;; for trying packages without installing
       :ensure t)
   #+end_src

* org-mode
** org-bullets
   Nice bullets for org-mode
   #+begin_src emacs-lisp
     (use-package org-bullets
       :ensure t
       :config
       (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
       )
   #+end_src

Ficheros para descargar

Los ficheros descritos: init.el y myinit.org puedes descargarlos desde este enlace

Los ficheros están almacenados en https://gitlab.com/comacero/emacs_conf_step e irán ampliándose a medida que publiquemos esta serie.

Referencias