YouTube

§Introducción

Hoy vamos a agregar las mismas configuraciones del video anterior a nuestro emacs de ejemplo, pero utilizando use-package:

  • vertico
  • orderless
  • evil

§Vamos al código fuente

§Encabezado del archivo

;;; init.el -- Configuración utilizando `use-package'  -*- lexical-binding:t -*-

§Primeras customizaciones

;;; 0x0003 -- Una configuración minimalista -- algo para comenzar
(load-theme 'wombat t)

(set-face-attribute 'default nil :height 180)

;; Pasamos un valor negativo a la función `menu-bar-mode'.
(menu-bar-mode -1)
;; Pasamos un valor negativo a la función `tool-bar-mode'.
(tool-bar-mode -1)
;; Pasamos un valor negativo a la función `scroll-bar-mode'
(scroll-bar-mode -1)

(setq inhibit-splash-screen t
      user-full-name "Alex Barocio")
(setq visible-bell t)

;;; 0x0004 -- Instalar paquetes en Emacs
;; Cambiar donde se guardan las customizaciones
(setq custom-file
      (expand-file-name "custom.el"
                        user-emacs-directory))

(when (file-exists-p custom-file)
  (load-file custom-file))

§Configuración de package.el

Nada especial, sólo lo que habíamos visto anteriormente.

§Repositorios

Primero que nada tenemos que ver de dónde obtenemos los paquetes, es decir, los repositorios de paquetes de emacs.

;;; Package
(require 'package)
;; Agregamos algunos repositorios de paquetes
(unless (member "nongnu" package-archives)
  ;; Argegamos este repositorio sólo si no está ya agregado.  Algunas
  ;; versiones de emacs traen ya por sí mismas este repositorio (creo
  ;; que apartir de la versión 28 de emacs).
  (add-to-list 'package-archives
               '("nongnu" . "https://elpa.nongnu.org/nongnu/")))
(add-to-list 'package-archives
             '("stable" . "https://stable.melpa.org/packages/"))
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/"))

§Precedencia

Ahora, configuraremos de dónde tomará los paquetes, en caso de que estén presentes en más de un repositorio.

;; Customizamos la prioridad de los repositorios de paquetes
;; (setopt package-archive-priorities   ; Esta macro está disponible a
                                        ; partir de emacs 29
(customize-set-variable 'package-archive-priorities
                        '(("gnu"    . 99) ; Preferimos los paquetes de GNU elpa;
                          ("nongnu" . 80) ; Usemos paquetes de non-gnu
                                        ; packages si no los podemos
                                        ; encontrar en GNU elpa;
                          ("stable" . 70) ; Preferimos versiones "liberadas" de melpa;
                          ("melpa"  . 0))) ; Si todo lo demás falla,
                                        ; tratamos de obtener
                                        ; versiones "no liberadas"
                                        ; de melpa.

§Inicialización

Finalmente preparamos todo para que funcione sin problemas.

;; Preparamos todo para instalar paquetes.
(package-initialize)       ; Inicializamos el repositorio de paquetes.
(unless package-archive-contents ; Verificamos si la lista de paquetes está vacía.
  (package-refresh-contents))    ; Actualizamos la lista de paquetes
                                        ; (sólo si está vacía).

§Configuración de use-package

Instalamos use-package si y sólo si (1) la versión de emacs es inferior a la 29 y (2) no se localiza la librería de emacs-lisp (código fuente [.el], compilado [.elc] o nativo [.eln]) en la load-path.


;;; `use-package' (0x0006)
(when (and ;; Todas las siguientes condiciones son verdaderas (no nil)
       ;; Verificamos que la versión de emacs es inferior a 29
       (version< emacs-version "29")
       ;; y que no localizamos la librería `use-package' en la
       ;; `load-path'
       (not (locate-library "use-package")))
  ;; Instalamos `use-package' cuando las condiciones son verdaderas.
  (package-install 'use-package))

(use-package use-package
  ;; Configuramos `use-package' para instalar el paquete si no se
  ;; encuentra instalado.
  :custom (use-package-always-ensure t))

§Paquetes cofigurados previamente

;;; 0x0004

(use-package beacon
  :init
  (beacon-mode +1))

(use-package 0x0)


(use-package doom-themes
  :hook (after-init . my/--forgettable-theme-function)

  :init
  (defun my/--forgettable-theme-function ()
    (load-theme 'doom-monokai-pro t)
    (disable-theme 'wombat)))

§Vertico con use-package

Ahora configuraremos vertico utilizando use-package:


;;; Vertico (0x0006)
;; (package-install 'vertico)   ; Esta línea pronto no será necesaria.

(use-package vertico
  :init
  ;; A continuación ponemos el bloque de inicialización para el paquete.
  (vertico-mode +1))

Esto es todo.

§Orderless con use-package

Configurar orderless es un poco más… elaborado, pero nada terriblemente complicado, si la configuración del video anterior fue clara.


;;; Orderless (0x0006)
;; (package-install 'orderless) ; Esta línea pronto no será necesaria.

(use-package orderless
  :init
  ;; A continuación ponemos el bloque de inicialización para el paquete.
  (defun first-initialism (pattern index total)
    "Completes with the first letter of the function/variable/object/symbol."
    (if (= index 0) 'orderless-initialism))

  ;; Esto nunca lo entendí
  (defun flex-if-twiddle (pattern index total)
    "Removes the pattern folowing a literal `~' from completions."
    (when (string-suffix-p "~" pattern)
      `(orderless-flex . ,(substring pattern 0 -1))))

  ;; Elimina de las complesiones las opciones que coincidan con lo que
  ;; siga de la exclamación.
  (defun without-if-bang (pattern index total)
    "Removes the pattern folowing a literal `!' from completions."
    (cond
     ((equal "!" pattern)
      '(orderless-literal . ""))
     ((string-prefix-p "!" pattern)
      `(orderless-without-literal . ,(substring pattern 1)))))

  :custom
  ;; En este bloque definimos las customizaciones de variables.

  ;; Con esta opción activamos el uso del paquete
  (completion-styles '(orderless))

  ;; Elegimos algunas opciones para la búsqueda, selección y filtrado
  ;; de opciones.
  (orderless-matching-styles '(orderless-regexp))

  ;; Activamos las opciones extra para `orderless'.
  (orderless-style-dispatchers '(;; first-initialism
                                 ;; flex-if-twiddle
                                 without-if-bang)))

§Evil con use-package

Esta configuración la tomé prestada de SystemCrafters, ya que yo no utilizo evil-mode. Aún así es un buen paquete que presenta algunas oportunidades de explorar el potencial de use-package. Además, sé que hay muchos usuarios de emacs que vienen de (n)vi(m), así que pudiera ser una buena oportunidad para ayudarles a tener algunos bindings que les sean más cómodos para iniciar en emacs.

La siguiente función ha sido crada para agregarse a un hook (nótese que la función no tiene parámetros). Un hook es una lista de funciones que se ejecutarán en determinadas condiciones.


;;; Evil (0x0006)
(defun rune/evil-hook ()
  (dolist (mode '(custom-mode
                  eshell-mode
                  git-rebase-mode
                  erc-mode
                  circe-server-mode
                  circe-chat-mode
                  circe-query-mode
                  sauron-mode
                  term-mode))
   (add-to-list 'evil-emacs-state-modes mode)))

Ahora configuraremos el paquete evil.

;; (package-install 'evil)              ; Esta línea pronto no será necesaria.

(use-package evil
  :hook ; Bloque de hooks
  (evil-mode . rune/evil-hook) ;Nótese que agregamos aquí la función
                               ;definida anteriormente.
  :after evil-collection ; Esta línea especifica que se deberá
                         ; ejecutar este macro después de haber
                         ; cargado y configurado el paqeute
                         ; `evil-collection'.
  :init
  ;; Bloque de inicialización del paquete (antes de ser cargado).
  (setq evil-want-integration t)
  (setq evil-want-C-u-scroll t)
  (setq evil-want-C-i-jump nil)

  ;; Bloque de configuración del paquete (después de ser cargado).
  (evil-mode +1)
  (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
  (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)

  ;; Utiliza movimientos en líneas visuales incluso fuera de buffers en `visual-line-mode'.
  (evil-global-set-key 'motion "j" 'evil-next-visual-line)
  (evil-global-set-key 'motion "k" 'evil-previous-visual-line)

  (evil-set-initial-state 'messages-buffer-mode 'normal)
  (evil-set-initial-state 'dashboard-mode 'normal))

El paquete evil es bastante útil, pero no se integra bien con la mayoría de los paquetes. Aún así, existe un paquete que hace que dicha integración sea más sencilla, al establecer sus propios bindings para muchos de los paquetes más populares.

;; (package-install 'evil-collection) ; Esta línea pronto no será necesaria.

(use-package evil-collection
  :init ; Inicializamos el paquete
  (setq evil-want-keybinding nil)
  (evil-collection-init))              ; Inicializamos la colección de
                                        ; configuraciones para `evil'.

§Cierre del archivo

;;; init.el ends here

§Comentarios

Los desarrolladores de emacs han decidido incluir use-package como parte de la distribución a partir de la versión 29 de emacs. Eso debe indicar que ha de haber algunas ventajas de utilizar esta macro.

§Ventajas

  • Ya viene con emacs 29.
  • Encapsula toda una configuración en un sólo bloque de una macro.
  • Es una macro muy utilizada y hay muchos paquetes que recomiendan su uso.
  • Tiene una estructura clara (una vez que se entiende).

§Desventajas

  • Oculta parte del funcionamiento de emacs.
  • Agrega capas de código que se deben ejecutar y, potencialmente, podría hacer el código más lento.
  • No siempre es fácil entender qué se supone que hará.
  • No siempre es fácil de debugear.

§¿Y ahora qué?

En el próximo video veremos una configuración sencilla para org-mode.

Puedes acceder a mis notas en mi repositorio: https://git.sr.ht/~abarocio80/videos/tree/master/item/content/0x0006--configurar-emacs-con-use-package.org

O en mi página: https://barocio.cc/videos/0x0006--configurar-emacs-con-use-package.html

Si te interesa este tipo de contenido, suscríbete al canal y activa las notificaciones para que (tarde o temprano) te enteres de los nuevos videos que vaya subiendo.

Nos vemos luego.