Comandos, módulos, marca, punto y otras zarandajas
Hasta ahora hemos venido trabajando directamente en el buffer
*scratch*
y todo ha ido funcionando bien, aunque nuestras funciones
y llamadas eran más bien efímeras. En este artículo vamos a guardar
el código, por primera vez, en un módulo, librería, fichero, o como lo
queráis llamar.
Tradicionalmente los ficheros que nos sirven de librerías o módulos,
para marcarlos como elisp, llevan una extensión .el
. Cargar uno de
esos módulos o librerías se puede hacer de muchas maneras. Por
ejemplo, Emacs cuando se inicia busca el código en el fichero
especial init.el
. Si queremos que nuestro código esté siempre
accesible, ese es el lugar apropiado para configurarlo. No voy a
entrar ahora a detallar cómo hacer un módulo para establecer un modo
de Emacs, me quedaré en algo más básico: crear un par de funciones
interactivas o comandos que nos permitan llamarlas desde el
minibuffer
con M-x
.
Un poco de código en un fichero
Voy a poner un ejemplo sencillo, y por tanto inútil, de lo que puede
representar un módulo o librería. Supongamos que quiero solucionar un
problema, acelerando la inserción de etiquetas en mis ficheros html
.
Concretamente las etiquetas de negrita, que es muy cansado escribir
<b></b>
cada vez que toca. Lo suyo además es que me deje el cursor,
lo que en emacs se llama punto, situado entre las etiquetas para
escribir cómodamente lo que sea. Veamos el siguiente código:
(defun insertar-etiqueta-negrita () "Inserta un par de etiquetas <b></b> en el punto del cursor." (interactive) (insert "<b></b>") (backward-char 4))
Definimos una función llamada insertar-etiqueta-negrita
que hace
justo lo que dice su cadena de documentación. Es una función
sencilla y no necesitará que se le introduzcan datos a través de
parámetros, por eso su lista de parámetros está vacía. Lo primero que
vemos en el cuerpo de la función es interactive
, una forma
especial que hace que nuestra función se convierta en un comando al
que se le puede llamar desde M-x
. La siguiente forma insert
insertará la cadena que queremos, en nuestro caso, la cadena contiene
las etiquetas de apertura y cierre de negrita en html
. Por último le
decimos que retrase el punto cuatro caracteres para que se quede
entre ambas. Bien, ese código lo vamos a guardar en un fichero que
podemos llamar, por ejemplo, negrita.el
.
Una vez guardado, sin haber evaluado el código si pulsamos M-x
y
llamamos a insertar-etiqueta-negrita
nos dará un error. El sistema
no encontrará dicha función. ¿Cómo puedo cargarla desde el fichero?
Podríamos por ejemplo, abrir el fichero y evaluar el código, pero lo
que nos facilita el proceso es que con load-file
emacs hace las
dos cosas sobre la marcha. Así si utilizamos M-x load-file
y le
decimos que cargue el fichero negrita.el
, automágicamente
tendremos disponible nuestra función.
Vamos a seguir con el ejemplo un poco... Vamos a suponer que se da el
siguiente caso: ya he escrito todo el texto que debería ir en negrita
y no he escrito las etiquetas, porque soy así de torpe. Lo puedo
solucionar de dos maneras. La primera sería escribirlas manualmente al
principio y al final. La segunda escribir las dos etiquetas juntas en
un extremo y corto-pegar la otra en el otro... o una tercera,
teniendo como tenemos el poder en la punta de los dedos, escribir una
función que lo haga por mí. La forma debería escribir en el inicio
la etiqueta <b>
y en el final la etiqueta </b>
. Veamos el
siguiente código:
(defun marcar-negrita-region (inicio fin) "Inserta una marca <b></b> en torno a una región." (interactive "r") (save-excursion (goto-char fin) (insert "</b>") (goto-char inicio) (insert "<b>")))
Vemos una función marcada como interactive
, aunque es un poco
distinta a la anterior, lleva aparejada una "r"
para marcar que es
de una clase especial. La forma interactive
tiene varios códigos
según lo que se quiera hacer con ella. Si miramos qué es lo que
significa esa r
en el enlace anterior nos dirá que se utilizarán el
punto y la marca como parámetros para la función.
El punto he dicho ya que es la posición del cursor dentro del
buffer, pero ¿qué es la marca? La marca es otro valor que está
en el buffer, lo activamos con el comando set-mark-command
,
normalmente asociada a la combinación C-<SPC>
, para marcar el texto
que se sitúe entre los dos valores.
Bien, la siguiente forma que nos encontramos es save-excursion
.
Básicamente lo que hace es guardar los valores de posición del cursor
─o punto─ para poder recuperarlo y dejarlo como estaba aunque en su
cuerpo se mueva el mismo, como hacemos con las llamadas a
goto-char
. En esta función, lo que se hace es saltar al final,
proporcionado por el argumento fin
para introducir la etiqueta de
cierre de negrita y luego al inicio
para introducir la etiqueta de
comienzo de negrita. Cuanto save-excursion
termina, tanto el punto
como la marca están en el sitio que tenían antes de llamar a nuestra
función.
Si hemos guardado el código en nuestro fichero, lo podemos recargar de
nuevo llamando al comando load-file
y nuestra nueva función estará
disponible.
Alguien dirá que no hemos avanzado mucho: en lugar de escribir
<p></p>
tenemos que escribir M-x nombre-de-la-función
, que es
bastante más largo, así que no hemos ganado nada. Se olvidan que
podemos establecer en nuestro código los atajos que queramos. Es
habitual que en emacs se dejen las combinaciones de C-c
para este
tipo de cosas. Cada modo utiliza los suyos, y vemos que según el
tipo de archivo que estemos editando C-c C-c
, la combinación de
teclas superocupada hace cosas distintas. En nuestro caso, podemos
por ejemplo establecer los siguientes atajos en el código:
;; Asignación de combinaciones de teclas globales (global-set-key (kbd "C-c b") 'insertar-etiqueta-negrita) (global-set-key (kbd "C-c B") 'marcar-negrita-region)
Conclusión
Ha sido un repaso muy rápido a las funciones que vamos a emplear como comandos de nuestros programas. Pero los conceptos, ─dados así a grandes rasgos─, son sencillos de entender.