Archivo de configuración de Emacs desde un fichero org-mode.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Notxor 144fe83aae Añadir el paquete `editorconfig' al inicio. 35 minutes ago
LICENSE Initial commit 1 month ago
README.org Añadir el paquete `editorconfig' al inicio. 35 minutes ago

README.org

init-emacs

Archivo de configuración de Emacs desde un fichero org-mode. Lo ideal es tener agrupadas las opciones por conceptos y no, como hace por defecto Emacs en custom-set-variables, alfabéticamente.

Inicio de la configuración

La configuración comienza estableciendo las variables necesarias para la configuración de paquetes. Estoy utilizando el modo use-package.

Los paquetes los buscará en los repositorios GNU y melpa. Al iniciar refresca los paquetes, comprueba si está instalado use-package, si no lo está lo instala y comienza el proceso.

  ;;; package --- init.el
  ;;; Commentary:
  ;;; Este es mi fichero init.el para configurar Emacs
  (require 'package)
  ;;; Code:
  (add-to-list 'package-archives '("gnu"   . "https://elpa.gnu.org/packages/"))
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
  (package-initialize)

  (unless (package-installed-p 'use-package)
    (package-refresh-contents)
    (package-install 'use-package))
  (eval-and-compile
    (setq use-package-always-ensure t
          use-package-expand-minimally t))

También puede haber algunos paquetes bajados a mano o desarrollados por mí, que los busca en diferentes sitios.

  ;; lugar para los paquetes bajados a mano
  (add-to-list 'load-path "~/.emacs.d/site-packages")
  (add-to-list 'load-path "~/.emacs.d/notxor-blog/")

Ajuste de variables

El apartado de custom-set-variables lo genera automáticamente Emacs cuando se utiliza el modo gráfico de configuración. Avisa de que seamos cuidadosos si lo modificamos a mano.

Lo que no me gusta de esta generación automática es que ordena las variables alfabéticamente y prefiero agruparlas por concepto. Pero por concepto es posible que nos encontremos con algunas variables que se queden solas.

Cabecera

  (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.

Ajustes de calendario y agenda

  ;; Estilos de cabeceras
  '(calendar-date-style 'iso)
  '(calendar-day-header-array ["Do" "Lu" "Ma" "Mi" "Ju" "Vi" "Sa"])
  '(calendar-day-name-array
    ["domingo" "lunes" "martes" "miércoles" "jueves" "viernes" "sábado"])
  '(calendar-month-abbrev-array
    ["Ene" "Feb" "Mar" "Abr" "May" "Jun" "Jul" "Ago" "Sep" "Oct" "Nov" "Dic"])
  '(calendar-month-name-array
    ["enero" "febrero" "marzo" "abril" "mayo" "junio" "julio" "agosto" "septiembre" "octubre" "noviembre" "diciembre"])
  '(calendar-week-start-day 1) ; La semana comienza en lunes

  '(org-agenda-diary-file "~/agenda/diario.org")
  '(org-agenda-files
    '("/home/notxor/agenda/agenda.org" "/home/notxor/agenda/personal.org"))
  '(org-agenda-include-diary t)
  '(org-archive-location "~/agenda/especiales/archive.org::* Desde %s")

  '(org-caldav-calendar-id "personal")
  '(org-caldav-files '("~/agenda/personal.org"))
  '(org-caldav-inbox "~/agenda/personal.org")
  '(org-caldav-url
    "https://nube.nueva-actitud.org/remote.php/dav/calendars/Notxor")
  '(org-icalendar-timezone "Europe/Madrid")
  '(org-todo-keywords
    '((sequence "PENDIENTE(p)" "ESPERANDO(e)" "|" "HECHO(h)" "CANCELADO(c)")))

  '(diary-entry-marker 'font-lock-variable-name-face)
  '(diary-file "~/agenda/diario.org")

Un punto importante es la captura de citas y otros asuntos mediante el sistema de captura de org-mode. La captura suele ser una de las dificultades que se nos plantea cuando queremos tomar notas rápido. Las siguientes plantillas facilitan que con pocas pulsaciones de teclas muestre una estructura según el tipo de anotación que quiero hacer.

    '(org-capture-templates
      ;; Es una lista de listas así que vamos por partes
      '(("t" "Tarea Pendiente")
        ("tt" "Tarea Simple    (t) trabajo" entry (file "~/agenda/agenda.org")
         "* PENDIENTE %? \t :trabajo:
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"PENDIENTE\"            from \"\"      %U
     :END:" :empty-lines 1)
          ("ta" "Tarea Simple    (a) asociación" entry (file+headline "~/agenda/agenda.org" "Asociación")
           "* PENDIENTE %? \t :pica:
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"PENDIENTE\"            from \"\"      %U
     :END:" :empty-lines 1)
          ("tp" "Tarea Simple    (p) personal" entry (file+headline "~/agenda/agenda.org" "Personal")
           "* PENDIENTE %? \t :personal:
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"PENDIENTE\"            from \"\"      %U
     :END:" :empty-lines 1)
   ;;; Capturar tareas que pasan a estar a la espera
          ("e" "Tarea a la espera")
          ("et" "Tarea a la espera    (t) trabajo" entry (file "~/agenda/agenda.org")
           "* ESPERANDO %? \t :trabajo:
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"ESPERANDO\"            from \"\"      %U
     :END:" :empty-lines 1)
          ("ea" "Tarea a la espera    (a) asociación" entry (file+headline "~/agenda/agenda.org" "Asociación")
           "* ESPERANDO %? \t :pica:
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"ESPERANDO\"            from \"\"      %U
     :END:" :empty-lines 1)
          ("ep" "Tarea Simple    (p) personal" entry (file+headline "~/agenda/agenda.org" "Personal")
           "* ESPERANDO %? \t :personal:
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"ESPERANDO\"            from \"\"      %U
     :END:" :empty-lines 1)
   ;;; Capturas que tienen «deadline» asociada
          ("l" "Tarea con fecha límite")
          ("lt" "Tarea    (t) trabajo" entry (file "~/agenda/agenda.org")
           "* PENDIENTE %? \t :trabajo:
     DEADLINE: %(substring (call-interactively 'org-deadline) 12)
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"PENDIENTE\"            from \"\"      %U
     :END:" :empty-lines 1)
          ("la" "Tarea    (a) asociación" entry (file+headline "~/agenda/agenda.org" "Asociación")
           "* PENDIENTE %? \t :pica:
     DEADLINE: %(substring (call-interactively 'org-deadline) 12)
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"PENDIENTE\"            from \"\"      %U
     :END:" :empty-lines 1)
          ("lp" "Tarea    (p) personal" entry (file+headline "~/agenda/agenda.org" "Personal")
           "* PENDIENTE %? \t :personal:
     DEADLINE: %(substring (call-interactively 'org-deadline) 12)
     :PROPERTIES:
     :CREATE:      %U
     :END:
     :LOGBOOK:
     - State  \"PENDIENTE\"            from \"\"      %U
     :END:" :empty-lines 1)
   ;;; Templates de captura para cosas que no son para la agenda
          ("n" "Capturas no para agenda")
          ("nc" "Anotar (c) contacto" entry (file+headline "~/agenda/especiales/personal.org.gpg" "Sin ordenar")
           "** %^{Nombre} %^{Apellidos}%?
     :PROPERTIES:
     :Nombre:     %\\1
     :Apellidos:  %\\2
     :Alias:      %^{Alias}
     :Grupo:      %^{Grupo}
     :F-nacim:    %^{F-nacim}u
     :Móvil:      %^{Móvil}
     :Teléfono:
     :Email:      %^{Email}
     :Web:
     :Dirección:  %^{Dirección}
     :Ciudad:     %^{Ciudad}
     :Provincia:  %^{Provincia}
     :Cód.Pos:    %^{Código Postal}
     :Compañía:
     :Notas:
     :END:" :empty-lines 1)
          ("nd" "Anotar (d) diario" entry (file+headline "~/agenda/bitacora.org" "Diario")
           "** %U
  %?" :empty-lines 1)
          ("ni" "Anotar (i) idea" entry (file+headline "~/agenda/bitacora.org" "Ideas")
           "** Idea para %^{Tema}
     :PROPERTIES:
     :Tema:      %\\1
     :fecha:     %U
     :END:
  %?" :empty-lines 1)
      ("np" "Anotar (p) presupuesto" entry (file+headline "~/agenda/cuentas.org" "Presupuestos")
       "** Presupuesto para %^{Cliente}
     :PROPERTIES:
     :Cliente:       %\\1
     :fecha:         %U
     :END:
  %T

  | Concepto                              | Precio (€) | Cantidad  | Total (€) |
  | <30>                                  | <9>        | <9>       | <9>       |
  |---------------------------------------+------------+-----------+-----------|
  | %?                                    |            |           |           |
  |                                       |            |           |           |
  |---------------------------------------+------------+-----------+-----------|
  | Total                                 |            |           |           |
  ,#+TBLFM: $4=$2*$3;%.2f::@>$4=vsum(@3..@-1);%.2f
  " :empty-lines 1)
  ;;; Lista de templates de captura para Frateco
          ("f" "Tareas para Frateco Esperanto")
          ("ff" "Tarea    (f) Frateco" entry (file+headline "~/agenda/agenda.org" "Esperanto")
           "* PENDIENTE %? \t :personal:
     DEADLINE: %(substring (call-interactively 'org-deadline) 12)
     :PROPERTIES:
     :CREATE:       %U
     :END:
     :LOGBOOK:
     - State  \"PENDIENTE\"            from \"\"      %U
     :END:" :empty-lines 1)
          ))

Lector de feeds

Para leer las noticias que suelen interesarme utilizo elfeed, que es la herramienta de Emacs para RSS.

  '(elfeed-feeds
    '("https://trasteandoconjess.es/feed"
      "https://write.privacytools.io/c3po/feed/"
      "https://56k.es/rss"
      "https://ciberpatrulla.com/blog/feed"
      "https://victorhckinthefreeworld.com/feed/"
      "https://jordila.librebits.info/feed/"
      "https://notxor.nueva-actitud.org/rss.xml"
      "https://pfctelepathy.wordpress.com/feed/"
      "https://ondahostil.wordpress.com/feed/"
      "https://priioajn.wordpress.com/feed/"
      "https://izaroblog.com/feed/"
      "https://elpinguinotolkiano.wordpress.com/feed/"
      "http://www.lapipaplena.org/feed/"
      "http://www.infocop.es/AreaRSS/"
      "http://www.copmadrid.org/wp/feed/"
      "https://lamiradadelreplicante.com/feed/"
      "https://mamalinuxera.wordpress.com/feed/"
      "https://zagueros.noblogs.org/feed/"
      "https://colaboratorio.net/feed/"
      "http://www.maxxcan.com/feed/"
      "https://mierda.tv/feed/"
      "http://rufianenlared.com/feed/"
      "https://lwn.net/headlines/newrss"
      "https://luluvonflama.wordpress.com/feed/"
      "https://lamaldiciondelescritor.blogspot.com/feeds/posts/default"
      "https://www.atareao.es/feed/"
      "https://elbinario.net/feed/"
      "https://linuxenmovimiento.es/feed/"
      "https://www.muylinux.com/feed/"
      "http://asociacionpica.org/feed"
      "https://nueva-actitud.org/feed/"
      "https://fatimenia.wordpress.com/feed/"
      "https://clarosenelbosque.com/feed/"
      "http://worldbuildingschool.com/feed/"
      "https://ugeek.github.io/feed.xml"
      "http://lapiedradesisifo.com/feed/"
      "http://elblogdeiulius.es/feed/page:feed.xml"
      "http://planet.emacs-es.org/rss20.xml"
      "http://ruifigueiredo.me/rss.xml"
      "https://quijotelibre.com/feed/"
      "https://ciberpatrulla.com/feed/"
      "https://ekaitz.elenq.tech/feeds/all.atom.xml"
      "https://ebzzry.io/sitemap.xml"
      "http://muzaiko.info/public/podkasto/podkasto.rss"
      "https://unesperante.wordpress.com/feed/"
      "http://feeds.feedburner.com/VarsoviaVentoPodkasto"
      "http://www.esperanto.es/hef/index.php?format=feed&type=rss"
      "https://teokajlibroj.wordpress.com/feed/"
      "http://www.liberafolio.org/feed/"
      "https://eo.globalvoices.org/feed"
      "http://revuoesperanto.org/rss.xml"
      "http://eo.mondediplo.com/?page=backend"
      "https://bertilow.com/bertiloblogo/?feed=rss2"
      "https://scivolemo.wordpress.com/feed/"
      "http://feeds.feedburner.com/CuadernoDeCulturaCientfica"
      "https://lacienciaysusdemonios.com/feed/"
      "https://www.linux.com/feeds/rss"
      "http://planetkde.org/rss20.xml"
      "http://planet.kde-espana.org/atom.xml"
      "https://jordila.librebits.info/feed"
      "https://casatiajulia.com/blog/feed"
      "http://feeds.feedburner.com/blogelhackernet.xml"
      "https://elblogdelazaro.gitlab.io/index.xml"
      "https://www.davidrevoy.com/feed/rss"
      "https://adrianperales.com/feed/"))

Ajustes varios

Lo primero es ajustar algunos directorios donde Emacs puede buscar información para el sistema de ayuda Info o páginas de manual de erlang.

  '(Info-default-directory-list
    '("/usr/share/info/" "/usr/local/share/info/" "~/opt/share/info/"))
  '(edts-man-root "/home/notxor/.emacs.d/edts/doc/R7B")

Otros ajustes se refieren al sistema de corrección ortográfica al vuelo.

  '(ispell-dictionary "espanol")
  '(ispell-program-name "aspell")

También los lenguajes con los que podemos ejecutar bloques de código dentro de org-mode. La función principal es utilizar la llamada programación literaria, del que el presente fichero es sólo un pequeño ejemplo.

  '(org-babel-load-languages
    '((dot . t)
      (plantuml . t)
      (org . t)
      (ledger . t)
      (python . t)
      (emacs-lisp . t)
      (scheme . t)
      (latex . t)
      (gnuplot . t)
      (sqlite . t)
      (shell . t)
      (awk . t)
      (sed . t)
      (tcl . t)
      (julia . t)
      (lua . t)))

Las dos líneas finales de este apartado son decirle a Emacs dónde encontrar el ejecutable (java) de la aplicación plantuml y la combinación de teclas C-M-p para que la establezca como teclas básicas de perspective. Por algún motivo, no deja que se defina en otro sitio que no sea en el bloque custom-variables y además con un formato críptico.

  '(org-plantuml-jar-path "/usr/share/java/plantuml.jar")
  '(persp-mode-prefix-key [134217744])

Ajustes de aspecto y comportamiento

Algunos valores más para modificar el aspecto y/o comportamiento de Emacs cuando trabajamos con él.

  '(abbrev-suggest t)
  '(delete-selection-mode nil)
  '(display-line-numbers-type 'visual)
  '(face-font-family-alternatives
    '(("Monospace" "Deja Vu Mono" "fixed")
      ("Monospace Serif" "Fire Code" "Consolas" "Deja Vu Sans" "FreeMono" "Nimbus Mono L" "courier" "fixed")
      ("courier" "CMU Typewriter Text" "fixed")
      ("Sans Serif" "helv" "helvetica" "arial" "fixed")
      ("helv" "helvetica" "arial" "fixed")))
  '(ansi-color-faces-vector
    [default default default italic underline success warning error])
  '(ansi-color-names-vector
    ["black" "red3" "ForestGreen" "yellow3" "blue" "magenta3" "DeepSkyBlue" "gray50"])
  '(column-number-mode t)
  '(custom-enabled-themes '(dracula))
  '(httpd-host 'local)
  '(indent-tabs-mode nil)
  '(pdf-view-midnight-colors '("#232629" . "#f8f8f2"))
  ;; Cuestiones `estéticas'
  '(inhibit-startup-screen t)             ;No muestra la pantalla de inicio por defecto de `Emacs'
  '(scroll-bar-mode nil)                  ;Elimina las barras de scroll
  '(tool-bar-mode nil)                    ;Elimina la barra de herramientas
  '(menu-bar-mode nil)                    ;Elimina el menú (accesible desde `<f10>')

  '(truncate-lines t)                     ;Las líneas en una línea sin saltos
  '(show-paren-mode t)                    ;Remarca la pareja de un paréntesis (corchete, llave)
  '(which-key-mode t)                     ;Activa la sugerencia de teclas
  '(word-wrap t))
  ;; Establecer el tamaño de inicio de la ventana
  (add-to-list 'default-frame-alist '(width . 200)) ;Son valores en caracteres, dependen del tamaño de fuente
  (add-to-list 'default-frame-alist '(height . 58))
  (save-place-mode t)      ; Guarda la posición del cursor al cerrar un archivo

Envía los ficheros de backup a un directorio temporal.

  ;; Centralizando los ficheros temporales en el directorio temporal
  (setq backup-directory-alist
        `((".*" . ,temporary-file-directory)))
  (setq auto-save-file-name-transforms
        `((".*" ,temporary-file-directory t)))

Configuraciones de teclas generales y ganchos

En este apartado se establecen las teclas generales disponibles en todos los modos. Aunque es posible que alguna quede sobrescrita por alguna tecla local del modo utilizado. En general, se utiliza la convención de C-c, como tecla base.

  ;; Asignación de combinaciones de teclas globales
  (global-set-key (kbd "C-v")     'iedit-mode)
  (global-set-key (kbd "C-c a")   'org-agenda)
  (global-set-key (kbd "C-c b")   'ibuffer-sidebar-toggle-sidebar)
  (global-set-key (kbd "C-c c")   'org-capture)
  (global-set-key (kbd "C-c e")   'elfeed)
  (global-set-key (kbd "C-c g")   'magit-status)
  (global-set-key (kbd "C-c i")   'org-caldav-sync)
  (global-set-key (kbd "C-c h")   'hl-line-mode)
  (global-set-key (kbd "C-c l")   'display-line-numbers-mode)
  (global-set-key (kbd "C-c r")   'swiper)
  (global-set-key (kbd "C-c s")   'dired-sidebar-toggle-sidebar)
  (global-set-key (kbd "C-c t")   'toggle-truncate-lines)
  (global-set-key (kbd "C-c w")   'whitespace-mode)
  (global-set-key (kbd "<C-return>") 'hs-toggle-hiding)
  (global-set-key (kbd "M-/")     'hippie-expand)
  ;; Configuración de auto-complete
  (global-set-key (kbd "M-TAB") 'auto-complete)

Los ganchos (hooks) sirven para establecer automáticamente modos según se activen o no otros.

  ;; Hooks asignados automáticamente a modos
  (add-hook 'text-mode-hook 'turn-on-auto-fill)
  (add-hook 'text-mode-hook 'turn-on-flyspell)
  (add-hook 'text-mode-hook 'hl-line-mode)
  (add-hook 'dired-mode-hook 'all-the-icons-dired-mode)
  (add-hook 'dired-mode-hook 'dired-git-mode)
  (add-hook 'dired-mode-hook 'auto-revert-mode) ; refresco de dired
  (add-hook 'ledger-mode-hook 'display-line-numbers-mode)
  (add-hook 'prog-mode-hook 'display-line-numbers-mode)
  (add-hook 'prog-mode-hook 'hs-minor-mode) ; para poder plegar funciones
  (add-hook 'prog-mode-hook 'hl-line-mode)
  (add-hook 'gdscript-mode 'whitespace-mode)
  (add-hook 'org-mode-hook 'org-bullets-mode) ; activar modo de visualización de cabeceras de un punto
  (add-hook 'ediff-prepare-buffer-hook #'show-all)
  (add-hook 'prog-mode-hook 'electric-pair-mode) ; activar pareja de paréntesis, llaves, etc.
  (add-hook 'xref-backend-functions #'dumb-jump-xref-activate) ; activar «jump to definition»

Instalación de paquetes

Preparadas todas las variables llega el turno a los paquetes que necesito instalar para mi trabajo. Algunos paquetes están instalados pero son de uso esporádico, habría que hacerles una limpia.

Paquetes de aspecto y comportamiento

El paquete editorconfig cubre un estándar establecido para varios editores. Proporciona soporte para varias propiedades, como indente_style, charset, end_of_line o tab_width. Dichas propiedades se establecen en un archivo .editorconfig y serían comunes para todos los editores que soportan dicho esquema.

  (use-package editorconfig
    :ensure t
    :config
    (editorconfig-mode t))

En dicho fichero de configuración común para los distintos lenguajes, se puede establecer un comportamiento distinto para cada lenguaje o tipo de archivo. Por ejemplo, en mi sistema tengo el siguiente, sacado del ejemplo de la página web aunque retocado un poco a mi conveniencia:

  # EditorConfig is awesome: https://EditorConfig.org

  # top-most EditorConfig file
  root = true

  # Unix-style newlines with a newline ending every file
  [*]
  end_of_line = lf
  insert_final_newline = true
  charset = utf-8
  trim_trailing_whitespace = true

  # 4 space indentation
  [*.py]
  indent_style = space
  indent_size = 4

  # Tab indentation (no size specified)
  [Makefile]
  indent_style = tab

  # Indentation override for all JS under lib directory
  [lib/**.js]
  indent_style = space
  indent_size = 2

  # Matches the exact files either package.json or .travis.yml
  [{package.json,.travis.yml}]
  indent_style = space
  indent_size = 2

El paquete beacon remarca la posición del cursor cuando entras en un buffer. Hace un vistoso guiño que te permite descubrir de un sólo vistazo dónde está. A parte de la vistosidad, viene muy bien cuando trabajas con muchos buffers abiertos.

  ;; Resalte de la posición del cursor al cambiar de `buffer'
  (use-package beacon
    :ensure t
    :config
    (beacon-mode t))

El paquete powerline embellece la linea de estado de Emacs haciéndola más vistosa.

  ;; Mejorando la visualización de la línea de estado
  (use-package powerline
    :ensure t
    :config
    (powerline-default-theme)
    (setq powerline-default-separator 'rounded))

El paquete heaven-and-hell permite tener definidos un par de temas, uno claro y uno oscuro, e intercambiarlos con la pulsación de una tecla. A veces, trabajando fuera al aire libre, los temas oscuros no se ven con claridad y necesito cambiar a un tema claro. Como tema claro utilizo el famoso dracula y como tema claro uno de los que ya viene instalado por defecto: tsdh-light. También se puede cambiar al tema claro que se establece por defecto al arrancar Emacs:

  • C-c <F6>: cambia al tema por defecto de Emacs
  • <F6>: intercambia los temas, el claro y el oscuro.

Ambas teclas no llaman directamente a las funciones de heaven-and-hell sino que llaman a las funciones definidas en este archivo de configuración para restablecer powerline después de haber cambiado el tema de color.

  (use-package heaven-and-hell
    :ensure t
    :init
    (setq heaven-and-hell-theme-type 'dark) ;; Omit to use light by default
    (setq heaven-and-hell-themes
          '((light . tsdh-light)
            (dark . dracula))) ;; Se puede sustituir por (dark . (tsdh-dark wombat))
    ;; Optionall, load themes without asking for confirmation.
    (setq heaven-and-hell-load-theme-no-confirm t)
    :hook ((after-init . heaven-and-hell-init-hook)))

  (defun ajuste-powerline-theme ()
    "Hace un reset de la powerline tras cambiar el tema."
    (interactive)
    (heaven-and-hell-toggle-theme)
    (powerline-reset))

  (defun ajuste-powerline-default-theme ()
    "Hace un reset de la powerline tras cambiar al tema por defecto."
    (interactive)
    (heaven-and-hell-load-default-theme)
    (powerline-reset))

  (global-set-key (kbd "C-c <f6>") 'ajuste-powerline-default-theme)
  (global-set-key (kbd "<f6>")     'ajuste-powerline-theme)

El código para hacer el fondo de Emacs transparente está comentado para desactivarlo. Queda vistoso pero es molesto para trabajar, alguna vez lo activo, pero sólo en modo presentación.

  ;; Fondo de Emacs transparente
  ;;(set-frame-parameter (selected-frame) 'alpha '(92 . 90))
  ;;(add-to-list 'default-frame-alist '(alpha . (92 . 90)))

Establecer y activar el plegado de código con hs-minor-mode asignándole las teclas necesarias, partiendo de M-p.

  ;; Activar plegado de código con hs-minor-mode
  ;; HIDE
  (global-set-key (kbd "M-p t") 'hs-hide-all)
  (global-set-key (kbd "M-p d") 'hs-hide-block)
  (global-set-key (kbd "M-p c") 'hs-hide-comment-region)
  (global-set-key (kbd "M-p l") 'hs-hide-level)
  ;; SHOW
  (global-set-key (kbd "M-p a") 'hs-show-all)
  (global-set-key (kbd "M-p s") 'hs-show-block)
  ;; TOGGLE
  (global-set-key (kbd "M-p e") 'hs-toggle-hiding)
  ;; JUMP
  (global-set-key (kbd "M-p i") 'imenu)

Dashboard es un paquete que sustituye la página inicial de Emacs proporcionando información sobre aspectos habituales: abrir algún fichero que hemos abierto hace poco, o proyecto. También nos muestra una lista de las actividades de la agenda más cercanas… y es un arranque vistoso.

  (use-package dashboard
    :ensure t
    :config
    (dashboard-setup-startup-hook))

  (setq initial-buffer-choice (lambda () (get-buffer "*dashboard*")))
  ;; Establece el título
  (setq dashboard-banner-logo-title "Bienvenido a Emacs Dashboard")
  ;; Establece la cartelera
  (setq dashboard-startup-banner 'logo)
  (setq dashboard-items '((recents  . 5)
                          (bookmarks . 5)
                          (projects . 5)
                          (agenda . 5)
                          (registers . 5)))

  ;; Centra el contenido de la pantalla
  (setq dashboard-center-content t)

  ;; Mostar el atajo de salto al lado de la cabecera
  (setq dashboard-show-shortcuts nil)

Paquetes de utilidad

El paquete ivy es un entrometido que lo quiere gestionar y mover todo, pero resulta muy útil porque lo muestra de manera más clara y sencilla de entender que el comportamiento por defecto. Nos muestra alternativas del comando que estamos tecleando, tiene autocompletado y otras funciones que nos hacen la vida más sencilla.

Ivy

Hay dos grandes paquetes de ayuda (completados, listados, sugerencias) para el usuario de Emacs uno es helm, pero yo utilizo ivy pues lo noto más ligero y agradable que el anterior.

  ;; Configurar ivy
  ;; add ‘recentf-mode’ and bookmarks to ‘ivy-switch-buffer’.
  (use-package ivy
    :ensure t
    :init
    (setq ivy-use-virtual-buffers t
          ivy-height 15                             ; muestra 15 líneas de información (por defecto son 10)
          ivy-count-format ""                       ; no mostrar el contador
          ivy-initial-inputs-alist nil)
    :config
    (ivy-mode t))
  (use-package all-the-icons-ivy
    :init (add-hook 'after-init-hook 'all-the-icons-ivy-setup))
  (use-package all-the-icons-ivy-rich
    :ensure t
    :init (all-the-icons-ivy-rich-mode t))
  (use-package ivy-rich
    :ensure t
    :config
    (ivy-rich-mode t))

  (defun ivy-rich-switch-buffer-icon (candidate)
    (with-current-buffer
        (get-buffer candidate)
      (let ((icon (all-the-icons-icon-for-mode major-mode)))
        (if (symbolp icon)
            (all-the-icons-icon-for-mode 'fundamental-mode)
          icon))))
  (setq ivy-rich-display-transformers-list
        '(ivy-switch-buffer
          (:columns
           ((ivy-rich-switch-buffer-icon (:width 2))
            (ivy-rich-candidate (:width 30))
            (ivy-rich-switch-buffer-size (:width 7))
            (ivy-rich-switch-buffer-indicators (:width 4 :face error :align right))
            (ivy-rich-switch-buffer-major-mode (:width 12 :face warning))
            (ivy-rich-switch-buffer-project (:width 15 :face success))
            (ivy-rich-switch-buffer-path (:width (lambda (x) (ivy-rich-switch-buffer-shorten-path x (ivy-rich-minibuffer-width 0.3))))))
           :predicate
           (lambda (cand) (get-buffer cand)))))
  (setq all-the-icons-ivy-rich-icon t)
  (setq all-the-icons-ivy-rich-color-icon t)
  (setq all-the-icons-ivi-rich-icon-size 1.0)
  (setq all-the-icons-ivy-rich-field-width 80)

Which key

El paquete which-key muestra en el minibuffer las combinaciones de teclas disponibles después de haber pulsado una. Por ejemplo, cuando pulsamos C-x nos muestra todas las posibles opciones con una lista de tecla--comando.

  (use-package which-key
    :ensure t
    :init
    (which-key-setup-minibuffer)
    (which-key-mode))

Presentaciones

   (use-package org-tree-slide
    :defer t)
  (setq org-tree-slide-indicator
    '(:next "Siguiente >>" :previous "<<  Anterior" :content "<<  Contenido  >>"))

  (when (require 'org-tree-slide nil t)
    (define-key org-mode-map (kbd "<f8>") 'org-tree-slide-mode)
    (define-key org-mode-map (kbd "S-<f8>") 'org-tree-slide-skip-done-toggle)
    (define-key org-tree-slide-mode-map (kbd "C->")
      'org-tree-slide-move-previous-tree)
    (define-key org-tree-slide-mode-map (kbd "C-<")
      'org-tree-slide-move-next-tree)
    (define-key org-tree-slide-mode-map (kbd "C-x s c")
      'org-tree-slide-content)
    (setq org-tree-slide-skip-outline-level 4)
    (org-tree-slide-narrowing-control-profile)
    (setq org-tree-slide-skip-done nil))

Utilización de perspectivas

El paquete perspective proporciona espacios de trabajo separados en Emacs, parecido a cómo se trabaja en diferentes escritorios en los gestores de ventanas. Muestra las etiquetas de cada espacio de trabajo en la línea de estado, remarcando el que esté activo.

  (use-package perspective
    :ensure t
    :init
    (persp-mode t))

Base de datos de contactos

Es una base de datos poco intuitiva. La guardo cifrada con GPG aunque Emacs la abre directamente sin preguntar nada, tiene accesible la clave. Eso me permite guardar las copias de seguridad e incluso enviar(me)la sin afectar a la seguridad.

  ;; Preparando la base de datos bbdb
  (use-package bbdb
    :init
    (setq bbdb-file "~/agenda/especiales/bbdb.gpg")
    (setq bbdb-phone-style nil)
    :defer t
    :config
    (bbdb-initialize))

Paquetes añadidos a org

Este paquete tiene un compendio amplio de utilidades para org-mode. En particular lo instalo por la utilidad de exportación ox-bibtex y la de embellecimiento org-bullet-mode.

  (use-package org-contrib
    :defer t)

Contabilidad

Para la contabilidad utilizo la aplicación ledger. El paquete de autocompletado de ledger lleva un tiempo dando errores, por eso lo pongo aquí comentado.

  ;;configuración para contabilidad
  (use-package ledger-mode
    :ensure t
    :defer t)
  (autoload 'ledger-mode "ledger-mode" "Modo mayor para Ledger" t)
  (add-to-list 'auto-mode-alist '("\\.ledger$" . ledger-mode))
  (add-hook 'ledger-mode-hook
            (lambda ()
              (setq-local tab-always-indent 'complete)
              (setq-local completion-cycle-threshold t)
              (setq-local ledger-complete-in-steps t)))
  (setq ledger-reconcile-default-commodity "€")

  ;; (use-package company-ledger
  ;;    :ensure t
  ;;    :defet t
  ;;    :after company)

Lector de feeds

También utilizo Emacs como lector de feeds. El paquete que me lo facilita es elfeed.

  (use-package elfeed
    :defer t
    :ensure t)

Paquete del blog

  (load-file "~/.emacs.d/notxor-blog/notxor-blog.el")
  ;; (use-package notxor-blog
  ;;   :load-path "~/.emacs.d/notxor-blog/"
  ;;   :defer t
  ;;   :ensure t)

Gestión de anotaciones

La captura de notas la puse más arriba en la definición de variables. Esas notas, capturadas al vuelo, se guardan en ficheros aparte de la gestión de notas más científica que mantengo después. Activo un registro para acceder directamente a la apertura de un fichero de notas para después clasificarlas y pasarlas al sistema de anotaciones.

Registro para notas rápidas

Establece un registro de acceso directo para anotar directamente sin necesidad de buscar dónde.

  ;; Guardar en un registro el fichero de bitácora para abrirlo en cualquier momento
  (set-register ?a '(file . "~/agenda/bloc-notas.org"))
Paquete de notas y Zettelkasten

Sistema de toma de notas estandarizado con los principios del Zettelkasten. Si no sabes de lo que estoy hablando echa un ojo a mi blog y lo sabrás, encontrarás una entrada donde explico todo el proceso y lo que significa cada línea de este apartado.

  ;; Tomar notas
  (use-package deft
    :ensure t
    :bind ("<f5>" . deft)
    :commands (deft deft-refresh)
    :config (setq deft-directory "~/Nextcloud/Notes"
                  deft-extensions '("org" "md" "txt")
                  deft-use-filename-as-title t))

  (use-package zetteldeft
    :ensure t
    :after deft
    :config (zetteldeft-set-classic-keybindings))

  (setq zetteldeft-title-suffix "\n#+tags: #")
  (setq deft-default-extension "org")
  (setq zetteldeft-backlink-prefix "- Backlink: ")

  ;; Cambio de directorio Deft
  (defun deft-cambio-dir (dir)
    "Cambiar de directorio Deft al `DIR' de forma interactiva."
    (interactive "DNuevo directorio Deft: ")

    (message (format "Se cambia def-directory a: %s" dir))
    (setq deft-directory (expand-file-name dir))
    (deft-refresh))

  (defun deft-recursivo ()
    "Establece que `deft' busque también en subdirectorios."
    (interactive)
    (setq deft-recursive t)
    (deft-refresh))

  (defun deft-no-recursivo ()
    "Hace que `deft' no busque en subdirectorios."
    (interactive)
    (setq deft-recursive nil)
    (deft-refresh))

  (global-set-key (kbd "C-<f5>") #'deft-cambio-dir)
  (global-set-key (kbd "M-<f5>") #'deft-recursivo)
  (global-set-key (kbd "S-<f5>") #'deft-no-recursivo)

Se han añadido tres funciones para controlar qué notas aparecen en el listado de deft. La primera deft-cambio-dir modifica el directorio que se cargará. Por defecto se establece a ~/Nextcloud/Notes, pero se puede establecer a cualquier otro. Al cambiar de directorio se refresca el listado de notas. También se puede hacer que busque en subdirectorio o no. Las teclas mapeadas para estas funciones son:

  • C-<f5> cambia el directorio.
  • M-<f5> hace la búsqueda de notas recursiva en subdirectorios.
  • S-<f5> restringe la búsqueda al directorio seleccionado.

Paquetes de programación

auto-tangle

El paquete org-auto-tangle se utiliza para que al guardar un archivo org que estamos editando, automáticamente haga el tangle del código a sus correspondientes ficheros. Si se usa la programación literaria es un paquete muy útil que nos ahorra tiempo (y nos evita errores).

  (use-package org-auto-tangle
    :defer t)
    ;; :hook (org-mode . org-auto-tangle-mode)
    ;; :config
    ;; (setq org-auto-tangle-default t))

Comprobación de código

El paquete flycheck comprueba el código al vuelo detectando errores y avisando de posibles problemas. Hay que instalar también los paquetes para cada lenguaje de programación utilizado.

  ;; configuración para flycheck
  (use-package flycheck
    :ensure t
    :init (global-flycheck-mode))

Control de versiones

Otras herramientas importantes son las destinadas al control de versiones: magit y va-fossil. Cada una de estas aportan facilidades para el uso de git y de fossil respectivamente.

  ;;magit
  (use-package magit
    :ensure t)
  ;; fossil
  (use-package vc-fossil
    :defer t)

Gestión de proyectos

La gestión de proyectos la realiza projectile. La instalación es muy básica: se le dice un directorio donde los guardamos y también se activa el completado con ivy.

  ;; Configuración para projectile
  (use-package projectile
    :ensure t
    :bind-keymap (("C-c p" . projectile-command-map))
    :init
    (setq projectile-project-search-path '("~/proyectos/"))
    (setq projectile-completion-system 'ivy)
    (projectile-mode t))
  ;; autocompletado para `projectile'
  (use-package flycheck-projectile
    :ensure t
    :defer t)

Cursores múltiples

El paquete iedit permite modificar el nombre de una variable en todas las apariciones que haga en un buffer a la vez. En la configuración de teclas generales utilizo la combinación C-v para activarlo y desactivarlo. El procedimiento es muy sencillo:

  1. Situar el punto sobre la variable cuyo nombre queremos modificar.
  2. Activar iedit. Mostrará el nombre remarcado a lo largo del buffer.
  3. Modificar el texto resaltado. Veremos cómo se van cambiando también el resto de apariciones del nombre.
  ;; Configurar ‘iedit’
  (use-package iedit
    :ensure t)

Árbol de directorios

Mientras programo o escribo me gusta tener la barra de directorios situada a la izquierda del frame y poder acceder a toda la funcionalidad que proporciona dired sin necesidad de abrir toda una sucesión de buffers. Además, utilizo la integración de git con dired y la utilización de iconos más vistosos con el paquete all-the-icons.

  ;; Ajustes de dired-sidebar
  ;;(setq dired-sidebar-subtree-line-prefix "->")
  (use-package dired-sidebar
    :ensure t
    :defer t
    :commands (dired-sidebar-toggle-sidebar)
    :init
    (setq dired-sidebar-theme 'nerd)
    (setq dired-sidebar-use-term-integration t)
    (setq dired-sidebar-use-custom-font t))

  (use-package dired-git
    :ensure t)

  (use-package all-the-icons
    :ensure t)
  (use-package all-the-icons-dired
    :ensure t)
  (use-package all-the-icons-ibuffer
    :ensure t
    :init (all-the-icons-ibuffer-mode t))

Lista de buffers

El siguiente paquete me permite abrir una lista de buffers en la sidebar, compartiéndola con el anterior dired-sidebar.

  (use-package ibuffer-sidebar
    :defer t)

Soporte para autocompletado

Es el modo general de autocompletado de Emacs. Para algunos lenguajes se deben instalar los paquetes específicos.

  ;; Activar autocompletado general
  (use-package company
    :ensure t
    :init
    (setq company-tooltip-align-annotations t)
    :config
    (global-company-mode t))

Soporte para la comprobación de sintaxis

  (use-package flycheck
    :ensure t
    :defer t)

Lenguajes de marcado de texto

Soporte para asciidoc

No lo uso mucho… hace un tiempo colaboré con un proyecto que utilizaba como lenguaje de formateo el asciidoc y aún no lo he quitado… por si lo vuelvo a necesitar.

  ;; Paquete para asciidoc
  (use-package adoc-mode
    :defer t)
  (add-to-list 'auto-mode-alist '("\\.asciidoc\\'" . adoc-mode))

Soporte para LaTeX

Configuración para LaTeX. El soporte de TeX en general viene con la instalación base de Emacs. Lo único que hago en esta configuración es ajustar algunos comportamientos. También tuve un tiempo instalado el paquete ox-tufte, que proporciona la posibilidad de exportar un documento para el paquete de LaTeX tufte. Los documentos que genera ese paquete son realmente vistosos, si se trata de maquetar un libro: una columna con un amplio margen donde mostrar notas, gráficos y tablas pequeñas. Realmente interesante.

  ;; Ajustes para AUCTeX
  (setq TeX-view-program-selection
        '(((output-dvi has-no-display-manager)
           "dvi2tty")
          ((output-dvi style-pstricks)
           "dvips and gv")
          (output-dvi "xdvi")
          (output-pdf "xdg-open")
          (output-html "xdg-open")))
  (add-hook 'LaTeX-mode-hook (lambda ()(TeX-electric-math t)))
  (add-hook 'LaTeX-mode-hook 'turn-on-cdlatex)               ;Activar CDLaTeX
  (add-hook 'LaTeX-mode-hook (lambda ()(company-mode 1)))    ;Activar Autocompletado
  (company-auctex-init)
  (add-hook 'LaTeX-mode-hook (lambda ()(TeX-fold-mode 1)))   ;Activar el plegado
  (add-hook 'LaTeX-mode-hook 'latex-extra-mode)
  (add-hook 'LaTeX-mode-hook 'display-line-numbers-mode)

  ;; (use-package ox-tufte
  ;;   :defer t)

Gestión de citas bibliográficas

Normalmente gestiono las citas bibliográficas en formato bib con la aplicación JabRef. Sin embargo, me he encontrado en ocasiones la necesidad de gestionarlas en CSL (Citation Style Language). El paquete citeproc permite dicha gestión y para hacerlo desde org-mode se necesita el paquete citeproc-org

  (use-package citeproc
    :defer t
    :ensure t)
  (use-package citeproc-org
    :defer t
    :ensure t
    :after citeproc)

Soporte para PlantUML

Uno de los paquetes más útiles para hacer gráficos, desde org-mode también, es PlantUML. Como su nombre indica su especialidad son los esquemas gráficos UML, pero también realiza multitud de diagramas no UML, como los ditaa, Gantt, mapas mentales, etc. El la configuración de variables se ajusta la localización del ejecutable jar (es una herramienta Java).

  (use-package plantuml-mode
    :defer t)

Soporte para ficheros gráficos pikchr

El sistema de generación de gráficos pikchr es heredero de la herramienta pic de U*ix y su versión libre gpic. En mi blog hay una explicación más extensa sobre la herramienta.

  (use-package pikchr-mode
    :defer t)

web-mode

Este modo viene por defecto instalado con Emacs, tan solo añado algunas extensiones de archivo a la lista que se deben tratar con el modo.

  ;; Configurar web-mode
  (use-package web-mode)
  (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.js[x]?\\'" . web-mode))

Lenguajes de programación

scheme

Entorno de programación para scheme.

  (use-package geiser
    :ensure t
    :defer t)

  (use-package geiser-guile
    :after geiser
    :defer t)

  (use-package flycheck-guile
    :defer t)

lisp

Entorno de programación para lisp.

  (use-package slime
    :defer t
    :config
    (setq inferior-lisp-program "/usr/bin/sbcl"))

  (use-package slime-company
    :defer t
    :after slime)

Clojure

Entorno de programación para Clojure.

  (use-package clojure-mode
    :defer t)
  (use-package cider
    :defer t)
  (use-package flycheck-clojure
    :defer t)
  (use-package clojure-snippets
    :ensure t)
  (use-package ivy-clojuredocs
    :ensure t)
  (use-package clj-refactor
    :defer t)
  (use-package cljr-ivy
    :defer t)

Además se puede instalar información sobre el lenguaje para consultarlo directamente desde Emacs

  (use-package clojure-essential-ref
    :defer t
    :bind (
           :map cider-mode-map
           ("C-h F" . clojure-essential-ref)
           :map cider-repl-mode-map
           ("C-h F" . clojure-essential-ref)))

lua

Paquetes para la programación con el lenguaje lua. También hay un paquete para gestionar lua-rocks, la herramienta de control de paquetes del lenguaje, pero que instalo porque tampoco utilizo demasiado éste.

  (use-package lua-mode
    :defer t)
  ;; autocompletado para `lua'
  (use-package company-lua
    :defer t)
  (use-package flymake-lua
    :defer t)

Tcl/Tk

El lenguaje Tcl/Tk es otro de los soportados por Emacs sin necesidad de instalar nada. Lo único que hago es añadir a la lista de extensiones automáticas la extensión .test para que la admita como propia de Tcl y facilitarme la edición de las pruebas unitarias.

  ;; Añadir extensión `.test' para `tcl-mode'
  (add-to-list 'auto-mode-alist '("\\.test\\'" . tcl-mode))

Soporte C++

  (use-package modern-cpp-font-lock
    :ensure t
    :init
    (add-hook 'c++-mode-hook #'modern-c++-font-lock-mode))

Programación en Python

Últimamente no utilizo demasiado el lenguaje Python. Dicho lenguaje cuenta con paquete instalado con la base de Emacs pero sólo colorea sintaxis y poco más. El paquete elpy proporciona las herramientas necesarias para trabajar con Python en Emacs. También puedes configurar elpy llamando a elpy-config, pero exige tener instalada la aplicación pip para poder instalar los paquetes de Python que se necesiten.

Otra opción sería instalar lsp y el soporte para este lenguaje.

  ;; Configuración del entorno elpy para Python
  (use-package elpy
    :ensure t
    :defer t
    :config
    (setq python-shell-interpreter "python3")
    (setq elpy-rpc-python-command "python3")
    :init
    (advice-add 'python-mode :before 'elpy-enable))

Programación en erlang

El paquete edts proporciona todas las herramientas necesarias para programar en erlang en Emacs. También se puede recurrir a la instalación del paquete lsp y el servidor específico de erlang para hacerlo. Pero esto es mucho más simple.

  ;; Configurar el sitio de erlang
  (use-package edts
    :defer t)

Programación en julia

  (use-package julia-mode
    :defer t)
  (use-package julia-repl
    :defer t
    :init
    (add-hook 'julia-mode-hook 'julia-repl-mode))
  (use-package flycheck-julia
    :defer t)

Fin

Modificación de tipos de letra

Se modifica el aspecto de algunos tipos de letra, concretamente el tipo por defecto será DejaVu Sans Mono.

También se cambian los tamaños de los encabezados cuando Emacs se encuentre en modo presentación con org-tree-slide, para hacerlos más grandes y más similares a lo que la gente espera en una presentación.

También se modifica el color de la etiqueta de la perspectiva seleccionada. Se establece el color a amarillo utilizando la tipografía normal. Por defecto es rojo y negrita y me resulta fea.

  ;; Ajustes de fuentes y tipos de letra
  (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 98 :width normal))))
   '(org-tree-slide-heading-level-1 ((t (:inherit outline-1 :weight bold :height 3.5))))
   '(org-tree-slide-heading-level-2 ((t (:inherit outline-2 :weight bold :height 2.5))))
   '(org-tree-slide-heading-level-3 ((t (:inherit outline-3 :weight bold :height 1.5))))
   '(persp-selected-face ((t (:foreground "yellow" :weight normal)))))

Finalización del archivo con las instrucciones que mandan las buenas formas de elisp. Si no se usan el init.el funcionaría igual, pero quedan así mejor.

Finalización correcta del fichero

  (provide 'init)
  ;;; init.el ends here