Copyright (c) 2003 Eduardo Ferro bajo GNU FDL
Emacs es uno de los editores más conocidos en el entorno UNIX y
dejando de lado las guerras santas Emacs vs Vi, ha demostrado ser uno de los
editores preferidos para la programación en esos entornos.
Para la edición cómoda de ficheros fuente se suelen requerir a los editores
las siguientes funcionalidades:
Ni que decir tiene que emacs cuenta con estas y otras funcionalidades, por lo que en este artículo voy a intentar describir la forma de activar y usar todas y cada una de las funcionalidades indicadas. No vamos a tratar en este artículo el uso básico de emacs puesto que sobre ese tema existen muy buenas referencias en Internet y además daría para escribir no uno sino varios libros, así que supongo los conceptos básicos de emacs (buffers, modos, cortar, pegar, ayuda, etc) son conocidos.
Emacs usa como fichero de configuración por defecto el fichero ".emacs" en el directorio del usuario ($HOME/.emacs). Emacs utiliza para su configuración y extensión un dialecto del lisp conocido como EmacsLisp o más comúnmente elisp. El fichero .emacs es simplemente un fichero de código elisp que emacs carga en su arranque, por lo que un conocimiento somero de elisp será muy conveniente para el uso avanzado de emacs. Por ahora nos bastará con saber que las sentencias van encerradas entre paréntesis, y que todo lo que siga a un ";" hasta el final de la línea será considerado comentario.
En los siguientes apartados vamos a ir describiendo sentencias de elisp, que introducidas en nuestro fichero de configuración .emacs nos ayudarán a la hora de editar ficheros fuentes.
Para activar el realzado de las coincidencias encontradas hasta el momento en las búsquedas, debemos poner las siguientes sentencias:
(setq search-highlight t) (setq query-replace-highlight t)
Antes de poder realizar configuraciones sobre el comportamiento de los modos C y C++ debemos introducir en el fichero de configuración la siguiente sentencia:
(require 'cc-mode) ; modo para C/C++Cuando escribimos un fichero fuente o cuando escribimos un fichero de texto suele ser interesante que el editor decida cuando no caben más palabras en en la línea actual y pase a la siguiente. Esta funcionalidad en emacs se conoce como "auto-fill". Con la siguiente sentencia indicamos que la columna donde deben terminar las líneas es la 77 y que debe activar el modo "auto-fill" para todos los modos derivados del modo de texto y en los modos para C y C++:
(setq default-fill-column 77) (add-hook 'text-mode-hook 'turn-on-auto-fill) (add-hook 'c++-mode-hook 'turn-on-auto-fill) (add-hook 'c-mode-hook 'turn-on-auto-fill)Por defecto en emacs, si vamos al final del fichero y pulsamos el cursor para ir hacia abajo emacs introduce un salto de linea, pero a veces este comportamiento no es el deseado. Con la siguiente sentencia podemos evitarlo:
; no añade lineas vacías al final (setq next-line-add-newlines nil)Suele ser interesante en los lenguajes de programación que cuando cerremos una llave o paréntesis, emacs nos señale a qué llave o paréntesis de apertura se corresponde. Para ello debemos introducir en el fichero de configuración la siguiente sentencia:
; Para que se marquen los paréntesis y ; y las llaves (require 'paren)En muchos lenguajes de programación el sangrar las líneas de forma correcta es fundamental para su correcta legibilidad y su facilidad de mantenimiento. Por ello, es muy importante realizar un sangrado del código correcto. El sangrado del código se puede realizar mediante la inserción de tabuladores o la inserción de espacios en blanco. Cualquiera de las dos soluciones es adecuada, pero desgraciadamente es muy posible, que sin querer, mezclemos las dos, en cuyo caso el fichero fuente sólo se vería bien si tenemos la tabulación configurada al mismo tamaño que el que editó el fichero. Para solucionar este problema lo que se suele hacer es utilizar espacios, pero dejar que sea emacs el que decida cuántos espacios se deben utilizar. Las siguientes líneas configuran emacs para que inserte siempre espacios y para que en los modos de C y C++ el tabulador sangre la línea actual (utilizando espacios), excepto en el caso de que estemos dentro de cadenas literales:
; No sangra si estamos en literales (setq c-tab-always-indent "other") ; Espacios en vez de tabuladores (setq-default indent-tabs-mode nil)
;; Coloreado automático de sintaxis para todos los modos reconocidos (global-font-lock-mode t) (setq font-lock-support-mode 'lazy-lock-mode) ; No existe tamaño máximo de buffer para ; colorear los buffers (setq font-lock-maximum-size nil) (require 'font-lock) (require 'lazy-lock)Realmente, la única sentencia necesaria es
(global-font-lock-mode
t), que activa el modo de realzado automático mediante colores, el
resto de líneas indican que por defecto se use el modo "vago"
(lazy-lock-mode) es decir que no esté todo el rato verificando
la sintaxis para realzarla porque consume demasiados recursos (y el modo
"vago" es suficientemente bueno). También le indicamos que aunque el fichero
sea muy grande realice el coloreado aunque tarde un poco más.
Emacs tiene una gran cantidad de configuraciones relacionadas con el realzado de sintaxis mediante colores. Se pueden configurar cada uno de los colores usados para cada tipo de entidad (palabras clave, comentarios, funciones, variables, etc) e incluso configurar nuevas entidades, pero no nos vamos a meter con ello, porque la configuración por defecto es bastante buena.
Además es muy útil indicar a emacs que cuando terminamos una sentencia mediante un retorno de carro, lo que queremos hacer es saltar a la siguiente línea y realizar el sangrado, de forma que el cursor quede preparado para insertar la siguiente sentencia en el sitio correcto. Este comportamiento lo conseguimos con las siguientes sentencias:
; Retorno de carro cambia de línea y realiza el sangrado ; en la siguiente linea (define-key c-mode-map "\C-m" 'newline-and-indent) (define-key c++-mode-map "\C-m" 'newline-and-indent)Cuando veamos que emacs ha sangrado algo aparentemente mal deberemos repasar la sintaxis de las líneas anteriores, porque lo más probable es que tengamos un error de sintaxis en el fichero. Lo que podemos hacer, en caso de que nos cueste ver el error, es subir hasta la ultima línea que este correctamente sangrada y desde allí ir bajando poco a poco pulsando tabulador (para sangrar la línea) hasta que veamos qué línea es la que se sangra mal. Esa línea o la anterior será la que contenga el error de sintaxis. Como podéis ver, esta funcionalidad no sólo nos permite hacer nuestro código más legible (y por tanto de mejor calidad), sino que además nos ayuda a encontrar pequeños problemas sintácticos.
En algunos, casos es posible que necesitemos sangrar una región, por ejemplo
porque hemos pegado código desde otro sitio y no ha quedado con el sangrado
correcto. En estos casos, debemos utilizar el comando de sangrado de una región
Alt-x indent-region, una vez tengamos seleccionada la región a
sangrar.
Si estamos programando en C o C++ también podemos usar el comando Alt-x
c-indent-defun, que se encargará del sagrado de la función o método en
el que estemos. Esta función suele estar asignada a la combinación de teclas
Ctrl-c Ctrl-q.
(define-key global-map [(control return)] 'dabbrev-expand)Siendo "control return" la combinación de teclas elegida para la expansión. Para hacer uso de esta funcionalidad, simplemente debemos escribir al menos tres letras de la palabra que queremos escribir y pulsar Ctrl-Return repetidamente hasta que demos con la expansión que queremos.
Emacs también permite la definición manual de abreviaturas mediante el modo "abbrev-mode" (ver manual de emacs).
Una de las posibilidades es usar el navegador de objetos y ficheros llamado speedbar. Para ello debemos introducir la siguiente línea en el fichero de configuración:
(require 'speedbar)Y luego una vez estemos ejecutando emacs podremos ejecutar el navegador introduciendo
Alt-x speedbar. Una vez ejecutemos este comando, nos aparecerá
una nueva ventana de emacs con todos los ficheros y directorios del directorio
actual. El navegador Speedbar muestra la información en forma de árbol, cada
nodo se puede expandir o contraer, en caso de que el nodo que expandamos sea
de un fichero nos aparecerán cada una de las clases, métodos o funciones que
hayamos definido en ese fichero.
Según editamos los ficheros fuente, el navegador ira analizándolos para poder ir actualizando la lista de ficheros y nodos, pero en algunos casos el speedbar tardará en actualizarse por lo que es posible que no siempre este completamente sincronizado.
tempo-define-template, esta función tiene como primer parámetro
el nombre de la plantilla, como segundo la propia plantilla, como tercero la
cadena que se debe expandir, como cuarto parámetro una cadena con la
descripción de la plantilla y por ultimo el nombre de la tabla de plantillas
donde queremos definirla (esto es necesario porque podríamos querer tener
distintas plantillas con el mismo nombre en diferentes tablas).
(tempo-define-template "c-if"
'(> "if (" p ")" n>
"{" > n
> p n
"}" > n>
)
"if"
"Inserta un if de c/c++"
'c-tempo-tags)
Esta plantilla tiene como nombre "c-if", la cadena a expandir es "if" y se
introduce en la tabla de plantillas "c-tempo-tags".
Con las siguientes sentencias en el fichero de configuración preparamos todo lo necesario para poder crear plantillas para los modos C y C++:
(require 'tempo) (setq tempo-interactive t) (defvar c-tempo-tags nil "tabla de plantillas tempo para el modo C") (defvar c++-tempo-tags nil "tabla de plantillas tempo para el modo C++") ; Asignamos la tabla de plantillas para C/C++ a los ; modos de C y C++ (add-hook 'c-mode-hook '(lambda () (tempo-use-tag-list 'c-tempo-tags) )) (add-hook 'c++-mode-hook '(lambda () (tempo-use-tag-list 'c-tempo-tags) (tempo-use-tag-list 'c++-tempo-tags) ))Después de este código para la creación de las tablas y la carga de las mismas, podemos introducir en el fichero de configuración las plantillas que hayamos definido.
Para usar las plantillas, mientras estemos programando, deberemos introducir
una de las cadenas que hemos definido para la expansión, por ejemplo "if" y
sin mover el cursor introducir Alt-x tempo-expand-if-complete,
con ello se expandirá la plantilla y podremos movernos entre las marcas de
inserción definidas utilizando los comandos Alt-x
tempo-forward-mark y Alt-x tempo-backward-mark.
Lo normal, es asignar combinaciones de teclas en el fichero de configuración
para estas funciones. Por ejemplo, podemos realizar las siguientes
asignaciones para los modos C y C++:
(define-key c++-mode-map
[(control shift return)]
'tempo-expand-if-complete)
(define-key c-mode-map
[(control shift return)]
'tempo-expand-if-complete)
(define-key c++-mode-map
[(control shift left)]
'tempo-backward-mark)
(define-key c-mode-map
[(control shift left)]
'tempo-backward-mark)
(define-key c++-mode-map
[(control shift right)]
'tempo-forward-mark)
(define-key c-mode-map
[(control shift right)]
'tempo-backward-mark)
Alt-x doctor
Si quieres ponerte en contacto conmigo:
eferro@inicia.es