Mar 24 2014

Emacs whitespace-mode

Tag: mediumoverdrive @ 10:49 pm

Whitespace-mode renderiza caracteres para que sean visibles, tales como espacios, tabulaciones o nuevas lineas.

Esto es de gran importancia especialmente cuando se emplean lenguajes como Python.

Para comenzar a usarlo tan solo debemos teclear:

 M-x whitespace-mode

Este comando hara toggle de este modo para el fichero actual. Si queremos activar/desactivar el modo a nivel global para la sesion actual de emacs deberemos lanzar:

 M-x global-whitespace-mode

whitespace1

Ejemplo de captura con whitespace-mode por defecto

  • los tabs se muestran como «>>»
  • los espacios como «.»
  • fin de linea como «$»
  • las lineas en rojo son trailing spaces
  • mientras que las lineas amarillas son «TABs» en lugar de espacios al principio de la linea.

Tambien existen otros modos utiles como:

 M-x whitespace-newline-mode
 M-x global-whitespace-newline-mode

Ahora bien, si no queremos acabar con los ojos destrozados, podemos modificar los simbolos y colores por defecto de este modo:

Para reducir los colores podemos emplear:

(setq whitespace-style (quote (spaces tabs newline space-mark tab-mark newline-mark)))

Si queremos mostrar el simbolo pilcrow en lugar del simbolo del dolar para nueva linea hariamos lo siguiente:

(setq whitespace-display-mappings
;; all numbers are Unicode codepoint in decimal. try (insert-char 182 ) to see it
 ‘(
  (space-mark 32 [183] [46]) ; 32 SPACE, 183 MIDDLE DOT 「·」, 46 FULL STOP 「.」
   (newline-mark 10 [182 10]) ; 10 LINE FEED
    (tab-mark 9 [9655 9] [92 9]) ; 9 TAB, 9655 WHITE RIGHT-POINTING TRIANGLE 「▷」
  ))

Simbolo   Unicode Code Point (Decimal)       Unicode Name
·                183                                                     MIDDLE DOT
¶               182                                                     PILCROW SIGN
↵               8629                                                  DOWNWARDS ARROW WITH CORNER LEFTWARDS
↩               8617                                                  LEFTWARDS ARROW WITH HOOK
⏎               9166                                                  RETURN SYMBOL
▷               9655                                                 WHITE RIGHT POINTING TRIANGLE
▶               9654                                                 BLACK RIGHT-POINTING TRIANGLE
→              8594                                                 RIGHTWARDS ARROW
↦               8614                                                 RIGHTWARDS ARROW FROM BAR
⇥               8677                                                 RIGHTWARDS ARROW TO BAR
⇨               8680                                                 RIGHTWARDS WHITE ARROW

 

whitespace2

Whitespace-mode tunneado para que quede mucho mas chulo que por defecto

Para eliminar los espacios en blanco al final de la linea tan solo debemos invocar a la funcion:

M-x delete-trailing-whitespace

Aunque tambien podemos anadir las siguientes lineas en nuestro .emacs, para asegurarnos de manera automatica, que cada vez cuando guardamos, no dejamos trailing spaces:

(add-hook ‘before-save-hook ‘delete-trailing-whitespace)

Referencias:
http://ergoemacs.org/emacs/whitespace-mode.html
http://www.emacswiki.org/emacs/WhiteSpace


Mar 09 2014

GTAGS in Emacs

Tag: mediumoverdrive @ 10:27 pm

GTACS o mas conocido como Global TAGS o simplemente GLOBAL, es una herramienta de GNU (GNU Global).

Si no disponemos de la herramienta global debemos instalarla:

# apt-get install global

Ademas de esto, debemos haber bajado alli ggtags (que se puede descargar de http://www.emacswiki.org/emacs/GnuGlobal mediante wget):

$ wget http://elpa.gnu.org/packages/ggtags-0.7.12.el

Por ultimo, en nuestro .emacs debemos anadir lo siguiente:

(add-to-list ‘load-path «~/.emacs.d/ggtags/»)
(load-file «~/.emacs.d/ggtags/ggtags-0.7.12.el»)
     (add-hook ‘c-mode-common-hook
               (lambda ()
                 (when (derived-mode-p ‘c-mode ‘c++-mode ‘java-mode)
                   (ggtags-mode 1))))

Primero nos debemos posicionar en el directorio del proyecto y tan solo debemos ejecutar (con la opcion -v para verbose o con la opcion –statistics para mostrar estadisticas):

$ gtags –statistics

gtags1

Esto generara 4 ficheros:

  • GTAGS : TAGS para definiciones
  • GRTAGS : TAGS para referencias
  • GPATH : TAGS para ficheros
  • GTAGSROOT :  Si la variable de entorno GTAGSROOT no esta asignada y el fichero GTAGSROOT existe en el mismo directorio que el fichero GTAGS, entonces global asignara GTAGSROOT al contenido del fichero.

Ademas debemos tener en cuenta el fichero de configuracion de global, que pueden ser:

  1. ‘$HOME/.globalrc’ : fichero de configuracion de global para el usuario.
  2. ‘/etc/gtags.conf’ : fichero de configuracion de global para el sistema.
  3. ‘[sysconfdir]/gtags.conf’ : Ditto.

Tenemos distintas opciones utiles para este comando:

  • -i : actualiza los ficheros TAGS de manera incremental.
  • –single-update <fichero> : actualiza los TAGS para un solo fichero.
  • –acept-dotfiles : acepta ficheros ocultos que por defecto global ignora.
  • -v : modo verbose
  • –statistics : realiza estadisticas

gtags2

Auto-completion de funciones mediante abbrev con M-C-i

Una vez construidos los ficheros tags o bien podemos usar emacs para movernos entre ellos (tan solo debemos usar M-. y M-* para saltar dentro de la definicion o volver al punto anterior. Algunos de los keybindings de Emacs mas importantes son estos:

  • M-. : encuentra definiciones
  • M-] : encuentra referencias
  • M-* : aborta (vuelve al punto previo de la llamada de manera recursiva)
  • M-n o M-p : va al siguiente o al anterior TAG
  • M-o : hace toggle de abbrev completo (en mi caso me funciona ESC + soltar ESC + TAB o Meta+Control+i).
  • M-{ o M-} : previo o siguiente fichero

Ademas pulsando F10 podemos ver un nuevo menu para GTAGS.

gtags3

Usando GTAGS en emacs, en este caso M-] para encontrar referencias

gtags4

Menu mostrado para GTAGS en C-mode (puede realizarse para cualquier modo de programacion) mediante la tecla F10

Sin embargo si desde consola queremos hacer algunos queries tambien podemos hacerlo con global:

  • global <patron> -> imprime los TAGS que coinciden con el patron.
  • global -c <patron> -> imprime simbolos que comienzan por patron.
  • global -f <fichero> -> imprime todos los TAGS de ese fichero.
  • global -u -> actualiza los TAGS de manera incremental.
  • global -x <patron> -> muestra detalles
  • global -g <patron> -> muestra en que linea se encuentra el patron especificado
  • global -r <patron> -> muestra referencias

Para mas informacion se puede consultar la pagina man global, man gtags o el manual de global: http://www.gnu.org/software/global/manual/global.html


Mar 05 2014

Ejecucion de Swank (servidor Lisp) y Emacs (como cliente)

Tag: advancedoverdrive @ 10:42 pm

SLIME esta implementado de tal forma que puede ejecutarse el cliente Emacs desde un lado (slime.el) mientras el servidor Lisp en otra maquina distinta. Asi que en un host ejecutaremos emacs y le diremos a SLIME que conecte a una maquina remota.

Conectando a un Lisp remoto

Si queremos cargar swank sin ejecutar emacs de manera habitual, debemos ejecutar lo siguiente:
(load "/path/to/swank-loader.lisp")
(swank-loader:init)
Dentro de la imagen lisp que se esta ejecutando, tan solo debemos iniciar el servidor swank.
(swank:create-server)

Como vamos a tener tunneling en nuestra conexion mediante ssh, podemos indicar a sawnk que no use una conexion extra para la salida, de la siguiente forma:

(setf swank:*use-dedicated-output-stream* nil)

Si debemos realizar ciertas tareas tales como reconectar a swank, debemos mirar en otros argumentos de swank:create-server. Estos argumentos son:

:PORT : Puerto del servidor de escucha (por defecto es 4005).

:STYLE : Estilo de comunicacion

:DONT-CLOSE : Valor booleano que indica si el servidor continua aceptando conexiones despues de recibir la primera (por defecto es NIL). Util si tenemos procesos lisp ejecutandose por largo periodo de tiempo, donde conectariamos en diferentes momentos, en dicho caso deberiamos especificar :dont-close t.

:CODING-SYSTEM : Sistema de codificacion usado para la comunicacion entre Emacs y Lisp.

Un ejemplo completo con estos argumentos:

(swank:create-server :port 4005  :dont-close t :coding-system "utf-8-unix")

Mientras que en el lado de emacs deberiamos usar esto para dicha configuracion:

(setq slime-net-coding-system 'utf-8-unix)
(slime-connect "127.0.0.1" 4005)

Configurando el cliente Emacs

Desde aqui necesitamos crear un tunel ssh en el puerto 4005 desde nuestra maquina local hasta el puerto 4005 en la maquina remota.

$ ssh -L4005:127.0.0.1:4005 username@remote.example.com

Despues de esto podemos ejecutar SLIME mediante M-x slime-connect.

Configurando las translaciones pathname

Cuando ejecutamos swank remotamente, Emacs asume que los ficheros que se vayan a encontrar son ficheros normales. Sin embargo, si queremos slime-compile-and-load-file (C-c C-k) y slime-edit-definition (M-.) para trabajar correctamente, necesitamos encontrar algun modo de decirle a nuestro Emacs local que debe referirse a ficheros remotos.

Existen principalmente dos formas de hacer esto. La primera es usar mount, NFS o similar, el disco duro de la maquina remota sera visible en nuestro sistema de ficheros local como cualquier otro fichero. Sin embargo NFS es realmente lento, con bugs etc. Es por eso que la mejor forma es tener una conexion ssh y emacs con tramp-mode para hacer el resto. Lo que hacemos es decirle a Emacs como debe coger el fichero en una maquina remota y traducirlo en algo que tramp puede entender y acceder. cl:machine-instance devuelve el «hostname» para una maquina remota como hostname.domain.com.  Por lo que podemos tener algo asi:

(add-to-list 'slime-filename-translations
             (slime-create-filename-translator
              :machine-instance "hostname"
              :remote-host "hostname.domain.com"
              :username "user"))

Redireccion global de todo IO al REPL

Por defecto SLIME no cambia *standard-output*  y variantes fuera del REPL. Por lo que si tenemos cualquier otro thread el cual llama format, write-string, etc. La salida solo sera vista en *inferior-lisp* buffer o en la terminal. Por lo que podemos hacer es:

(run-in-new-thread
  (lambda ()
    (write-line "In some random thread.~%" *standard-output*)))

Para enviar la salida al buffer REPL de SLIME, de manera contraria a *inferior-lisp*, configuramos swank:*globally-redirect-io* a T.

El valor de esta variable solo es checkeado una vez cuando swank acepta la conexion. Por lo que debemos configurarlo mediante ~/.swank.lisp, ya que sino necesitaremos llamar a swank::globally-redirect-io-to-connection manualmente.

Conectando a SLIME de manera automatica

Para hacer que SLIME conecte a nuestro Lisp cualquiera que sea nuestro fichero lisp abierto, debemos anadir esto en nuestro .emacs:

(add-hook 'slime-mode-hook
          (lambda ()
            (unless (slime-connected-p)
              (save-excursion (slime)))))

Para entender un poco mejor la arquitectura de SLIME, Swank y Emacs podemos visualizar el siguiente grafico:

slime_swank


« Página anteriorPágina siguiente »