Configuración de Emacs paso a paso (02)

Paquetes básicos de interfaz con el usuario e instalación del tema gráfico.

/images/emacs_logo_round.png

En este artículo vamos a continuar configurando nuestro Emacs añadiendo unos cuantos paquetes útiles a nuestra configuración. Añadiremos una serie de paquetes para hacer más fácil el acceso a funciones básicas del editor y por último instalaremos un tema gráfico. Es decir un fichero que configura el aspecto visual de nuestro editor.

ace-windows

Emacs es un software que se inventó bastante antes del concepto de ventanas que manejamos ahora en casi todos los sistemas operativos. Por esa razón usa una terminología algo arcaica. Las ventanas que conocemos en cualquier entorno gráfico se llaman frames en Emacs y las secciones en las que podemos dividir una ventana del editor se llaman windows.

Para que quede claro puedes probar a dividir tu pantalla de Emacs en varias ventanas usando C-x 2 o C-x 3 unas cuantas veces. Si lo que quieres es abrir un nuevo frame el comando sería C-x 4 f

ace-windows es un paquete que nos ayuda cuando tenemos varias windows de Emacs y queremos cambiar de ventana con el comando C-x o. Todas las ventanas abiertas mostrarán un número y no tenemos más que teclear el número elegido para saltar a la ventana que queramos.

* ace-windows
  To jump to different windows easily
  #+begin_src emacs-lisp
  (use-package ace-window
    :ensure t
    :init
    (global-set-key [remap other-window] 'ace-window)
    (custom-set-faces
     '(aw-leading-char-face
       ((t (:inherit ace-jump-face-foreground :height 3.0)))))
    )
  #+end_src

which-key

which-key es un paquete que nos facilita la vida al teclear comandos. Prueba a teclear C-x (el prefijo de muchísimos comandos en nuestro editor) antes y después de instalar el paquete para ver la diferencia.

  • which-key nos permite ir construyendo el comando poco a poco, podemos borrar el último caracter introducido con C-h u
  • Si tenemos varias páginas de posibles combinaciones podemos usar C-h n y C-h p para movernos a la siguiente (next) o anterior (prior)
  • Si ponemos el cursor del ratón encima de alguna de las sugerencias que nos aparecen en la miniconsola veremos un texto de documentación del comando.
  • C-h a aborta el comando

which-key funcionará incluso con los atajos de teclado que nosotros configuremos. En cambio no funcionará con M-x (execute-extended-command) y es buena cosa que no lo haga. Se calcula que Emacs es capaz de ejecutar unos diezmil comandos y eso antes de que instalemos ningún paquete opcional. De todas formas en el siguiente apartado instalaremos un paquete que nos ayudará con eso también.

* which-key
  Some help with hotkeys
  #+begin_src emacs-lisp
    (use-package which-key
      ;; give us help for keys in RT
      :ensure t
      :config (which-key-mode))
  #+end_src

ivy-counsel-swipper

Vamos a instalar tres paquetes que trabajan en equipo y mejoran muchísimo la experiencia de usuario en Emacs.

ivy es un gestor de listas. La lista gestionada puede ser de casi cualquier cosa. Podría ser una lista de ficheros si hemos invocado la función de cargar fichero. O podría ser una lista de coincidencias si estamos buscando una palabra en el editor, o una lista de comandos si estamos tecleando un comando en el minibuffer.

ivy por si solo sería un poco difícil de usar, así que se instalan también swipper que nos va a dar un interfaz de búsquedas mejorado dentro del fichero que estamos editando, y counsel que añade muchas funcionalidades apoyándose en ivy. En realidad si instalamos counsel los otros dos paquetes vienen como dependencias.

Una vez instalados los paquetes no tenemos más que teclear M-x para verlos en acción. Si os fijais ivy añade un caracter ‘^’ a la cadena de búsqueda. Ese caracter significa “principio de la cadena” en regexp, así que si tecleo window, ivy filtrará todos los comandos que empiecen por window. Si borro el ‘^’ y tecleo window, entonces ivy me devolverá todos los comandos que contengan la cadena window. Ya veis que con la funcionalidad combinada de counsel e ivy puedo buscar comandos en el minibuffer de M-x sin saber exactamente como se llaman.

* ivy - counsel - swipper
  An enhanced incremental search and a lot of features from counsel
  #+begin_src emacs-lisp
    (use-package counsel
      :ensure t
      :bind
      (("C-S-o" . counsel-rhythmbox)
       ("M-x" . counsel-M-x)
       ("C-x C-f" . counsel-find-file)
       ("<f1> f" . counsel-describe-function)
       ("<f1> v" . counsel-describe-variable)
       ("<f1> l" . counsel-load-library)
       ("<f2> i" . counsel-info-lookup-symbol)
       ("<f2> u" . counsel-unicode-char)
       ("C-c g" . counsel-git)
       ("C-c j" . counsel-git-grep)
       ;; ("C-c k" . counsel-ag)    requires installation: apt install silversearcher-ag
       ("C-x l" . counsel-locate)
       ("M-y" . counsel-yank-pop)
       :map ivy-minibuffer-map
       ("M-y" . ivy-next-line))
      )
    ;; Takes care of elections menus
    (use-package ivy
      :ensure t
      :diminish (ivy-mode)
      :bind
      (("C-x b" . ivy-switch-buffer)
       ("<f6>" . ivy-resume)
      )
      :config
      (ivy-mode 1)
      (setq ivy-use-virtual-buffers t
            ivy-count-format "%d/%d "
            ivy-display-style 'fancy)
      )

    (use-package swiper
      :ensure t
      :bind
      (("C-s" . swiper-isearch)
       ("C-r" . swiper-isearch-backward)
       :map minibuffer-local-map
       ("C-r" . counsel-minibuffer-history)
      )
      :config
      (ivy-mode 1)
      (setq ivy-use-virtual-buffers t)
      )
  #+end_src

Merece la pena leer los manuales de los paquetes y este artículo también está muy bien.

Algo que me despistó un poco al principio fue el diálogo de abrir ficheros C-x C-f. A veces el autocompletado de ivy nos puede interferir, por ejemplo si queremos abrir un nuevo fichero llamado test y en ese directorio ya existe test.txt, el autocompletado siempre nos abrirá el segundo en lugar de crear el primero. El problema se resuelve tecleando C-M-j (ivy-inmediate-done) para ejecutar la acción de abrir fichero justo con la cadena que hemos tecleado y no con el autocompletado.

Si no te convencen estos paquetes, se supone que el paquete Helm es una alternativa a la combinación de estos tres, pero nunca lo he probado.

hydra

hydra permite montar “árboles de comandos” en la configuración propuesta vienen tres árboles configurados: uno de comandos que conmutan entre dos estados, uno de comandos de navegación, y otro de comandos para org-mode

Más adelante usaremos hydra para implementar nuevos árboles de comandos.

* hydra
Defines command trees (so to speak)
#+begin_src emacs-lisp
  (use-package hydra
    :ensure t)
#+end_src

** Hydra for toggle modes
#+begin_src emacs-lisp
  (global-set-key
   (kbd "C-x t")
   (defhydra toggle (:color blue)
     "toggle"
     ("a" abbrev-mode "abbrev")
     ("s" flyspell-mode "flyspell")
     ("d" toggle-debug-on-error "debug")
     ("c" fci-mode "fCi")
     ("f" auto-fill-mode "fill")
     ("t" toggle-truncate-lines "truncate")
     ("w" whitespace-mode "whitespace")
     ("q" nil "cancel")
     )
   )
#+end_src

** Hydra for navigation
#+begin_src emacs-lisp
  (global-set-key
   (kbd "C-x j")
   (defhydra gotoline
     (:pre (linum-mode 1)
      :post (linum-mode -1))
     "goto"
     ("t" (lambda () (interactive)(move-to-window-line-top-bottom 0)) "top")
     ("b" (lambda () (interactive)(move-to-window-line-top-bottom -1)) "bottom")
     ("m" (lambda () (interactive)(move-to-window-line-top-bottom)) "middle")
     ("e" (lambda () (interactive)(end-of-buffer)) "end")
     ("c" recenter-top-bottom "recenter")
     ("n" next-line "down")
     ("p" (lambda () (interactive) (forward-line -1))  "up")
     ("g" goto-line "goto-line")
     )
   )
#+end_src

** Hydra for some org-mode stuff
#+begin_src emacs-lisp
  (global-set-key
   (kbd "C-c t")
   (defhydra hydra-global-org (:color blue)
     "Org"
     ("t" org-timer-start "Start Timer")
     ("s" org-timer-stop "Stop Timer")
     ("r" org-timer-set-timer "Set Timer") ; This one requires you be in an orgmode doc, as it sets the timer for the header
     ("p" org-timer "Print Timer") ; output timer value to buffer
     ("w" (org-clock-in '(4)) "Clock-In") ; used with (org-clock-persistence-insinuate) (setq org-clock-persist t)
     ("o" org-clock-out "Clock-Out") ; you might also want (setq org-log-note-clock-out t)
     ("j" org-clock-goto "Clock Goto") ; global visit the clocked task
     ("c" org-capture "Capture") ; Don't forget to define the captures you want http://orgmode.org/manual/Capture.html
     ("l" (or )rg-capture-goto-last-stored "Last Capture")
     )
   )
#+end_src

avy

avy es un paquete que permite moverse rápidamente por el fichero editado sin usar el ratón. Con la configuración que ves aquí te permite teclear dos caracteres y marcará todas las coincidencias en el fichero cada una con una letra-atajo diferente. Puedes moverte a cualquier coincidencia sin mas que teclear su código. La verdad es que no la uso mucho.

* avy
  #+begin_src emacs-lisp
    ;; avy
    (use-package avy
      :ensure t
      :config
      (avy-setup-default)
      :bind(
            ("M-g c" . avy-goto-char-2)
            )
      )
  #+end_src

iedit

iedit es mucho más interesante, si entramos en el iedit-mode pulsando C-; iedit seleccionará todas las ocurrencias, en todo el fichero, del símbolo bajo el cursor (o de lo que tengamos selecionado en la región si está activa) y nos permitirá editar todas las ocurrencias de una sola vez. Con iedit activado la combinación M-h lo restringe a la función actual (muy útil si estamos programando). Hay muchas mas formas de restricción, lo mejor es leer la descripción del modo (C-h m iedit-mode). Cuando terminemos la edición pulsamos de nuevo C-;

* iedit
Interactive edition of all ocurrences of X
  #+begin_src emacs-lisp
    (use-package iedit
      :ensure t)
  #+end_src

color-theme

Aun no he trabajado mucho en los temas, tengo configurado el leuven_theme y parece que hace un buen trabajo. Los ficheros org-mode se ven bien y no tengo ningún problema editando texto o programando.

Aun no tengo ningún tema dark bien probado. Y también tengo pendientes investigar los temas doom. Si consigo probarlos a tiempo les dedicaré un artículo dentro de esta serie.

(use-package color-theme-modern
  :ensure t)
(use-package leuven-theme
  :ensure t
  ;; :config
  ;; (load-theme 'leuven-dark t)
  ;; (setq leuven-scale-outline-headlines t)
  ;; (setq leuven-scale-org-agenda-structure nil)
  )

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. En realidad el único fichero que tienes que actualizar es el myinit.org. El init.el debería cambiar automaticamente sin intervención de nadie.

Referencias