Notxor tiene un blog: Organización del espacio de trabajo en Emacs

Hoy vengo a hablar de cómo organizar un poco el espacio de trabajo de Emacs. Escribiré sobre las famosas tabs que se han incorporado en las últimas versiones y sobre otras herramientas más viejunas pero también válidas, que teníamos antes y que sigo utilizando, como perspective. Así pues, si no te organizas tus ventanas de aquí en adelante, será porque no quieres.

Como sabéis, llevo un tiempo trabajando con Emacs y vengo de nuevo a cansinar con él. Concretamente con cómo me apaño para tener controlados los sienes y sienes de buffers que puedo llegar a tener abiertos en un momento dado. Mi respuesta a ésto, es sencilla: no los tengo controlados... del todo... hay quien diría que en absoluto. Cuando empecé a utilizar Emacs venía de otros editores capaces de abrir pestañas mostrándolas visualmente y teniéndolas a un click de ratón. La principio las eché de menos: porque el sistema de buffers, hasta que lo entendí, me parecía marciano. Cambiar de un buffer a otro, abrir buffer, cerrar buffer, mostrar varios buffers en el mismo marco.

Método de sesiones

Al principio puede parecer buena idea tener varias sesiones abiertas, cada una con el aspecto con el que vayamos a trabajar. Puede ser un método cuando estás trabajando en una máquina sobrada de recursos. Este es el método más sencillo de entender: abres Emacs tantas veces como necesites. Además, por lo que tengo comprobado, es la única forma de que se mantengan las cosas en su sitio y no se trasvasen de un lugar a otro automágicamente. Que resulta que abres un buffer donde no toca, todo se lía y te pierdes en toda una marabunta de cosas.

La evolución natural de este sistema es abrir una sola sesión pero varios con frames lanzados con C-x 5. Esto es bastante más agradecido para el gasto de RAM y otros recursos de la máquina, pero tiene el inconveniente, ─o la ventaja─, de que se comparten los buffers abiertos y puedes abrir cualquiera en cualquiera de los frames. Además, si no tienes varias pantallas, la mejor forma de mantenerlos a raya es repartirlos por los distintos escritorios.

A falta de pestañas, me puse a investigar cómo podía reducir mi ansiedad de tener lo que fuera lo que estuviera editando a un golpe de click... y como siempre ocurre en Emacs encontré varias alternativas, de las cuales voy a mencionar sólo dos: perspective y la moderna tab-bar-mode.

Perspectivas

El paquete perspective es uno de esos paquetes que marcan la diferencia a la hora de organizarte el trabajo. Me ocurrió lo mismo cuando descubrí los terminales múltiples de GNU/Linux y sus primos pequeños los escritorios múltiples después. En cada uno puedes tener lo que necesites abierto y distribuido por tu pantalla de trabajo para poder saltar de un sitio a otro con apenas una combinación de teclas (y click de ratón si quieres).

La instalación es muy fácil, está en MELPA:

M-x package-install RET perspective RET

En mi caso no tengo ninguna configuración adicional en mi init.el porque no suelo tenerlo activado desde el inicio y sólo lo activo cuando veo que necesitaré trabajar en varios asuntos de manera simultánea, es decir: cuando lo necesito.

Algo que suele ser casi diario, últimamente que me paso días en los que además del trabajo habitual, estoy con el proyecto del raytracer y escribiendo artículos para el blog. Mientras voy programando, voy leyendo el pdf, voy tomando apuntes, que se convierten posteriormente en artículos para el blog, y realizando otras tareas como la contabilidad, consulta de documentación, etc. Además de perspective, otro paquete recomendable es persp-projectile si utilizas projectile. En el que la perspectiva se alía con el proyecto y permite abrir una perspectiva eligiendo entre toda la lista de proyectos. Su instalación es muy sencilla:

M-x package-install RET persp-projectile RET

Como en el anterior caso, no tengo tampoco ningún otro código de activación en el init.el. Simplemente cuando quiero abrir una perspectiva para trabajar con un proyecto específico tecleo el comando M-x projectile-persp-switch-project, selecciono el proyecto con el que quiero trabajar, y respondo a la pregunta de qué fichero quiero abrir y ya está todo: abierta una nueva perspectiva.

Para activar las perspectivas utilizo el comando persp-mode que abrirá la perspectiva por defecto main. Se puede configurar el nombre, como otras muchas opciones.

Captura-pantalla_perspectiva-main.png

En la imagen podemos observar que en la linea de estado aparecen unas etiquetas con las diferentes perspectivas abiertas, marcando la activa con otro color. Esas etiquetas se pueden modificar, cambiar colores, separadores, etc. Además, esas etiquetas se ordenan, ─también por defecto─, alfabéticamente.

La primera cuando abres perspective es main. En esta perspectiva suelo abrir tareas que yo llamo de pantalla completa como el lector de RSS elfeed o la agenda, o esas cosas.

En otras perspectivas tengo abiertos varios buffers de trabajo:

Captura-pantalla_perspectiva-blog.png

Si nos fijamos en la imagen anterior, en el buffer *:Buffers:* vemos que perspective abre un *scratch* independiente para cada perspectiva.

Combinaciones de teclas y comandos

Como muchas otras cosas que se pueden configurar, la combinación de teclas para trabajar con perspectivas, también puedes cambiarla en tu configuración. Por defecto es C-x x.

C-x x a
añadir buffer a la perspectiva.
C-x x k
eliminar el buffer de la perspectiva.
C-x x s
cambiar (switch) a una perspectiva. Si el nombre que tecleamos no existe, crea una perspectiva nueva.
C-x x c
eliminar la perspectiva.
C-x x n o C-x x ->
ir a la siguiente perspectiva... con n o con la flecha a la derecha.
C-x x p o C-x x <-
ir a la perspectiva anterior... con p o con la flecha a la izquierda.
C-x x r
renombrar la perspectiva.

Otro comando muy interesante y que descubrí hace poco, es la posibilidad de guardar las perspectivas que tenemos abiertas en nuestra sesión en un fichero con C-x x C-s y luego cargarlas desde el mismo con C-x x C-l. De esa forma, podemos cargar el estado completo de nuestra sesión, con sus perspectivas y buffers abiertos.

Pestañas con tab-bar

Otra forma de organizar nuestro escritorio en Emacs es utilizar el modo tab-bar que nos permitirá tener diferentes pestañas con diferentes diseños en la misma sesión.

Las últimas versiones de Emacs proporcionan un modo de pestañas que se activa (y desactiva) con M-x tab-bar-mode.

Sin embargo, este método de distribuir el espacio de trabajo no ha calado mucho en mi día a día. Especialmente porque ya estoy acostumbrado al método descrito anteriormente y ese suele ser el que utilizo. Aunque visualmente es algo más agradable de ver:

Captura-pantalla_tab-bar.png

Aparecen, una serie de botones en la parte superior del espacio de edición que representan las correspondientes pestañas. Esa barra está orientada, o pensada, para ser manipulada gráficamente. Presenta botones de cerrado (x) en cada pestaña1 y de creación de una nueva pestaña (+) en la barra, pero que no son útiles desde el Emacs en consola.

Las combinaciones de teclas comienzan, ─por defecto─, con el prefijo C-x t y las más habituales son:

C-x t 2
crear una pestaña nueva.
C-x t 0
cerrar la pestaña actual.
C-x t f o C-x t C-f
abrir un fichero en una pestaña nueva.
C-x t r
renombrar la pestaña.
C-x t o
ir a la siguiente pestaña.

El sistema es como es y no termino de entender por qué utilizan o en lugar de n para ir a la siguiente pestaña2. Supongo que debes configurar esas teclas en tu init.el, porque los comandos sí que existen como tab-bar-switch-next-tab o tab-bar-switch-prev-tab, o incluso tab-bar-switch-to-tab para cambiar a una pestaña determinada, o incluso un comando tab-bar-switch-to-recent-tab para saltar a la pestaña de edición de la que vienes. Algo muy útil si estás saltando entre dos pestañas yendo y viniendo.

Por tanto, si vas a utilizar esta característica con asiduidad, será recomendable que configures todas esas acciones con sus correspondientes teclas, especialmente si lo vas a usar en consola y no en modo gráfico, que es donde este modo parece tener su fuerte.

Conclusiones

Elegir un paquete u otro no va más allá que de los gustos. Ambos, tanto perspective como tab-bar, proporcionan formas de trabajo muy similares. Cada uno tiene sus pros y sus contras.

El principal pro de tab-bar es que viene ya integrada en las últimas versiones de Emacs. Por contra, perspective hay que instalarlo desde fuera. El principal contra de tab-bar es que viene inicialmente orientado a pichorros gráficos como para utilizarlo sin más en sesiones en consola. Por contra, perspective se utiliza de la misma manera en los dos casos y aunque sea un poco menos agraciado estéticamente, no ocupa sitio visual, o espacio de pantalla más que en la barra de estado.

Por tanto, elegir uno u otro, como muchas veces ocurre con nuestro editor favorito, es una cuestión de gustos. Que cada uno elija el que más se ajuste a su manera de trabajar y lo ajuste a sus gustos.

Nota al pie de página:

1

También se puede configurar, como muchas cosas en Emacs.

2

Que sería la opción habitual lógica a través de todos los paquetes de Emacs: n para siguiente y p para anterior.

-1:-- Organización del espacio de trabajo en Emacs (Post )--L0--C0--November 25, 2020 12:00 AM

Notxor tiene un blog: Material difuso y corrección gamma

Pues aquí estoy de nuevo con otra entrega del raytracer y todo lo que voy haciendo. Hoy voy a comenzar explicando cómo tengo configurado Emacs para trabajar con erlang, porque me lo habéis pedido y luego continuaré con las propuestas del libro... el de escribir un raytracer en un fin de semana. Concretamente hablaré sobre el primer material (el difuso) que propone y la corrección gamma del color.

Algunos me habéis preguntado cosas y otros me habéis mostrado un profundo aburrimiento con mi frikada. No puedo adelantar si esta serie durará mucho, ya siento aburriros, pero sois tan libres de no leerlo como yo de escribirlo. Por otro lado, hay quien quiere saber más, se queja de que voy lento y me pide que le dé más caña. Pero también hay quien ya se cansó en el primer artículo. Como he dicho antes, traigo otros pequeños avances: nuestras esferas representadas por primera vez con un material, ─en este caso, difuso─, y algunas cosillas más, como la corrección gamma del color y otros apuntes sobre las herramientas que estoy utilizando.

Voy a empezar por esta última, porque se debe a un pregunta que me han hecho: ¿Qué usas para hacerlo? La respuesta corta hubiera sido Emacs, pero conociendo al que me la ha hecho, estoy seguro de que se refiere a cosas más concretas.

Configuración de Emacs para programar en erlang

El hecho de programar con erlang, siendo un lenguaje minoritario, no cuenta con la profusión de herramientas que otros lenguajes tienen para la edición, depuración y mantenimiento del código. De hecho, la mayoría de las aplicaciones que sirven para ello, vienen con el propio erlang: observer, debugger, etc. que se pueden lanzar desde la consola, o shell, de erlang con llamando a observer:start() o debugger:start().

Si ya tienes instalado algún IDE como eclipse o IntelliJ, puedes instalarte el plugin de erlang. No los he probado, pero seguramente, conociendo ambos IDE's, serán unos paquetes que funcionarán perfectamente y proporcionarán herramientas más allá del coloreado de sintaxis.

A mí, esos IDE's me resultan demasiado pesados, complejos y prolijos, llenos de botones situados por todas partes y, como sabéis, me decanto más por un editor como Emacs. ¿Tengo que renunciar a muchas cosas eligiendo un editor en lugar de un IDE? Pues no, prácticamente a ninguna. Como digo, erlang trae sus propias aplicaciones de debug y de visualizador de procesos1... y para lo demás está Emacs.

Paquetes para trabajar con erlang

Para trabajar con este lenguaje tengo tres paquetes instalados en Emacs que para mí son los básicos. En la lista de paquetes podréis encontrarlos, hay más2. Pero los que yo uso son éstos y me son suficientes:

  • erlang: el paquete general, con coloreado de sintaxis, indentación y algunas herramientas adicionales.
  • company-erlang: para el autocompletado del código con company.
  • ivy-erlang-company: autocompletado company con ivy-mode3.

El segundo y el tercero no merecen demasiada atención, si ya tienes configurado ivy y company para otros lenguajes, por ello de ese trío me voy a concentrar en el primero. El paquete erlang es muy fácil de configurar y no necesitas más que añadir a tu init.el una o dos líneas, o tres según las herramientas que uses. En mi caso:

(require 'erlang-start)
(setq erlang-root-dir "/usr/lib64/erlang")
(require 'erlang-flymake)

La primera línea inicia el paquete erlang en nuestro Emacs. La segunda establece dónde está instalado. En OpenSuSe Tumbleweed se instala en el path que veis arriba. Por defecto, el directorio esperado es /usr/local/erlang. Si efectivamente lo tienes instalado en ese directorio o creas un enlace para dicha dirección, no necesitas ajustar la variable erlang-root-dir. En ese directorio, Emacs buscará no sólo los ejecutables y librerías, sino también la documentación. Y creedme, que es un lujo pulsar C-c C-d y que Emacs te abra la documentación de la librería o de la función sobre la que se encuentre el cursor para consultarla.

La tercera línea de la configuración activa flymake para erlang. Si no utilizáis flymake tampoco la necesitas. Lo veremos enseguida, pero primero vamos a ver qué combinaciones de teclas utilizo más frecuentemente:

  • C-c C-c, comment-region: Comenta las lineas de código seleccionadas.
  • C-c C-u, uncomment-region: Habilita el código comentado por el método anterior.
  • C-c C-d, erlang-man-function-no-prompt: Muestra la página de manual de erlang de la función en la que se encuentra el cursor.
  • C-c C-k, erlang-compile: compila el módulo que estamos editando.
  • C-c C-q, erlang-indent-function: reorganiza el indentado de la función al estilo de erlang.
  • C-c C-z, erlang-shell-display: abre un buffer con un shell de erlang.

Quizá lo más remarcable del paquete erlang son los skeletons. Los skeletons son plantillas de código erlang. Hay desde módulos completos para application, gen_server, supervisores, funciones y estructuras de código más habituales como receive, cabeceras, módulos, etc. Se pueden cargar desde el menú de Emacs o desde comando con M-x tempo-template-erlang-* ... donde el * se sustituye con el nombre del código que queramos, como small-header o small-server, application, etc.

flymake

flymake es una herramienta que va compilando el código que estamos escribiendo y notificando sus errores y avisos (warnings). No es específica para erlang, de hecho encontraréis en la lista de paquetes de ELPA todo un listado de ellas, porque cada lenguaje tiene su correspondiente paquete. Sin embargo, no busquéis en esa lista el paquete de erlang, no está.

En el caso de erlang el archivo erlang-flymake lo proporciona el mismo paquete erlang. Por eso lo activamos en la configuración junto a él.

El paquete flymake nos proporciona información muy valiosa para encontrar errores de sintaxis avisándonos de varias maneras. En formato texto podemos ver los siguientes avisos:

Captura-pantalla_flymake-texto.png

Como podemos ver en la imagen, en 1, vemos que en la línea de estado de Emacs aparece [Flymake[3 1], es decir: hay 3 errores y 1 aviso. En \(2\) se encuentra una función donde están los errores. En la imagen los errores se marcan en rosa y el aviso en naranja. Visto así, no hay mucha información más que existen esos errores y warnings. Si necesitamos más información, podemos apelar a M-x flymake-show-diagnostics o M-x flymake-show-diagnostics-buffer. Esta segunda hace que se muestre un buffer con esos errores tal y como los da el compilador:

Captura-pantalla_flymake-texto-lista.png

Como podemos ver, en el buffer un desglose con las líneas donde se han encontrado los errores y el tipo de error.

En modo gráfico la información es la misma pero presentada de manera más gráfica:

Captura-pantalla_gtk-lista.png

Como se puede ver, en el margen aparecen los símbolos ! para los warnings y !! para los errores. Además subrayan los errores en rojo y los warnings en azul. También se puede pinchar en la barra de estado justo sobre Flymake y nos aparecerá un menú que nos permite una serie de acciones, como por ejemplo, abrir el buffer de diagnóstico... para aquellos que gustan de despegar su mano del teclado para ir al ratón.

projectile y magit

Además lo que casi convierte Emacs en un IDE son las herramientas de projectile y magit. En realidad, ambas, no tienen nada de específico para trabajar con código erlang, pero sí son potentes herramientas para trabajar con código en general.

La primera, projectile, proporciona herramientas y comandos para trabajar sobre conjuntos de ficheros fuente agrupados en proyectos. Tiene muchas funciones útiles para gestionarlos, pero lo que más estoy utilizando es la opción de compilar el proyecto con C-c p c, o buscar algo dentro del proyecto con C-c p s4.

La segunda, magit, es una de esas aplicaciones de Emacs que aparece en todas partes como ejemplo de calidad. Sirve para gestionar un proyecto con git y permite hacer de todo, aparte de lo habitual de subir cambios, actualizar el repositorio o hacer commits: crear ramas locales y remotas, rebase, merge o cualquier otro comando que admita git, con especial mención a log o diff.

Si no has probado estas herramientas ya estás tardando en probarlas. Y como ya he hablado sobre ellas en otras ocasiones en el blog pues permitidme que lo deje aquí y dedique el artículo a los avances que he ido haciendo en el raytracer.

Primer material diffuse

El material difuso es un tipo de material que produce sólidos con aspecto mate. Si no entiendes exactamente a qué tipo de objetos me refiero, piensa en una goma de borrar o, en general, en cualquier tipo de goma. Este tipo de material presenta un aspecto rugoso o granulado, de forma que la luz al incidir sobre este tipo de superficies puede salir rebotada en cualquier dirección al azar y no reflejando el entorno:

material-difuso.png

Siendo la superficie rugosa, los rayos de luz pueden rebotar en cualquier dirección. El algoritmo más utilizado para este tipo de materiales es el conocido como Lambert. Sin embargo, el libro comienza con una aproximación que se supone algo menos exigente con los cálculos. Esta aproximación propone crear dos esferas de puntos tal que, dado el punto \(P\) donde incide el rayo se considera el centro de una de ellas en \(P + \overrightarrow{n}\) y el centro de la otra en \(P - \overrightarrow{n}\). De estas dos, la primera se considera que está fuera de la superficie donde incide el rayo tangente a esa superficie en ese mismo punto, mientras que la segunda estaría dentro del objeto.

Básicamente, lo que hace es lanzar otro rayo cuando el rayo \(r\) incide en el punto \(P\). Entonces, al azar, se obtiene el punto \(S\) dentro de lo que sería la esfera de radio 1, para formar el vector \((S - P)\):

aproximacion-lambert.png

Esta aproximación se traduce en el código en la creación de unas funciones muy sencillas, algunas como vec3_random/2 genera un punto aleatorio que luego pediremos que esté entre -1 y 1.

%%
%% Devuelve un punto aleatorio cuyas coordenadas están entre 0 y 1
%%
vec3_ramdom() ->
    {random(),random(),random()}.

%%
%% Devuelve un punto aleatorio cuyas coordenadas varían entre Min y
%% Max.
%%
vec3_ramdom(Min, Max) ->
    {random(Min, Max), random(Min, Max), random(Min, Max)}.

%%
%% Devuelve un punto aleatorio que se encuentre dentro de una esfera
%% con centro 0 y radio 1.
random_en_esfera_unidad() ->
    P = vec3_ramdom(-1, 1),
    M = modulo_cuadrado(P),
    if M >= 1 ->
            random_en_esfera_unidad();
       true ->
            P
    end.

Hasta ahora la función color_rayo generaba el color basándose en la normal del punto donde incidía el rayo y, por tanto, le bastaba con conocer el rayo. Sin embargo, se ha modificado la función a color_rayo/3:

%%
%% Calcula el color obtenido por un rayo particular
%%
color_rayo(_Estado, _Rayo, 0) ->
    {0.0,0.0,0.0};
color_rayo(Estado, Rayo, Contador) ->
    Impactos = impactos(Estado, Rayo, 0.001, ?INFINITO),
    Orden_impactos =
        lists:sort(
          fun(I,J) ->
                  {_,#impacto{t=T1}} = I,
                  {_,#impacto{t=T2}} = J,
                  T1 < T2
          end,
          Impactos),
    Impacto_Cercano = hd(Orden_impactos),
    case Impacto_Cercano of
        {true,Im} ->
            Objetivo = rerl:suma(rerl:suma(Im#impacto.normal,Im#impacto.p), rerl:random_en_esfera_unidad()),
            R = #rayo{origen=Im#impacto.p,dir=rerl:resta(Objetivo, Im#impacto.p)},
            rerl:mul(color_rayo(Estado, R, Contador - 1), 0.5);   % Ojo recursión
        {false,_} ->
            #rayo{dir=Dir} = Rayo,
            {_,Y,_} = rerl:vector_unidad(Dir),
            T = 0.5 * (Y + 1),
            rerl:suma(rerl:mul({1.0,1.0,1.0}, (1-T)),      % Del color blanco {1,1,1}
                      rerl:mul({0.5,0.7,1.0},  T))         % al color azul {0.5,07,1.0}
    end.

Se puede observar que se ha convertido en una función recursiva, porque sigue el rayo donde impacta y puede seguirlo las veces que sea necesario. Como podría darse el caso de que el rayo estuviera rebotando infinitas veces, se pone una limitación con contador, que lo hará sólo las veces que se determine por parámetro. Hacer notar también que en la llamada a impactos/4 se ha establecido una distancia Tmin de 0.001, hasta ahora se venía utilizando el valor 0, pero en los cálculos se consideraban valores como 0.0000001 como significativos y a estas alturas podemos considerar que es suficiente con una milésima para la aproximación a 0.

Con todo esto el resultado obtenido es:

imagen-cruda.png

La imagen obtenida es suficientemente prometedora, aunque algo oscura. Nos podemos preguntar si hemos hecho algo mal para que nuestras esferas tengan un color gris tan oscuro. Sin embargo, la explicación viene de una característica de nuestro sistema visual: su adaptación a las diferentes intensidades de luz. Necesitamos ajustar los colores de la imagen a cómo lo verían nuestros ojos en una situación lumínica similar. Para ello se utiliza la corrección gamma del color.

El cálculo de la superficie utilizando el procedimiento de Lambert tampoco es muy compleja ni necesita mucho más tiempo. En mi máquina ha sido al revés, se ha calculado más rápido que la aproximación.

lambert.png

La distribución del color en la fórmula de Lambert se distribuye según el ángulo que forme la normal con el vector calculado, pudiendo llegar a \(cos^3 \phi\).

%%
%% Devuelve un punto según la distribución de Lambert.
%%
random_vector_unidad() ->
    A = random(0.0, 2 * ?PI),
    Z = random(-1.0, 1.0),
    R = math:sqrt(1 - Z * Z),
    {R * math:cos(A), R * math:sin(A), Z}.

Sustituyendo la anterior llamada a random_en_esfera_unidad/0 por random_vector_unidad/0 en el código del cálculo de color del pixel se obtiene:

imagen-lambert-cruda.png

Si comparamos ambas imágenes calculadas, utilizando una aproximación la primera y utilizando la distribución de Lambert la segunda, son muy similares. Ésta última tiene unas sombras más suaves y quizá parezcan algo más luminosas ambas esferas.

Refactorización del código

Tras una pequeña refactorización del código, he metido todos los cálculos necesarios para realizar la imagen en los procesos tesela. Los objetos dejan de intervenir en los cálculos y se ha reducido el tiempo de render de la imagen anterior a unos 40 segundos. Una tercera parte, aproximadamente de lo que se empleaba antes. Más remarcable, si cabe porque no sólo calcula los mismos samples sino que además tiene que calcular los diferentes rayos para el material.

Corrección gamma

En el libro que estoy siguiendo para hacer este raytracer se limita a meter una corrección gamma calculando la raíz cuadrada del color que viene calculado. Sin embargo, he preferido cambiar la fórmula a una más general y acorde con las matemáticas:

\[V_f = A \cdot V_0^\gamma \]

que traducida a código se convierte en:

correccion_gamma({R,G,B}, Gamma) ->
    {math:pow(R, Gamma),
     math:pow(G, Gamma),
     math:pow(B, Gamma)}.

Como se puede observar la corrección \(\gamma\) es una potencia donde el valor final, \(V_f\), es el resultado de multiplicar el valor inicial, \(V_0\), por una constante \(A\) después elevarlo a \(\gamma\). Por tanto, si en el libro hacen una raíz cuadrada simplemente, están haciendo \(A=1\) y \(\gamma=1/2\).

La función de corrección la he puesto en el código que escribe el color del pixel en memoria:

{pixel_color,Pixel,Color} ->
    #state{lienzo=Lienzo,pixeles=Px} = Estado,
    Nuevo_lienzo = maps:put(Pixel, rerl:correccion_gamma(Color, 1/2), Lienzo),
    Faltan = Px - 1,
    Nuevo_Estado = Estado#state{lienzo=Nuevo_lienzo,pixeles=Faltan},
    if Faltan < 1 ->
            Tiempo = erlang:monotonic_time(millisecond) - Estado#state.tiempo,
            io:format("~nTiempo empleado en segundos: ~p~n", [Tiempo / 1000]),
            io:format("Escribiendo imagen...~n"),
            escribir_imagen(Nuevo_Estado);
       true ->
            ok
    end,
    loop(Nuevo_Estado);

Explicar con detalle cómo funciona la corrección gamma sería muy largo, pero si vemos la serie de imágenes

imagen-gamma-2.pngimagen-gamma-1.pngimagen-gamma-1-2.pngimagen-gamma-1-4.png

podemos percatarnos que valores superiores a \(1\) harán las imágenes más oscuras mientras que valores inferiores a \(1\) harán las imágenes más luminosas.

Nota al pie de página:

1

De procesos, de aplicaciones, de tablas de las bases de datos, de consumo de memoria y procesador... en fin, todo lo que esté moviendo el nodo erlang que se quiera analizar.

2

edts es otro paquete, no lo he probado, pero parece basarse en otros paquetes, como los anteriores para hacer su trabajo.

3

Éste se instaló como dependencia, así que no me preocupo por él.

4

Da la opción de buscar con distintas herramientas como grep o ag, que deben estar instaladas en el sistema, junto con su correspondiente paquete de Emacs. grep suele estar instalado por defecto, pero no así ag.

-1:-- Material difuso y corrección gamma (Post )--L0--C0--November 20, 2020 09:03 AM

Notxor tiene un blog: org-roam en modo servidor

Ya hablé en otro artículo sobre org-roam y hoy os lo traigo de nuevo. Desde aquél artículo inicial han pasado algunos meses y el continuo desarrollo que están poniendo en org-roam hace que haya evolucionado bastante, además de subsanar algunos problemas con los que me tropecé cuando empecé a utilizarlo hace algunos meses.

Como digo, el paquete ha madurado y han aparecido nuevas funcionalidades. Entre ellas tenemos un modo servidor que hace de org-roam una herramienta más visual y más moderna, si me permitís esa expresión. Hace tiempo que no me guío por el aspecto de las aplicaciones y todo lo he derivado hacia una existencia en texto plano que me permite trabajar hasta con el más mínimo dispositivo al que se le pueda enchufar un teclado decente. El aspecto moderno o gráfico no es una de mis prioridades, sin embargo, ¿qué pasa si trabajo con texto plano y tiene una interface gráfica agradable? Eso me está pasando con org-mode, con su modo de trabajo en texto plano, pero además proveen una asistencia gráfica mediante el paquete org-roam-server.

org-roam-server-completo.png

Las imágenes las he tomado de uno de los directorios de notas que utilizo para un proyecto que se va haciendo cada vez más complejo. Es un cajón de notas real. Así me aseguro de que los ejemplos visuales sean reales y no forzarlos inventando notas vacías. Como se puede apreciar en la imagen, casi no se pueden seguir las relaciones entre las distintas anotaciones en ese modo gráfico. Lo bueno es que pinchando y arrastrando cada nodo dibujado hace que los demás se muevan y cambien de posición. De esa manera podemos conseguir que el gráfico sea un poco más claro del que dibuja por defecto la herramienta. Pero vamos por partes.

Configuración

Estoy partiendo del hecho de que no tienes ya instalado org-roam. Si llevas un tiempo utilizándolo, seguro que ya encontraste este paquete adicional antes. También, quizá, debas enterarte un poco cómo va el asunto de la toma de notas con el método zettelkasten1. Si estás convencido de probarlo, primero tienes que instalar el paquete org-roam y después org-roam-server como es habitual:

M-x package-install RET org-roam-server RET

He hecho algunos cambios en la configuración de org-roam para ajustar este paquete. Por ejemplo he añadido una combinación de teclas para lanzar el servidor:

(global-set-key (kbd "C-c r b") 'org-roam)
(global-set-key (kbd "C-c r c") 'org-roam-capture)
(global-set-key (kbd "C-c r d") 'org-roam-doctor)
(global-set-key (kbd "C-c r f") 'org-roam-find-file)
(global-set-key (kbd "C-c r g") 'org-roam-graph)
(global-set-key (kbd "C-c r i") 'org-roam-insert)
(global-set-key (kbd "C-c r m") 'org-roam-mode)
(global-set-key (kbd "C-c r r") 'org-roam-find-ref)
(global-set-key (kbd "C-c r s") 'org-roam-server-mode)
(global-set-key (kbd "C-c r t") 'org-roam-buffer-toggle-display)

En el listado puedes ver todas las combinaciones de teclas que utilizo para tomar notas, y sólo cabe destacar desde el anterior artículo, la aparición de C-c r s para lanzar el servidor. Si volvemos a pulsar esa combinación, veremos un mensaje de org-mode-server disabled.

emacs-org-roam-server.png

En la imagen se muestra, ─abajo en la lista de procesos─, org-roam-server lanzado como un proceso httpd. Como ya me ha pasado alguna vez, este proceso puede interferir con el habitual uso del servidor web local que utilizo para probar la buena visualización de los artículos del blog antes de publicarlos. Ambos procesos intentan utilizar el mismo puerto 8080. Para solucionarlo, he añadido una configuración adicional tal que:

(setq org-roam-server-port 8000)

De esta manera, es posible levantar los dos procesos httpd de forma simultánea, org-roam-server en el puerto 8000 y el web local en 8080.

Como se puede observar, se mantiene nuestra querida interfaz de texto y podemos consultar las notas por su contenido, tener referencia de los enlaces que apuntan a ella y de aquellas notas a las que ésta apunta. Cualquier modificación que hagamos en ellas se refleja también de manera automágica en el servidor: la información en ambos modos es la misma, pero se presenta de manera diferente.

Saturados de notas

A poco complejo que sea el tema que estés trabajando2 la información mostrada de forma gráfica hace que nos perdamos en las múltiples conexiones, pero podemos filtrarlo de dos maneras.

Filtrado por nodos

Comenzaré por la botonera de la esquina superior derecha. El modo más simple es pulsar el botón File Viewer. Veremos que a la izquierda nos aparece un selector para poder buscar la nota que queramos:

org-roam-server-file-viewer.png

Como veis, la información es la misma que obtenemos en modo texto: el espacio grande reservado para la anotación y a la derecha vemos una lista de notas que enlazan a esa. Vale, para eso tenemos ya el modo texto en Emacs. Además no he conseguido aún poder modificar una nota desde este modo gráfico, ─aunque tenga un botón Edit bien visible─, pero eso es otro asunto.

El siguiente apartado en la botonera superior derecha es Buffer Network que lo que hace es mostrar los enlaces de un determinado archivo que podemos seleccionar en la lista desplegable de abajo a la izquierda:

org-roam-server-visor-nodo.png

A poco que seamos observadores veremos un selector numérico. Ese selector lo que hace es limitar las conexiones entre nuestro nodo seleccionado y otros. Por ejemplo, si incrementamos el selector para ver las etiquetas enlazadas de segundo nivel obtendríamos las siguientes conexiones:

org-roam-server-visor-nodo-incremento.png

Como podéis apreciar también, hay dos estilos de visualización: Dark Mode y Light Mode. Se puede elegir el que más os guste simplemente pinchando en el enlace que aparece en el centro de la parte superior de la página.

Y también, a poco que observemos, podemos ver que el tamaño de los círculos cambia de un nodo a otro. Cuantos más enlaces recibe una nota, más grande es el círculo que la representa. También vemos que hay distintos colores según las etiquetas que hayamos empleado y esto nos lleva al siguiente apartado.

Filtrado por etiquetas

También vemos en la parte superior derecha el botón Database Network que es el modo que está activado por defecto cuando arrancamos el servidor. Este modo nos muestra toda la base de datos, por defecto, pero también podemos filtrar toda esa información.

org-roam-excluir-etiquetas.png

En ese modo vemos el selector de la esquina inferior izquierda, que mostrará el mensaje Filter, y al lado hay un botón de color rojo que muestra Exclude. Si pinchamos en el botón veremos que cambiará a color verde con el mensaje Include. Con él podemos crearnos un filtro que incluya sólo los nodos con unas determinadas etiquetas, pero además que excluya otras. Cada etiqueta nos la mostrará en color rojo o verde, según esté excluida o incluida en la búsqueda. Así podemos establecer complejos filtros de información hasta tener en pantalla sólo unas pocas notas o incluso una o ninguna. A veces es interesante llegar a un filtro y que arroje una pantalla en blanco porque te hace pensar: hay un vacío en todo este barullo de notas, ¿Qué esperaba encontrar? Quizá me falta algo. Así he encontrado alguna laguna en la información, pero supongo que cada cual tendrá su estilo.

Conclusiones

El paquete org-roam se ha convertido en mi preferido para tomar notas y además de su potente interface de texto, nos proporciona un magnífico servidor gráfico para que visualicemos la información de maneras muy atractivas.

El otro día, hablando con un colega de profesión sobre el trabajo que estamos haciendo en un grupo de trabajo (valga la rebuznancia) sobre abuso infantil del COPPA3, le mostré estas mismas notas. Como era sólo visualizarlas un poco por encima arranqué el servidor y lo estuve manejando mientras hablábamos. Su pregunta fue: ¿cuánto cuesta el programa este de notas? Y a ver... es gratis, al final es gratis, pero necesita un esfuerzo extra para la gente que no está acostumbrada al texto plano.

Una herramienta tan vistosa casi que descuadra nuestro austero mundo de texto y llama la atención a quien no lo conoce. Puede ser un acicate para que otras personas se metan en este mundo de independencia real de nuestros datos y de la información que nosotros mismos generamos, de conseguir que ninguna corporación se apropie de ellos y en un cambio de versión nos chantajee4 para que nos dejemos los dineros en programas más nuevos que no necesitamos.

Nota al pie de página:

1

Puedes leer el artículo que enlazo en el primer párrafo de este artículo o buscar información por Internet. También puedes leer el artículo https://medium.com/voces-en-espa%C3%B1ol/zettelkasten-c%C3%B3mo-un-erudito-alem%C3%A1n-fue-tan-incre%C3%ADblemente-productivo-b16643e170cc

2

En las imágenes podéis ver que estoy utilizando las notas que necesito para un proyecto sobre abuso infantil.

3

Colegio Oficial de Profesionales de la Psicología de Aragón.

4

No deja de ser una forma admitida legalmente de un ataque ramsonware.

-1:-- org-roam en modo servidor (Post )--L0--C0--October 29, 2020 06:54 AM

Blog uGeek: Borrando líneas en blanco de un texto con Emacs

Borrando líneas en blanco de un texto con Emacs

A veces cuando copio un documento en la terminal, lo hace dejando líneas en blanco entre líneas. Para eliminar esto con Emacs es muy sencillo:...

Sigue leyendo el post completo de Borrando líneas en blanco de un texto con Emacs

Visita uGeek Blog

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Borrando líneas en blanco de un texto con Emacs (Post )--L0--C0--October 26, 2020 05:45 PM

Blog uGeek: Añadiendo texto al principio de cada línea en Emacs

Añadiendo texto al principio de cada línea en Emacs

Como podéis imaginar, yo creo y edito mis scripts con Emacs. Hay momentos en los que quiero añadir "#" en un bloque de código para que no se ejecute, o...

Sigue leyendo el post completo de Añadiendo texto al principio de cada línea en Emacs

Visita uGeek Blog

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Añadiendo texto al principio de cada línea en Emacs (Post )--L0--C0--October 24, 2020 10:30 AM

Notxor tiene un blog: Cambiando el blog a org-static-blog

Pues estoy de cambios en el blog y ya tengo algo visible que subir a la red para que se pueda ver. Me resistía al cambio, pues los sistemas son distintos y me arriesgaba a dejar por el camino muchos enlaces rotos, no sólo externos de otros blogs o redes sociales, sino también internos.

Después de pelearme con mis reticencias me puse al tajo e, incluso, me he dedicado a migrar también los diferentes artículos al formato de cabecera nuevo. De esta manera, se podrá consultar el contenido en el nuevo formato o en el antiguo... si al subir el contenido resulta todo como espero.

¿Por qué el cambio? Básicamente tengo estas razones:

  • org-page es un sistema complejo y por tanto también es más difícil hackearlo para ajustarlo a tus necesidades.
  • Por contra, org-static-blog es mucho más sencillo y parece pensado para que te lo adaptes a tus necesidades con poco esfuerzo.
  • Estaba cansado ya del tema oscuro que había hecho y aprovechando que estoy de cambios también le he puesto un poco más de cariño al CSS. Algo que aún no ha terminado del todo y no descarto ponerle un poco más.
  • Cuando terminas un artículo y lanzas el comando de publicación de org-static-blog, sólo genera ese HTML y actualiza los índices y RSS.
  • Puedo tener borradores en proceso sin andarme por las ramas (de git, se entiende).
  • Y por supuesto, el utilizar un control de versiones o no, es problema mío, no me obliga a tener una rama de edición, otra con el sitio generado, ni a tener que acordarme de generar el sitio cada vez que hago algún cambio, porque si se pierde en la rama de git no llega a materializarse. Este sistema detecta si el HTML es más antiguo que el org y si es así lo genera de nuevo.

¿Todo son ventajas? Pues no. Hay inconvenientes que exigen atención, como los enlaces rotos.

Enlaces rotos

A estas alturas, después de varios años escribiendo en el blog sobre mis cosas, resulta que hay quien lo lee y todo. No sólo eso, sino también que hay gente que lo enlaza y lo sigue por RSS.

El miedo al cambio viene, principalmente, de la cantidad de enlaces rotos que quedan siempre sueltos por el mundo. Incluso dentro del mismo blog o página. Por ello voy a intentar que esto no suceda o al menos que sea en el menor grado posible.

Podría haber optado por encogerme de hombros y decir: «sistema nuevo, adaptarse o morir». Pero no me ha parecido conveniente. Para pegar el cerrojazo siempre hay tiempo, me parece.

De momento, como he dicho antes, he convertido todos los artículos del sistema anterior, hecho con org-page, al nuevo sistema org-static-blog. Ha sido un trabajo relativamente sencillo pues sólo tenía que convertir algunos detalles de las cabeceras del fichero org: en lugar de la etiqueta tags de org-page, utiliza filetags, y también me encontré con alguna fecha que no cogía bien y me dediqué a añadir a mano los paréntesis angulares <..-..-..> y con eso está todo convertido... pero falta aún algo de trabajo.

Además, estoy escribiendo esto sin tener la certeza de que efectivamente no romperé ningún enlace... tengo confianza en que así sea, porque va a haber artículos duplicados para lo mismo. En las pruebas que he hecho en local, todo ha parecido funcionar correctamente... pero hasta que no lo pruebe subiéndolo todo al servidor, no puedo estar seguro. De todas formas me guardo una copia de seguridad del sitio viejo, por si tengo que replantear el tema.

El paquete lo puedes descargar por el procedimiento habitual, está en melpa y si tienes configurado ese repositorio de paquetes basta con el comando

M-x package-install <RET> org-static-blog <RET>

Yo soy algo más curioso y no lo he instalado: me he bajado el código del repositorio porque lo estoy cambiando un poco. De hecho no lo tengo donde esté accesible a Emacs, cuando lo uso tengo que cargarlo con load-file, pero aún no estoy en fase de darle cariño.

El código que he cambiado

El propio creador del sistema habla de que está pensado para que sea fácil de leer, comprender y modificar.

Above all, I tried to make org-static-blog as simple as possible. There are no magic tricks, and all of the source code is meant to be easy to read, understand and modify.

Después de haberlo mirado un poco, he de coincidir con el autor: ha sido fácil ajustar la funcionalidad a lo que quería conseguir sin complicarme mucho.

Una de las cosas que es ajustable es «ignorar» variables como org-export-with-toc o org-export-with-section-numbers y en su lugar, he incluido una línea #+options:. La ventaja es que puedo determinar si quiero números o índice en cada artículo, en lugar de limitarlo en todos. La función de crear un nuevo artículo me ha quedado así:

;;;###autoload
(defun org-static-blog-create-new-post (&optional draft)
  "Creates a new blog post.
Prompts for a title and proposes a file name. The file name is
only a suggestion; You can choose any other file name if you so
choose."
  (interactive)
  (let ((title (read-string (org-static-blog-gettext 'title))))
    (find-file (concat
                (if draft
                    org-static-blog-drafts-directory
                    org-static-blog-posts-directory)
                (read-string (org-static-blog-gettext 'filename)
                             (concat (format-time-string "%Y-%m-%d-" (current-time))
                                     (replace-regexp-in-string "\s" "-" (downcase title))
                                     ".org"))))
    (insert "#+title:    " title "\n"
            "#+date:     " (format-time-string "<%Y-%m-%d %H:%M>") "\n"
            "#+filetags: " "\n"
            "#+options:  H:3 num:nil toc:nil \\n:nil ::t |:t ^:nil -:nil f:t *:t <:t")))

Estructuras fijas de los ficheros

El código fundamental que falta en el org-static-blog son las cabeceras y pies de página. El sistema org-page lleva soporte para plantillas mustache que facilitan la vida en este sentido. Sin embargo, en este sistema va en el mismo código. Hay que cargar ese código en sus correspondientes variables:

  1. Para la cabecera del HTML:

    (defcustom org-static-blog-page-header
      "<meta name=\"author\" content=\"Notxor\">
      <meta name=\"referrer\" content=\"no-referrer\">
      <link href= \"/medios/css/estilos.css\" rel=\"stylesheet\" type=\"text/css\" />
      <link rel=\"icon\" href=\"/medios/img/favicon.png\">"
      "HTML to put in the <head> of each page."
      :type '(string)
      :safe t)
    

    Básicamente establece el autor, la dirección del fichero de estilos CSS y el favicon de la página. En mi caso, el autor lo pone fijo, pero no costaría mucho establecer una variable que cargue el contenido desde la cabecera, por ejemplo.

  2. Para el encabezamiento de cada página:

    (defcustom org-static-blog-page-preamble
      "<div>
          <header class=\"masthead\">
            <h1 class=\"masthead-title\"><a href=\"/\">Notxor tiene un blog</a></h1>
            <h2 class=\"masthead-subtitle\">Defenestrando la vida</h2>
            <img class=\"avatar\" src=\"/medios/img/abatar.png\" width=\"100px\"></img>
            <ul>
              <li><a href=\"/\">Blog</a></li>
              <li><a href=\"/tags/esperanto\">Esperanto</a></li>
              <li><a href=\"/tags/radio\">Radio</a></li>
              <li><a href=\"http://blog-antiguo.nueva-actitud.org\" target=\"_blank\">Blog antiguo</a></li>
              <li><a href=\"/etiquetas.html\">Etiquetas</a></li>
              <li><a href=\"/about/\">Acerca de...</a></li>
              <li><a href=\"/rss.xml\">RSS</a></li>
            </ul>
            <form method=\"get\" id=\"searchform\" action=\"//www.duckduckgo.com/\">
              <input type=\"text\" class=\"field\" name=\"q\" id=\"s\" placeholder=\"Buscar en DuckDuckGo\">
              <input type=\"hidden\" name=\"as_sites\" value=\"https://notxor.nueva-actitud.org\">
            </form>
          </header>
        </div>"
      "HTML to put before the content of each page."
      :type '(string)
      :safe t)
    

    Como se puede comprobar, la definición del «título» y el «subtítulo», el habitual menú de secciones con sus correspondientes enlaces y el formulario de buscar.

  3. Para el pie de página:

    (defcustom org-static-blog-page-postamble
       "<div>
        <script src=\"/medios/js/jquery-latest.min.js\"></script>
        <script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>
        <script id=\"MathJax-script\" async src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\"></script>
        <script src=\"/medios/js/main.js\"></script>
        <div class=\"footer\">
            <p>Generado con <code>org-static-blog</code> en <i>Emacs</i></p>
            <p>
                <img style=\"display: inline-block;\" src=\"/medios/img/cc-by-nc-sa.png\" align=\"middle\" />
                   <br />2012 - <span id=\"footerYear\"></span> <a href=\"mailto:notxor@nueva-actitud.org\">Notxor</a>
                &nbsp;&nbsp;-&nbsp;&nbsp;
                Powered by <a href=\"https://github.com/bastibe/org-static-blog\" target=\"_blank\">org-static-blog</a>
                <script type=\"text/javascript\">document.getElementById(\"footerYear\").innerHTML = (new Date()).getFullYear();</script>
            </p>
            <table>
                <tr>
                    <td>
                        <b>Donar por Paypal</b>
                    </td>
                    <td>
                        <b>Donar por Liberapay</b>
                    </td>
                </tr>
                <tr>
                    <td>
                        <!-- Inserción de botón pypal -->
                        <form action=\"https://www.paypal.com/cgi-bin/webscr\" method=\"post\" target=\"_top\">
                            <input type=\"hidden\" name=\"cmd\" value=\"_s-xclick\" />
                            <input type=\"hidden\" name=\"hosted_button_id\" value=\"29VXCW8SRNJ78\" />
                            <input type=\"image\" src=\"https://www.paypalobjects.com/es_ES/ES/i/btn/btn_donateCC_LG.gif\" border=\"0\" name=\"submit\" title=\"PayPal - Donar online de forma segura.\" alt=\"Botón Donar con PayPal\" />
                            <img alt=\"\" border=\"0\" src=\"https://www.paypal.com/es_ES/i/scr/pixel.gif\" width=\"1\" height=\"1\" />
                        </form>
                    </td>
                    <td>
                        <!-- Inserción de botón liberapay -->
                        <script src=\"https://liberapay.com/Notxor/widgets/button.js\"></script>
                        <noscript>
                            <a href=\"https://liberapay.com/Notxor/donate\">
                                <img alt=\"Donate using Liberapay\" src=\"https://liberapay.com/assets/widgets/donate.svg\"></a>
                        </noscript>
                    </td>
                </tr>
            </table>
        </div>
    </div>"
      "HTML to put after the content of each page."
      :type '(string)
      :safe t)
    

    Básicamente carga el poco javascript que utiliza el blog: coloreado de sintaxis, visualización de fórmulas matemáticas y el necesario para los botones de donación1. También está la información sobre la licencia y un enlace al código fuente que lo anima.

Los path

Una de las cosas que me encontré fue la manía que tiene el sistema de utilizar las URL de forma absoluta, comenzando por la dirección pública de la página. Eso coarta en gran medida las pruebas de visualización del sitio en local. Una costumbre que he adquirido tras escribir un artículo... monto un servidor local, bien con M-x httpd-start o desde una consola con python3 -m http.server 8080 luego lo abro con un navegador y lo pruebo. Veo si está todo correcto en su sitio, si las imágenes las he puesto bien y aparecen todas. Lo leo despacio por si encuentro algún error2.

Por todo ello, en muchos sitios he sustituido las llamadas a org-static-blog-get-absolute-url por una llamada a org-static-blog-get-local-url. Una función que la metí yo con un calzador para la tarea.

(defun org-static-blog-get-local-url (relative-url)
  "Esta es mía...Returns local URL based on the RELATIVE-URL passed to the function."
  (concat "/" (org-static-blog-get-relative-path relative-url)))

¿Qué consigo con esto? Pues básicamente que el blog completo sea navegable en local y no intente salir a Internet cada vez que pinches un enlace.

Además, para poner un poco de coherencia en los path del sitio, me empeñé en que las URL de los artículos se distribuyan por directorios con el formato año/mes/día y el título del mismo.

Para esto he tenido que hacer un par de cambios más. Uno de ellos viene recomendado en el mismo código:

(defun org-static-blog-generate-post-path (post-filename post-datetime)
  "Returns post public path based on POST-FILENAME and POST-DATETIME.

By default, this function returns post filepath unmodified, so script will
replicate file and directory structure of posts and drafts directories.

Override this function if you want to generate custom post URLs different
from how they are stored in posts and drafts directories.

For example, there is a post in posts directory with the
file path `hobby/charity-coding.org` and dated `<2019-08-20 Tue>`.

In this case, the function will receive following argument values:
- post-filename: 'hobby/charity-coding'
- post-datetime: datetime of <2019-08-20 Tue>

and by default will return 'hobby/charity-coding', so that the path
to HTML file in publish directory will be 'hobby/charity-coding.html'.

If this function is overriden with something like this:

(defun org-static-blog-generate-post-path (post-filename post-datetime)
  (concat (format-time-string \"%Y/%m/%d\" post-datetime)
          \"/\"
          (file-name-nondirectory post-filename)))

Then the output will be '2019/08/20/charity-coding' and this will be
the path to the HTML file in publish directory and the url for the post.

Por defecto es:
   post-filename)"
  (concat (format-time-string "%Y/%m/%d" post-datetime)
          "/"
          (file-name-nondirectory post-filename)))

Meter ese código ahí tal cual funciona como se espera, se genera la URL tal como dije antes y se crea el fichero html en un directorio dentro de su día, que está dentro de su mes y que a la vez está dentro de su año.

Lo que no avisa la documentación de la función es que luego tienes que sustituir, allí donde se busque el contenido de un artículo que no lo busque en el sitio por defecto con el formato por defecto:

/YYYY-mm-dd-nombre-del-artículo.html

En algunas funciones tenemos que sustituir también las formas que generan url's de ese estilo, para que busquen en el sitio correcto. Básicamente es sustituir la forma que añade la fecha al nombre del archivo por algo así:

(concat "/" (format-time-string "%Y/%m/%d" post-date)

No estoy seguro de haberlo hecho en todos los sitios oportunos, el código está disperso por distintas funciones que generan código html y es un poco enredoso encontrar los sitios adecuados. Lo he repasado varias veces y he visto que todos los enlaces que he probado funcionan. Sin embargo, hay tantos pichorros donde pinchar que no estoy seguro de haberlos probado todos. Si alguien encuentra algún enlace raro que no lleva a ningún lado le agradecería que me avisara.

Estructura de directorios

El sistema funciona de una manera bastante sencilla de entender: hay un directorio configurable donde escribir los artículos y otro donde escribir los borradores. Cuando generas el sitio, coge todo lo que haya en el directorio de referencia y genera los ficheros html. No los genera todos: sólo creará aquellos cuyo fichero html, si existe, sea más antiguo que su fichero org. O dicho de otro modo: sólo genera los modificados. En producción supongo que será mucho más sencillo rápido y efectivo... org-page empezaba a hacerse pesado la generación del sitio.

Otro aspecto sobre los directorios es que todo va al directorio raíz, por defecto, ya he contado que hay que modificar algo el código para conseguir que siga el formato de crear directorios (para fechas) y para otras cosas.

Además se pueden generar listados de artículos según las etiquetas, pero por defecto también las mete en el directorio raíz con el formato tag-etiqueta.html y contribuye al caos del raíz de forma considerable, sobre todo si te gustan la etiquetas como a mí. El caso es que me pareció muchos más manejable la forma de hacerlo de org-page que genera en un directorio tags/ una estructura de directorios, con el nombre de las etiquetas y dentro de ellos su correspondiente fichero index.html con el contenido. Para ello, modifiqué la función que genera esos ficheros de la siguiente manera:

(defun org-static-blog-assemble-tags ()
  "Render the tag archive and tag pages."
  (org-static-blog-assemble-tags-archive)
  (dolist (tag (org-static-blog-get-tag-tree))
    (org-static-blog-assemble-multipost-page
     (concat org-static-blog-publish-directory "/tags/" (downcase (car tag)) "/index.html")
     (cdr tag)
     (concat "<h1 class=\"title\">" (org-static-blog-gettext 'posts-tagged) " \"" (car tag) "\":</h1>"))))

Evidentemente, luego, al generar los enlaces que los visiten hay que modificar el código para que las encuentre con el mismo formato con código tal que:

(concat "/tags/" (downcase tag) "/index.html")

Además, hay que tener en cuenta los archivos rss.xml que quiero que se generen por etiqueta y hay que meterlos en algún sitio donde no se pisen unos a otros... pero lo vemos más despacio a continuación.

Fichero rss.xml por etiqueta

Otro problema que me planteaba con el sistema nuevo y que me resultaba una limitación es la generación de archivos RSS para cada etiqueta. De la gente que tengo constancia que sigue el blog, no accediendo al sitio, sino a través de lectores RSS, me constan, al menos tres de esos ficheros: el de la radio, el de Esperanto y el de Emacs. También sé que hay quien sigue el RSS general, no entiendo muy bien por qué.

El caso es que necesitaba generar los RSS por etiquetas y eso no era algo que contemplara el sistema, así que... ¿por qué no hacerlo yo? Pues manos a la obra: me puse a mirar el código y encontré una función que genera el RSS general (org-static-blog-assemble-rss). También encontré otra que genera un ítem para cada artículo. que se llama org-static-blog-get-rss-item y recibe como parámetro el =post-filename).

Partí del código de la primera pero añadiendo el parámetro tag:

(defun org-static-blog-rss-for-tag (tag)
  "Assemble the tag RSS feed.
The RSS-feed is an XML file that contains every blog post in a
machine-readable format."
  (let ((system-time-locale "en_US.utf-8") ; force dates to render as per RSS spec
        (rss-filename (concat org-static-blog-publish-directory "/tags/" (car tag) "/" org-static-blog-rss-file))
        (rss-items nil))
    (dolist (post-filename (cdr tag))
      (let ((rss-date (org-static-blog-get-date post-filename))
            (rss-text (org-static-blog-get-rss-item post-filename)))
        (add-to-list 'rss-items (cons rss-date rss-text)))
    (setq rss-items (sort rss-items (lambda (x y) (time-less-p (car y) (car x)))))
    (org-static-blog-with-find-file
     rss-filename
     (concat "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
             "<rss version=\"2.0\">\n"
             "<channel>\n"
             "<title><![CDATA[" org-static-blog-publish-title "]]></title>\n"
             "<description><![CDATA[" org-static-blog-publish-title "]]></description>\n"
             "<link>" org-static-blog-publish-url "</link>\n"
             "<lastBuildDate>" (format-time-string "%a, %d %b %Y %H:%M:%S %z" (current-time)) "</lastBuildDate>\n"
             org-static-blog-rss-extra
             (apply 'concat (mapcar 'cdr rss-items))
             "</channel>\n"
             "</rss>\n")))))

El parámetro tag llega como una lista de cadenas donde la primera es el nombre de la etiqueta y las siguientes son los ficheros que la llevan. Por tanto, monto el rss.xml en el mismo directorio que su listado de ficheros, para no sobreescribir un fichero con otro y el resto es idéntico a como se genera el RSS del blog.

Por un momento dudé si hacer la función interactiva o llamarla sólo para cada etiqueta. Al final, me decidí por hacerlo de una manera alternativa. Como no todas la etiquetas son relevantes, porque no todas tienen seguimiento, generar siempre los ficheros es un poco pérdida de tiempo. Así que lo solucioné de manera manual:

(defun org-static-blog-assemble-rss-by-tag ()
  "Assemble the RSS for tags."
  (interactive)
  (mapcar 'org-static-blog-rss-for-tag (org-static-blog-get-tag-tree)))

Es decir, cuando llamo a la función org-static-blog-assemble-rss-by-tag se generarán todos los ficheros rss.xml ─lo que lleva unos segundos─. ¿Por qué no generar sólo una etiqueta o unas pocas? Pues porque hacer unas etiquetas y no otras puede ser un poco confuso para los posibles lectores que lleguen al blog cuando encuentren que tienen referencias de un tema determinado y de otros no.

Como se ve, no es complicado adaptar un sistema tan sencillo: se pueden hacer muchas otras cosas y con muy pocas líneas de código.

El fichero CSS

Por otro lado, también ha habido un cambio de aspecto. He cambiado tipos de letras, colores y alguna cosilla más con la esperanza de hacerlo un poco más atractivo. Sin embargo, como podéis ver, tampoco es que mis capacidades de diseño sean sobresalientes. No ha quedado mal del todo.

Me había cansado del tema oscuro y aprovechando que iba a hacer cambios, me puse también manos a la obra con el aspecto. Aún me quedan algunas cosas que pulir.

El código completo

Sería muy largo poner aquí todo el código implicado. Se sale del tamaño razonable de un artículo del blog. Si alguien quiere acceder a él puede mirarlo en el siguiente repositorio:

https://codeberg.org/Notxor/org-static-blog

Conclusiones

Ha habido más cambios, por ejemplo en el código también he añadido la traducción al Esperanto de las cadenas del sistema. Al principio de comenzar a manejarlo pensé que debía utilizar dos blogs para cada una de las lenguas. Después he visto que me podía ajustar de otros modos.

Por supuesto el código que he subido al repositorio se puede utilizar como mejor veáis. Si hago cambios en el sistema para ajustarlo, para corregir algún bug o para dotarlo de alguna característica nueva, lo subiré al repositorio, pero tampoco tengo el ánimo de convertirlo en un proyecto que mantener... no me da de sí el tiempo como para comprometerme.

Al final, el sistema es tan sencillo que me parece hermoso, se entiende cómo funciona sin demasiado esfuerzo, es altamente personalizable y hasta un psicólogo como yo lo puede hacer sin ayuda.

Si estáis pensando en hacer un blog, queréis un sistema estático y sois usuarios de Emacs, es la alternativa estáis buscando... incluso le podéis automatizar la vista previa de forma muy sencilla:

(httpd-serve-directory org-static-blog-publish-directory)
(httpd-start)

Así no necesitas ni salir de Emacs para hacer las pruebas.

Nota al pie de página:

1

Que por cierto, a ver cuándo os estiráis y me puedo tomar mi primer café a vuestra salud :'(

2

Parece mentira, porque aún así se me cuelan siene' y siene'.

-1:-- Cambiando el blog a org-static-blog (Post )--L0--C0--October 02, 2020 06:53 AM

Notxor tiene un blog: La calculadora de Emacs

A los que usan Emacs no les extraña que entre las muchas cosas que trae nuestro editor favorito, aparezca una calculadora: Calc. Sin embargo, y yo entre ellos, no es fácil encontrar a alguien que la utilice de forma asidua y se entretenga en explicar un poco cómo funciona. Sólo un poco, porque en un artículo como este es imposible abarcarlo todo. Al principio me tenía que forzar a usarla, me costó acostumbrarme a sus idiosincrasias, a la notación polaca inversa y a sus modos de funcionamiento. Ahora me parece una de esas herramientas imprescindibles para el día a día... bueno, imprescindibles es una palabra muy amplia, antes me apañaba sin Calc con una calculadora de escritorio como la de KDE (Kcalc), con una interfaz gráfica a la que estamos más acostumbrados, con pulsar los botones con el ratón, etc. Quiero decir que, puesto que tengo una sesión de Emacs abierta casi el 100% del tiempo, me cuesta muy poco acceder a ella. Aunque no funciona exactamente como esas otras calculadoras: Calc tiene una interface de texto y tienes que aprenderte palabros raros como Notación Polaca Inversa o Pila (para los amantes del guiri: Stack).

Repito el aviso y paso ya al tema, que a lo mejor os interesa más que mi palabrería: este artículo no pretende ser un manual completo, ni tan siquiera un tutorial de uso de una herramienta tan compleja; apenas es una introducción a su uso, el intento de aclarar algunos conceptos básicos para hacerlo y una muestra de lo que puede hacer Emacs para facilitarnos la vida.

Calc

¿Qué es Calc y qué nos proporciona?1 Pues si atendemos a su documentación nos encontramos con algunas características:

  • Elección de modo algebraico o Notación Polaca Inversa (basada en pila).
  • Selección de la precisión de enteros y números decimales.
  • Aritmética de números racionales, números complejos... vectores, matrices, fechas y horas, infinitos, cantidades con unidades, fórmulas algebraicas...
  • Operaciones matemáticas como logaritmos y funciones trigonométricas.
  • Características para programadores: operaciones de bits y números no decimales.
  • Funciones financieras.
  • Funciones de teoría de números, como la factorización de números primos o el módulo aritmético.
  • Características de manipulación algebraica como el cálculo simbólico.
  • Mover datos desde, o hacia, buffers de edición.
  • Modo de insertar y manipular fórmulas de Calc y datos directamente en una buffer de edición.
  • Gráficos utilizando GNUplot.
  • Fácilmente programable utilizando macros de teclado, fórmulas algebraicas o mediante elisp.

Pero, mierda, si yo sólo quiero sumar unas pocas cantidades mientras repaso las facturas. Pues a eso voy, que, ni que decir tiene, es el principal uso que le estoy dando, pero que sepáis que se pueden hacer todas esas cosas... de momento vamos con un ejemplo sencillo. Un cálculo sin muchas pretensiones, utilizando los dos modos principales para comparar.

Primero voy a utilizar el modo algebraico y después el modo de pila, o polaco inverso, para demostrar que ambos métodos llegan a las mismas conclusiones. Para ilustrarlo utilizo un sencillo cálculo: \(\sqrt{(2+3)}\) ... vamos a ello:

  1. Abre Calc con la combinación de teclas C-x * (yo suelo utilizar el * del teclado numérido). Después pide que pulses otra tecla normalmente será c para Calc, pero puedes investigar otros modos con ?2. Mostrará un bufer en la parte inferior de Emacs tal que:

    --- Emacs Calculator Mode ---
        .
    
  2. Para introducir la operación en modo algebraico: pulsa la tecla ' y en el minibuffer aparecerá el mensaje Algebraic:, a partir de los dos puntos escribe sqrt(2+3) y pulsa <RET>. El buffer anterior ha cambiado a:

    --- Emacs Calculator Mode ---
    1:  2.2360679775
        .
    
  3. ¿Cómo se haría en modo pila?: Pues vuelve a la ventana de Calc y pulsa 2, en el minibuffer aparecerá Calc: 2, pulsa <RET>:

    --- Emacs Calculator Mode ---
    2:  2.2360679775
    1:  2
        .
    

    Repite el proceso con el número 3:

    --- Emacs Calculator Mode ---
    3:  2.2360679775
    2:  2
    1:  3
        .
    

    Fíjate que en la pila tenemos almacenados tres valores, el cálculo que hicimos en modo algebraico y los números 2 y 3. Fíjate también en que ambos números ocupan las primeras dos posiciones de abajo. Ahora cuando pulsemos + realizará la suma de ambas.

    --- Emacs Calculator Mode ---
    2:  2.2360679775
    1:  5
        .
    

    No hace falta pulsar <RET> puesto que lo interpreta como un comando de operación, en este caso necesita tener dos valores en la pila, como las operaciones +, -,=*= y /, por ejemplo. Sin embargo, la siguiente operación necesita sólo un valor: pulsa Q... con atención a la mayúscula, porque q es el comando de salir.

    --- Emacs Calculator Mode ---
    2:  2.2360679775
    1:  2.2360679775
        .
    

Algunos pensarán que el modo algebraico es el más directo y sencillo y no hay que teclear tanto. En realidad no es así: si cuentas las pulsaciones de teclas has salido perdiendo: ', s, q, r, t, (, 2, +, 3, ), <RET>... en modo pila: 2, <RET>, 3, <RET>, +, Q.

Pero si lo que necesitas es una calculadora con botones y demás, también puedes tenerla si utilizas Emacs en modo gráfico. En lugar de lanzar Calc con la combinación C-x * c lo haces con la combinación C-x * K (modo Keypad). Y ya tienes un teclado sobre el que pulsar con el ratón.

Si no estás en Emacs y quieres utilizar su calculadora porque ya le has cogido vicio puedes llamarla desde la línea de comandos:

emacs -f full-calc

o, si quieres que aparezca el teclado numérico:

emacs -f full-calc-keypad

Uso de andar por casa

Cuando más utilizo Calc es cuando estoy liado con las facturas. Es bastante agradecido el modo pila pues me permite ir almacenando valores e incluso cambiar su orden pulsando M-<TAB>. Me permite también, copiar valores ya introducidos. Como el camino se demuestra andando, vamos con un ejemplo, también por pasos:

  1. Si no tienes activado Calc actívalo... si te molestan cálculos anteriores borra con la tecla retroceso hasta que te aparezca el habitual estado:

    --- Emacs Calculator Mode ---
        .
    
  2. Introduce en la pila los número 1, 2 y 3 por ese orden... te quedará algo como:

    --- Emacs Calculator Mode ---
    3:  1
    2:  2
    1:  3
        .
    
  3. Sólo por probar y para que se vea vamos a cambiar el orden pulsando una vez M-<TAB>:

    --- Emacs Calculator Mode ---
    3:  2
    2:  3
    1:  1
        .
    
  4. Necesitamos copiar el valor 3, que está situado en la posición 2 de la pila: pulsa M-- (sí, la tecla Alt con el guión -) y después 2, el número de orden en la pila.

    --- Emacs Calculator Mode ---
    4:  2
    3:  3
    2:  1
    1:  3
        .
    
  5. Por juguetear un poco más, imaginemos que necesitamos sumar los últimos dos números pero sin que desaparezcan de la pila. Para ello pulsamos M-2:

    --- Emacs Calculator Mode ---
    6:  2
    5:  3
    4:  1
    3:  3
    2:  1
    1:  3
        .
    

    vemos que ha copiado las dos primeras posiciones de la pila. Ahora pulsamos + y obtenemos el resultado:

    --- Emacs Calculator Mode ---
    5:  2
    4:  3
    3:  1
    2:  3
    1:  4
        .
    

¿Qué demuestra todo esto? Pues básicamente que puedo jugar con la pila para almacenar los valores más habituales e implicarlos en los cálculos, sin destruir lo almacenado. Algo bastante útil cuando en tareas tediosas como la contabilidad se repiten los mismos valores varias veces.

Además de jugar con la pila también se pueden almacenar valores en variables de una manera sencilla. Por ejemplo, basta con pulsar s s y nos pedirá un nombre de variable para guardar el valor de la cabecera (1) de la pila en ella... para devolver el valor de dicha variable a la cabecera basta con pulsar s r. Además con las variables se pueden realizar también cálculos directos sin pasar por la pila, pero eso ya cada uno que se lo mire en la documentación.

Además, por si no tienes suficiente con las variables, también se pueden almacenar y recuperar valores desde los registros de Emacs.

Corrección de errores

Es posible que cuando estamos trabajando nos equivoquemos en alguna operación y queramos deshacer alguna operación. Por ejemplo, porque nos damos cuenta que hemos hecho una resta en lugar de una suma, o al revés: pulsamos la tecla U en mayúscula (undo para los amantes del guiri)... Si nos damos cuenta que, efectivamente lo habíamos hecho bien podemos pulsar D (también en mayúscula) que repetirá la acción (redo para los guiris).

Precisión

Por defecto, Calc suele arrancar con la precisión en 12 decimales, que para la mayoría de cálculos son más que suficientes, pero se puede cambiar a la precisión que se quiera.

Para saber qué precisión estamos utilizando basta ver la línea de estado del buffer de Calc y veremos que pondrá un mensaje del tipo Calc: 12 Deg. La precisión debe ser, al menos, de tres dígitos, sin embargo, si le pedimos una precisión de 2300 decimales no va a protestar.

También podemos cambiar el formato de los números a otros formatos como el de coma fija, la notación científica (hay más modos pero no los uso.

  • d n para visualizar los números en modo normal
  • d s para visualizar los números en modo científico
  • d f para visualizar los números en coma fija.

Conclusión

Con esta introducción apenas he rascado un poco en la superficie de esta herramienta. Suena casi a profanación utilizarla para sólo hacer unas pocas sumas y productos; pero, como dice el refrán: burro grande ande o no ande, y en este caso es así, sabes que es una herramienta completa, compleja y potente. Parece que quieres matar moscas a cañonazos, pero en realidad sirve para lo mucho y para lo poco y cada uno la usará según sus necesidades.

Y si alguien tiene necesidades de cálculo más complejas sabrá que la tiene a mano, para cálculos financieros, para cálculo de vectores o de matrices, para cálculos trigonométricos... Todo sin salir de tu editor favorito y sin separar los dedos del teclado.

Nota al pie de página:

1

He de advertir que mi uso de Calc es mucho más prosaico. Apenas realizo algunos cálculos sencillos y si alguien quiere exprimirle todo el potencial que tiene, debería leerse la documentación que viene con Emacs.

2

Otro modo bastante utilizado es K para keypad que muestra un teclado donde se puede utilizar el ratón (si estás en modo gráfico).

-1:-- La calculadora de Emacs (Post )--L0--C0--September 04, 2020 06:46 PM

Blog uGeek: Visualizar aparte una Cabecera de un OrgMode en Emacs

Visualizar aparte una Cabecera de un OrgMode en Emacs

Hay momentos, al menos a mi me pasa, de todas las notas que voy registrando en mi orgmode, quiero exporta una ya sea en formato txt, pdf, markdown,......

Sigue leyendo el post completo de Visualizar aparte una Cabecera de un OrgMode en Emacs

Visita uGeek Blog

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Visualizar aparte una Cabecera de un OrgMode en Emacs (Post )--L0--C0--September 03, 2020 05:45 PM

Blog uGeek: Compilar Emacs 27.1 para Ubuntu, Debian, Raspbian y derivadas

Compilar Emacs 27.1 para Ubuntu, Debian, Raspbian y derivadas

En el Artículo anterior compilamos Nano y ahora toca el turno de Emacs. Los que utilizamos Debian, Ubuntu, Raspbian... tenemos el problema que en los repositorios oficiales, no encontramos nunca...

Sigue leyendo el post completo de Compilar Emacs 27.1 para Ubuntu, Debian, Raspbian y derivadas

Visita uGeek Blog

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Compilar Emacs 27.1 para Ubuntu, Debian, Raspbian y derivadas (Post )--L0--C0--August 12, 2020 09:10 PM

Blog uGeek: Habilitar el modo-org en Emacs, cuando abras un archivo txt o markdown

Habilitar el modo-org en Emacs, cuando abras un archivo txt o markdown

Es posible que te interese el habilitar el modo org cuando abras un archivos .txt o markdown....

Sigue leyendo el post completo de Habilitar el modo-org en Emacs, cuando abras un archivo txt o markdown

Visita uGeek Blog

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Habilitar el modo-org en Emacs, cuando abras un archivo txt o markdown (Post )--L0--C0--June 16, 2020 09:22 PM

La Pipa Plena: La entrada 37 de emacs

Aprovechando el confinamiento en /home hemos terminado la entrada 37 de lo que llamamos el curso de emacs pero más que curso, son nuestros apuntes sobre los temas con los que nos vamos encontrando y en esta ocasión es fill-column-indicator, customize-themes, ffap, free-keys y auto-save-buffers El enlace es: http://lapipaplena.duckdns.org/emacs/ ¡¡Buen confinamiento para todos y excelentes … Sigue leyendo La entrada 37 de emacs
-1:-- La entrada 37 de emacs (Post la pipa plena)--L0--C0--April 12, 2020 02:32 PM

La Pipa Plena: subida la entrada 36 al curso de emacs

Hemos subido más cosas de las que nos vamos encontrando con emacs y las hemos puesto en la entrada número 36 para tenerlas siempre a mano. Recordamos que el archivo org puede descargarse de: http://lapipaplena.duckdns.org/emacs/curs_emacs.org y el curso completo de: http://lapipaplena.duckdns.org/emacs/
-1:-- subida la entrada 36 al curso de emacs (Post la pipa plena)--L0--C0--March 24, 2020 03:22 PM

La Pipa Plena: No estamos durmiendo…

Aunque parezca que tenemos el blog abandonado, cosa no muy descabellada, la verdad es que continuamos a pleno rendimiento pero en aspectos no tan evidentes como son las entradas de un blog. Una muestra del git log del tractatus así lo confirma: Y además hemos revisado y corregido varias cosas del curso de emacs que … Sigue leyendo No estamos durmiendo…
-1:-- No estamos durmiendo… (Post la pipa plena)--L0--C0--February 23, 2020 09:34 AM

Maxxcan's Site: Proyecto Twice3D -- Impresora Recicladora

Presentación del proyecto Twice3D -- Impresora Recicladora
-1:-- Proyecto Twice3D -- Impresora Recicladora (Post )--L0--C0--November 06, 2019 12:00 AM

Maxxcan's Site: Introducción a la programación literaria

Introducción a la programación literaria
-1:-- Introducción a la programación literaria (Post )--L0--C0--October 23, 2019 12:00 AM

Onda Hostil: Mi entorno de trabajo

Me han preguntado bastantes veces cómo me organizo y, aunque hace un tiempo hablé un poco sobre mi entorno de trabajo en Emacs, desde entonces he introducido algunas mejoras así que voy a hablar de mi entorno de trabajo en general. Aprovecho para enlazar otras entradas del blog en las que hablé en concreto de las herramientas que cito para que se note que las uso de verdad y no es (solo) postureo.

La base: acta en Org

La base de mi metodología es un archivo de Org que utilizo como acta y lista de tareas. Org tiene la ventaja de que me permite añadir imágenes, código y enlaces a diferentes documentos y, además, puedo exportar la parte del acta en diferentes formatos según las manías del receptor.

Este archivo se abre directamente cuando abro Emacs por las mañanas para que pueda ver qué me queda por hacer y acceder directamente a los documentos o al código en los que estoy trabajando desde él, que se abrirán o no en el propio Emacs según su formato. Para que esto ocurra he añadido la siguiente líneas a mi archivos de configuración:

; Abrir archivos con programa que corresponda
; Lo privativo!
(add-hook 'org-mode-hook
           '(lambda ()
          (add-to-list 'org-file-apps
               '("\\.m\\'" . default)    ;; Matlab
               '("\\.fig\\'" . default)  ;; Matlab
               '("\\.xlsx\\'" . default) ;; Excel
               )))

; Abrir acta al iniciar Emacs
(find-file (expand-file-name "acta/acta.org" default-directory))

Como toda mi labor investigadora se basa en este archivo tengo, evidentemente, una copia de seguridad.

El soporte auxiliar: diario de Emacs

Aparte de tener apuntadas mis tareas por temática, llevo un diario en el que apunto qué he hecho cada día. Esto tiene una doble función: por una parte, cuando me desmoralizo y creo que no avanzo, tengo evidencia empírica de que no es así; por otra, me sirve para seguir mi proceso mental y recordar qué estaba haciendo antes de irme de vacaciones, por ejemplo. Esto me resulta crucial porque me permite tanto desconectar en cuanto levanto el culo de la silla del trabajo como tener mis ideas hiladas en un lugar que no es mi (variable) cabeza.

Para ello uso el diario de Emacs de manera poco ortodoxa, que es como me gusta a mí usar las cosas. Tengo una copia de seguridad también del diario, claro.

El producto: texto plano y control de versiones

El tercer pilar de mi organización es que todo lo que produzco (los documentos, la bibliografía, las imágenes, el código …) es texto plano. Aparte de que de esta manera podré seguir accediendo a mi información dentro de treinta años1, así puedo tener todo bajo control de versiones. Para el control de versiones uso Magit en Emacs y git en la terminal por la vieja costumbre.

Os detallo un poco más cómo funciono:

  • Documentos: escribo en Org o en LaTeX tanto los artículos como los informes y las presentaciones para clase. Para LaTeX uso el modo AUCTeX con RefTeX para las referencias bibliográficas, CDLaTeX para las ecuaciones y Company para el autocompletado.

  • Bibliografía: la manejo con Jabref y, últimamente, con Helm-bibtex desde el propio Emacs. En este último caso, uso las variables locales para seleccionar el archivo de bibliografía correspondiente a cada documento así como la carpeta donde viven los pdfs.

%%% Local Variables:
%%% eval:(setq bibtex-completion-bibliography '("ruta_a_bib"))
%%% eval:(setq bibtex-completion-library-path '("ruta_a_pdf"))
%%% End:
  • Imágenes: trabajo generalmente con svg en Inkscape, o exporto a eps o svg desde el resto de programas. El motivo es que ambos son formatos vectoriales y eps el favorito de las revistas científicas. Para las gráficas científicas, tengo el código para producir la imagen bajo control de versiones y una función que le da un estilo uniforme a todas las imágenes que exporto.

  • Código: programo en Matlab por obligación y en Julia y últimamente algo en Python por vicio. Con Matlab hago más que suficiente con no caer en las malas prácticas que fomenta. Para programar en los otros dos uso los modos específicos de Emacs y también Org para programación literaria.

Un día en mi vida

Dicho esto, uno de mis días laborales suele tener esta estructura:

  1. Abro Emacs.
  2. Leo en la lista de tareas qué me queda por hacer y en el diario qué hice el día anterior.
  3. Decido qué voy a hacer. Si hay un archivo relacionado, estará enlazado en la propia lista de tareas y se me abrirá en Emacs o en el programa externo correspondiente.
  4. Trabajo. Escribo, programo, busco papers … abro ramas y envío actualizaciones al repo según corresponda con Magit o desde la terminal.
  5. Actualizo la lista de tareas y el diario con lo que vaya terminando y las conclusiones sacadas.
  6. Cierro Emacs.

Esta rutina laboral se irá modificando según vaya aprendiendo cosas nuevas, cuando eso ya os contaré. ¡De momento contadme vosotros qué hacéis!


  1. Dudo que vaya a querer, pero podré↩
-1:-- Mi entorno de trabajo (Post Ondiz)--L0--C0--October 16, 2019 03:00 PM

Maxxcan's Site: Trabajando con R en Emacs

Cómo trabajar con R en Emacs
-1:-- Trabajando con R en Emacs (Post )--L0--C0--October 09, 2019 12:00 AM

Maxxcan's Site: Cómo gestionar tus contraseñas con Emacs y Pass

Como gestionar las contraseñas con Emacs y Pass
-1:-- Cómo gestionar tus contraseñas con Emacs y Pass (Post )--L0--C0--September 30, 2019 12:00 AM

Maxxcan's Site: Racket con Emacs

Como trabajar con Racket en Emacs
-1:-- Racket con Emacs (Post )--L0--C0--September 29, 2019 12:00 AM

Onda Hostil: Lo que he aprendido: manejar referencias bibliográficas en Emacs

Detesto instalar programas, aprender dónde están los botoncillos en un programa nuevo y que luego no me convenza y vuelta a empezar. Supongo que es uno de los motivos por los que me encanta Emacs: mismo programa, miles de tareas diferentes.

Últimamente he estado hurgando un poco en sus habilidades como gestor bibliográfico. Como ya os conté, yo suelo usar Jabref que es el programa que aprendí a usar en su momento y con el que me apaño bien para añadir referencias directamente desde la web, pero hay veces en las que manejar texto plano a pelo me parece más conveniente. ¡Y para eso no hay nada que iguale a Emacs! Os cuento un poco.

El modo BibTeX

La forma más básica para trabajar con bibliografías en Emacs es el modo BibTeX: se carga directamente al abrir un archivo con extensión .bib y nos permite organizar (M-x bibtex-sort-buffer) y adecentar (C-c C-c ) nuestras referencias.

Para insertar entradas tenemos el comando genérico C-c C-b tras el que podemos usar autocompletado, o el grupo de comandos que empiezan por C-c C-e. Por ejemplo, para crear una entrada de tipo artículo podemos hacer lo siguiente:

  • con C-c C-e C-a (o M-x bibtex-Article) creamos una plantilla para artículo;
  • rellenamos los datos necesarios, algunos comienzan por OPT porque son opcionales;
  • al acabar hacemos C-c C-c (o M-x bibtex-clean-entry) para quitar los campos opcionales que no hemos rellenado y que nos corrija el formato;
  • si no le hemos puesto una palabra clave nos sugerirá una y la entrada estará finiquitada y lista para ser citada.

Otro comando interesante es M-x bibtex-fill-entry (generalmente C-c C-q ) para alinear correctamente cada entrada bibliográfica. Y tampoco está mal establecer la variable bibtex-maintain-sorted-entries para tener las referencias en orden alfabético.

Como siempre, podemos recurrir a M-x describe-mode para que Emacs nos explique qué hace el modo. Es un modo chiquitico, pero muy útil para embellecer la lista de referencias ya que ayuda a cambiar de mayúsculas a minúsculas, quitar espacios innecesarios y míticas mierdas que, a las que somos maniáticas, nos ponen muy nerviosas.

Helm-bibtex

Mi modo favorito para gestionar las referencias bibliográficas en Emacs es Helm-bibtex. Lo descubrí intentando abrir los artículos que cito directamente desde Emacs y lo he introducido directamente en mi rutina de escritura científica (que algún día os contaré) junto con AUCTeX y RefTeX.

Es sencillito de usar: una vez instalado, lo llamamos con M-x helm-bibtex. Nos aparecerá entonces una lista de nuestras referencias bibliográficas en la que podremos elegir la entrada que queramos. Dándole a TAB vemos las acciones posibles, que se ejecutan todas en las teclas F1F12.

Como sugieren en su ayuda, he enlazado M-x helm-bibtex a la combinación Menú + b añadiendo esta línea al archivo de configuración:

(global-set-key (kbd "<apps> b") 'helm-bibtex)    

con la idea de configurar el resto de las historietas de Helm también en la tecla Menú y pulsar menos botoncicos.

Evidentemente, aunque sea muy listo este modo, tenemos que decirle dónde tenemos el archivo de bibliografía, los artículos en cuestión y las notas al respecto, si las estamos usando. Yo, como tengo un archivo y una carpeta con referencias para cada tema, establezco unas variables locales para el artículo que esté escribiendo

%%% Local Variables:
%%% eval:(setq bibtex-completion-bibliography '("refs.bib"))
%%% eval:(setq bibtex-completion-library-path  '("references/"))
%%% End:

pero si tuviera todas las referencias juntas, podría añadir ese par de líneas al archivo de configuración directamente con las rutas correspondientes.

ACTUALIZACIÓN (16/10/2019) Por algún motivo que desconozco (Windows), la ruta relativa dejó de funcionar de un día para otro y tuve que poner la ruta absoluta.

Una cosa que me encanta de este modo es que, por medio de RefTeX, localiza la bibliografía local si se usa helm-bibtex-with-local-bibliography en lugar de helm-bibtex. Algo bastante útil sobre todo cuando estamos manejando bibliografías de otras personas.

De esta manera, cuando estoy escribiendo un artículo y quiero citar algo o a alguien, abro mis referencias, busco entre ellas lo que necesito y abro directamente el archivo en el propio Emacs usando pdf-tools. En Windows (sorpresa) esto no me carrula, así que he añadido esto al archivo de configuración

(setq bibtex-completion-pdf-open-function
  (lambda (fpath)
    (call-process "acrobat" nil 0 nil fpath)))

para que me abra los pdfs con al Acrobat Reader. Si, por lo que sea, lo que busco no está entre mis referencias, el cacharro me busca en repositorios online. Me falta investigar cómo funcionan las notas, que hasta ahora no he tenido necesidad de ellas.

Org-ref

Si Helm-bibtex os ha gustado y sois fanáticos de Org como la que escribe, org-ref os va a enamorar. Sirve para gestionar las referencias bibliográficas y cruzadas en Org y nos permite añadir letreros ref, label y cite como los de LaTeX.

Lo que más me gusta de este modo es que su propia ayuda es un archivo Org en el que se usan las funcionalidades del modo. Se abre con M-x org-ref-help y nos cuenta todo lo necesario para jugar con él. Hace cosas molonas como permitir navegar por el documento siguiendo las referencias, mostrar el título y demás de los trabajos citados si ponemos el cursor encima o ser capaz de extraer la información bibliográfica de un pdf (como Jabref). Es muy chulo y lo mejor para entender cómo funciona es abrir el archivo de ayuda y hurgar.

En fin, una cosa más que puedo hacer con Emacs.

Referencias

Managing BibTeX Files with Emacs

BibTeX-Mode for GNU-Emacs

Research Literature Management with Emacs


Suena:

-1:-- Lo que he aprendido: manejar referencias bibliográficas en Emacs (Post Ondiz)--L0--C0--September 25, 2019 11:30 AM

La Pipa Plena: Entradas 33 y 34 del curso de emacs

Hemos añadido al curso de emacs dos nuevas entradas sobre las últimas cosas del curso de emacs que nos han aparecido en las amenas charlas que sobre el tema efectuamos: pass, highlight-changes-mode,  mouse-avoidance-mode, glasses-mode, list-color-display, nov, real-auto-save, transpose-frame, diff-mode, substitute-in-file-name, memento-mori, recenter-positions, pathify-directory y golden-ratio-adjust http://lapipaplena.duckdns.org/emacs/ Y tambien hemos actualizado el org correspondiente: http://lapipaplena.duckdns.org/emacs/curs_emacs.org   … Sigue leyendo Entradas 33 y 34 del curso de emacs
-1:-- Entradas 33 y 34 del curso de emacs (Post la pipa plena)--L0--C0--September 15, 2019 04:53 PM

Onda Hostil: Lo que he aprendido: Julia, Babel y Org

Ya sabéis que me gusta llevar la contraria. También que me gusta el minimalismo y usar el mínimo de herramientas posible. Así que cuando me ha dado por explorar la programación literaria y la investigación reproducible en Julia, en lugar de aprender a utilizar los cuadernos Jupyter como una persona normal, me he puesto a jugar con mi adorado modo Org y su funcionalidad para incluir bloques de código Babel1. Supongo que es lo que tiene ser la única de tu entorno (laboral) que hace estas cosas y no tener por tanto limitaciones en la elección de herramientas. Total, como en la academia no se colabora, no se va a dar el caso de que mi elección me limite. En fin, dejo la academia, que me caliento, y os explicito los motivos:

  • No instalo más software: ya estoy programando en Julia en Emacs así que no necesito mil programas y mi ordenador durará años y años.

  • Utilizo mis atajos de teclado y configuración: como sigo usando el mismo programa, no tengo que aprender dónde están otros botoncillos. Además, tengo definido cómo exportar a pdf desde Org pasando por LaTeX en mi archivo de configuración por lo que el documento final es exactamente como yo quiero.

  • Puedo cambiar de lenguaje de programación: el sistema funciona para una pila de lenguajes de programación. Puedo incluso mezclar código de diferentes lenguajes en un único documento2.

Visto esto, parece que elegir Org es una buena idea, así que paso a contaros en qué consiste la programación literaria, cómo se aplica en Org y qué tiene de especial el caso de Julia.

La idea: escribir para humanos

La idea de la programación literaria, como tantas otras buenas ideas, fue de Donald Knuth. Consiste en cambiar de lector objetivo al escribir un programa: en lugar de una secuencia de instrucciones para una máquina salpicada por algún comentario sobre la implementación, el programa se convierte en una descripción de la lógica detrás de la implementación salpicada por algún fragmento de código. De esta manera, no es necesario descifrar qué hace el programa leyendo el código porque las decisiones de diseño y la lógica se explicitan. Se puede pensar en el programa, entonces, como en una obra literaria.

Como me dedico a los métodos de cálculo, es decir, propongo una manera de calcular algo y luego demuestro mediante un ordenador que mi manera es mejor que la manera anterior, este enfoque me interesa por dos motivos:

  • Investigación reproducible: puedo escribir un artículo científico que incluya mis datos y mi código con lo que quien lo lea puede acompañarme en el proceso, obtener mis mismos resultados y verificar si que mis conclusiones son correctas.

  • Documentación útil: puedo explicar en el propio programa mi proceso mental para implementar numéricamente un cálculo que inicialmente era analítico, incluyendo matemáticas si es preciso.

Solo nos queda responder a una pregunta: ¿cómo demonios se lee esa mezcla de texto y código sin volverse una loca? Pues mediante los procesos de weaving, que deja solo lo humano, y tangling, que deja solo lo que entiende la máquina. ¡A ver si os habíais pensado que el señor Knuth no había pensado en esto! La cuestión aquí es que como tanto la documentación o explicación y el código salen de un mismo documento, ambos crecen juntos y limitamos la típica divergencia de según la documentación esta función tiene dos variables de entrada pero según el código tiene tres.

Programación literaria en Org

Ahora que sabemos qué es lo que queremos hacer, vamos a ver cómo lo hacemos en Org. No puede ser más fácil: cuando queramos meter un cacho de código escribimos

#+BEGIN_SRC lenguaje opciones_cabecera

Código

#+END_SRC

y ya está. Impresionante. Más os voy a decir: los bloques se pueden crear con las plantillas fáciles de Org situándonos en el principio de la línea y haciendo <s TAB.

Para poder ejecutar el trocito de código necesitamos primero decirle a Org que vamos a usar el lenguaje en cuestión y que ese lenguaje sea uno de los soportados. Tan sencillo como ir al archivo de configuración y añadir elementos a la lista de lenguajes:

(org-babel-do-load-languages
(quote org-babel-load-languages)
(quote (
(LENGUAJE1 . t)
(LENGUAJE2 . t)
)))

Ahora si hacemos C-c C-c sobre el trocito, lo ejecutaremos y nos saldrá el resultado debajo. Por seguridad, preguntará si queremos ejecutar y tendremos que contestarle, si somos vagos y nos gusta ver el mundo arder podemos decirle que ejecute todo el código sin preguntar con

(setq org-confirm-babel-evaluate nil)

¡Destrucción! ¡Sí!

Un detallico sobre los resultados: los trocitos de código se ejecutan por defecto como si fueran una función (opción de cabecera :results value) y solo nos devolverán el contenido si se lo pedimos explícitamente, con un return en el caso de Python, por ejemplo. Podemos cambiar la opción a :results output y, entonces, Org nos devolverá el contenido de STDOUT. Para lenguajes interpretados, podemos combinar esta opción con :session, que abre un intérprete y envía allí el código de todos los bloques que contengan dicha opción. Es un poco lío esto, pero jugando un poco con las opciones y leyendo la docu, se entiende.

También usamos las opciones de cabecera para decidir si al crear el documento exportamos el código (:exports code), los resultados (:exports results), el código y los resultados (:exports both) o nada (:exports none); para decirle a Org qué debe hacer con los resultados (:post); o para decir si queremos solo el archivo para la máquina (:tangle ARCHIVO_DESTINO), que por defecto no nos crea.

También podemos configurar cómo exporta el código al documento final. En mi caso, como el documento final es un pdf y eso pasa por LaTeX, quiero que use listingsUTF8 para los bloques de código. Se puede configurar para minted también, claro.

;; Exportar código como listings
(require 'ox-latex)
(setq org-latex-listings t)

;; Paquetes de LaTeX para código
(setq org-latex-default-packages-alist
'((""    "listingsutf8"  t)
("usenames,dvipsnames,svgnames,table"    "xcolor"    t))))

Las cuqueces y los colorinchis no se limitan al documento final, con

(setq org-src-fontify-natively t)

también tendremos colores en nuestro Org.

Ah, por cierto, el trocito de código lo podemos modificar en un buffer especial que se abre con C-c '.

El caso de Julia

Julia es uno de los lenguajes que no tiene soporte directamente en Babel porque su autor no le dio el copyright a la FSF. Por lo tanto, aparte de añadir Julia a la lista de lenguajes que puede usar Org, necesitamos los paquetes ESS y ob-julia.

Luego, hacen falta un par de líneas extra en el archivo de configuración para decirle a ob-julia dónde está el ejecutable de Julia (yo lo tengo en el PATH y por eso no le doy la ruta entera) y decirle a Emacs que use ob-julia:

;; Código Julia en Org
(setq inferior-julia-program-name "julia") ;; nombre o ruta de ejecutable
(require 'ob-julia)

(org-babel-do-load-languages
(quote org-babel-load-languages)
(quote (
(julia . t)
)))

Ale, ya puedo jugar a programar explicándome a mí misma lo que he hecho. Ahora solo me falta aplicar estas ideas al archivo de configuración de Emacs para no romperlo nunca.

Seguiremos informando.

Referencias

Documentación de Babel

Babel: active code in Org-mode

Working with source code en el manual de Org

Introduction to Literate Programming

Emacs para ciencias del dato

Julia with Emacs Org mode

Org-mode and julia: an introduction

Literate Programming Examples

Literate programming with Org-mode

Ten simple rules for writing and sharing computational analyses in Jupyter Notebooks

Drops of Jupyter notebooks: how to keep notes in the information age


Os dejo con música:


  1. También hay un paquete específico para Julia, pero ¿me gusta a mí lo fácil? No. 
  2. Lo digo como su supiese programar en múltiples lenguajes, ¿habéis visto? 
-1:-- Lo que he aprendido: Julia, Babel y Org (Post Ondiz)--L0--C0--September 06, 2019 02:00 PM

Jubilación Efectiva: Spacemacs ¿Editor definitivo?.

Pues, para mí, va a ser que no, aunque en mi lento retorno a estos andurriales, me he visto sorprendido por este entorno. Lo cierto es que este verano me he encontrado con un pequeño problema ya que se me ha oxidado algo el Emacs, por falta de uso y en la búsqueda de vídeos …

Spacemacs ¿Editor definitivo?. Leer más »

La entrada Spacemacs ¿Editor definitivo?. se publicó primero en Jubilación Efectiva.

-1:-- Spacemacs ¿Editor definitivo?. (Post Antonio Simón)--L0--C0--August 22, 2019 05:19 PM

Onda Hostil: Lo que he aprendido: Julia en Emacs

He conseguido por fin poder programar en Julia usando Emacs. Eh, que no ha sido tan fácil: algo tan sencillo como instalar el julia-mode y el ess se convirtió en un infierno. Me pasó de todo.

Primero en GNU/Linux, como no estaba usando la versión más novedosa de elementary, el Emacs de los repositorios era demasiado antiguo y no compatible con los modos que me hacían falta. Me quedaban varias opciones: (i) actualizar el sistema (lo que finalmente hice); (ii) añadir un ppa con un Emacs más moderno (bien, pero prefiero tener los paquetes de mi distro que ya he organizado alguna petarda); o (iii) compilar Emacs desde fuente (ya lo hice alguna vez y no me apetecía repetir).

Luego en Windows, donde sí tenía un Emacs lo suficientemente moderno, parece ser que Julia tiene no sé que bug y se cuelga y hay que darle a C-g para que se reviva.

En fin, que actualicé el sistema operativo y en quince minutos ya tenía un entorno para programar en Julia. Bueno, eso en mi recién estrenado Juno, en Windows me conformo con Atom, ese editor que no es un editor. Qué dura es la vida a veces.

Después de contaros mis desventuras (para eso tengo un blog), paso a resumir qué hice la vez que funcionó todo.

Julia en GNU/Linux

Julia no está en los repos, nos dejan unos binarios genéricos para que descarguemos y ejecutemos sin más. Hay que elegir unos u otros según la arquitectura de nuestro procesador. Yo, como nunca sé qué tengo lo miro así:

ondiz@slimbook:~$ lscpu
Arquitectura:                        x86_64
modo(s) de operación de las CPUs:    32-bit, 64-bit

Descargados los binarios correspondientes, es útil crear un enlace simbólico a algún lugar donde ya estemos buscando ejecutables o añadir la carpeta donde los hemos descargado al PATH, a gusto del consumidor.

Yo he elegido la primera opción, así que he hecho:

sudo ln -s RUTA_A_EJECUTABLE /usr/local/bin/julia

Cuidadín que hay que poner la ruta absoluta al ejecutable bin/julia que si no no carrula.

Julia en Emacs

Pues lo que decía al principio: para tener un entorno chachi para programar en Julia solo hace falta instalar los modos julia-mode y ess. El primero es el modo oficial para editar Julia y el segundo es un paquete que ayuda a trabajar con lenguajes de programación para estadística (ESS viene de Emacs Speaks Statistics) como R, o en este caso, Julia. Se pueden hacer otras cosas, pero esta es la más simple en mi opinión.

Una vez instalados los modos, para activar una terminal juliana inferior solo hay que hacer M-x julia. Luego ya podemos abrir un archivo en la parte superior y jugar con opciones que nos da el modo ESS.

Llevo poco con el tema y solo he memorizado un par de combinaciones útiles (miento, no las he memorizado, las escribo aquí para mirarlas en el futuro):

  • C-c C-l: carga un archivo completo, lo que sería un include("archivo").

  • C-M-x: ejecuta (me encanta esta palabra) un trozo de código en el REPL.

  • C-c C-z: cambia del script al REPL o viceversa.

Hay también una pila de comandos para gestionar errores y para acceder a la documentación que algún día controlaré. O no. También me falta echarle un ojo a imenu anywhere para que me aparezcan opciones de autocompletado en cualquier lugar. Me lo dejo de deberes.

Curiosamente, lo que más trabajo me dio fue acostumbrarme a no darle a la flecha hacia arriba para repetir el último comando en el REPL. Aquí, como las combinaciones de GNU Readline están ya pilladas, hay que usar M-p y M-n (o C-↑ y C-↓) para moverse por la historia. Comint y cosas, ya sabéis, y si no, con hacer C-h b os enteráis.

Y hala, ya tengo un entorno para programar. Contadme qué usáis vosotros para que aprendamos todos, venga.

juliaEmacs

Referencias

Página oficial de Julia

Manual del modo ess

Julia en el modo ess

imenu anywhere en GitHub


Os dejo con un grupo cuyas canciones suelo berrear en los conciertos de las fiestas de los pueblos vecinos y que tiene el mérito de que no me quedase dormida encima del libro de física de primero de carrera. Era abrirlo y bostezar, oigan.

-1:-- Lo que he aprendido: Julia en Emacs (Post Ondiz)--L0--C0--August 08, 2019 12:54 PM

Jubilación Efectiva: Compilando Emacs en Debian Stretch.

Una de las últimas tareas que acometí en mi Debian, antes de pasarme al mundo de Antergos, fue la de compilar GNU Emacs, algo necesario para dispones de su última versión, dado el sistema de gestión de paquetes de esta distribución. La tarea me imponía algo de respeto, porque hacía muchos años que no me …

Compilando Emacs en Debian Stretch. Leer más »

La entrada Compilando Emacs en Debian Stretch. se publicó primero en Jubilación Efectiva.

-1:-- Compilando Emacs en Debian Stretch. (Post Antonio Simón)--L0--C0--April 18, 2019 01:00 PM

Onda Hostil: Lo que he aprendido: el buffer de paquetes de Emacs

Años usando Emacs y no ha sido hasta hace unos meses que he descubierto que el buffer de los paquetes, ese al que entramos con M-x list-packages es mucho más fácil de usar de lo que yo pensaba.

Resulta que si te posicionas en la línea de un paquete sin instalar y le das a la i lo marcas para instalar, si vas a uno instalado y le das a la d lo marca para eliminar (delete) y si le das a la U así en general, marca los paquetes que hay que actualizar con una I (upgrade). ¿Y ahora cómo hacemos efectivas estas órdenes? Pues dándole a la x. Así todo lo que queramos borrar se borrará, lo que queramos instalar se instalará y lo que queramos actualizar se actualizará.

En la imagen se ve la I mágica de la que hablo en la columna de la izquierda del todo.

paquetes

En fin, aquí lo dejo, por si hay otro genio como yo por ahí al que le resulta útil. A cuidarse.

Referencias

48.1 The Package Menu Buffer en el manual de Emacs


Solo del punk no se vive, hoy suenan trompetas.

-1:-- Lo que he aprendido: el buffer de paquetes de Emacs (Post Ondiz)--L0--C0--April 15, 2019 11:00 AM

MGallego: Introduccion a Emacs Lisp: Seteando Variables

Existen dos formas de setear una variable en Lisp:

Usando set

Imaginemos que queremos setear una variable que contenga una lista de lenguajes de programación. Podemos hacerlo de la siguiente manera:

   (set 'lenguajes '(c python pascal php java erlang))

Esto setería una variable llamada lenguajes que contendría la lista '(c python pascal php java erlang)

Debemos fijarnos en un par de cosas, una de ellas ya la había explicado en el post anterior.

Si nos fijamos en la lista '(c python pascal php java erlang) podemos ver que la lista comienza con una comilla. Con esto lo que le estamos diciendo al intérprete es que la debe devolver tal y como está, sin evaluar nada.

Por otro lado vemos que hay una comilla simple delante del nombre de la variable. Esto es mas o menos lo mismo, no queremos que la evalúe, solo queremos pasar el elemento a la función set. Si no pusiésemos esa comilla el interprete devolvería un error al tratar de evaluarla.

De esta forma ya tenemos una variable lenguajes que al evaluarla fuera de paréntesis nos devolvería una lista de lenguajes de programación.

Usando setq

Setq es una forma un poco mas sencilla de crear una variable, aunque tampoco mucho mas, ya que lo que nos ayuda setq es en que no tenemos que poner la comilla en la variable que queremos crear. La creación de la variable anterior con setq sería de la siguiente manera:

   (setq lenguajes '(c python pascal php java erlang))

La q de setq es de quoted.

Creando un contador sencillo.

Si usamos set o setq de nuevo sobre una variable que ya tiene un valor asignado este se sobrescribe, así que podemos ver un sencillo ejemplo de esto viendo como podemos definir una variable contador en emacs.

     (setq counter 0) ; inicializador
     (setq counter (+ counter 1)) ; incrementador

     counter ; resultado

El "inicializador" lo que hace como su nombre indica es crear la variable y setearla a 0. Inicializarla. El incrementador incrementa el valor de la variable en 1, así que cada vez que ejecutemos la expresión del incrementador el valor de la variable counter se aumentará en 1.

-1:-- Introduccion a Emacs Lisp: Seteando Variables (Post )--L0--C0--April 14, 2019 03:37 PM

MGallego: Introduccion a Emacs Lisp: Listas

He comenazado a leerme el manual de introducción a Emacs Lisp, el cual es gratuito y se puede leer online aquí o descargar desde la misma dirección.

Así que voy a ir apuntando por aquí un breve resumen de lo que vaya aprendiendo, aunque no me gusta demasiado como está organizado el libro y voy a intentar solo anotar las cosas que realmente me resulten interesantes o crea que pueden llegar a aportar algo realmente

Listas

Lisp está basado en listas, un ejemplo de lista es el siguiente

     '(rose
       violet
       daisy
       buttercup)

Átomos

Cada uno de los elementos de las listas, separados por espacios en blanco se llama "atom", átomo. En el caso anterior rose, violet, daisy y buttercup serían átomos de la lista. Como buen átomo que se precie no se puede dividir en ningún elemento mas pequeño.

Pocas veces los programadores llaman átomo a los átomos, ya que se suelen referir a ellos por el tipo de átomo que es, por ejemplo string: '("texto entre comillas dobles") el texto entrecomillado con comillas dobles es un átomo de tipo string.

Listas vacías

Así que una lista en Lisp no es mas que una serie de átomos encerrados entre paréntesis. Aunque también podemos tener listas sin átomos, como por ejemplo (). Esto se llama "lista vacía"

Expresiones simbólicas

La representación de átomos o listas es llamada representación simbólica, Symbol Representation también denominada s-expression

Espacios en blanco

Los espacios en blanco no son tenidos en cuenta dentro de una lista, solo se usan como separados de átomos, pero independientemente del número de ellos. Los ejemplos siguientes representan la misma lista:

      '(atom1 atom2 atom3)

      '(atom1
        atom2
        atom3)

      '(atom1          atom2   atom3)

Ejecución de código

Cualquier lista en Lisp es un programa que se puede ejecutar. En la jerga de Lisp: evaluar.

Al evaluar una lista de lisp pueden ocurrir tres cosas:

  1. No hacer nada salvo devolver la propia lista
  2. Devolver un error
  3. Tratar el primer símbolo de la lista como un comando que realiza algo

En los ejemplos en los que hemos visto antes ponía una comilla simple delante de la lista, de está manera: '(lista de elementos) con esto se le dice al intérprete que debe devolver la lista tal cual. En el caso de no poder la comilla el interprete lo que intenta hacer es ejecutar el primer elemento de lista como una función. Como por ejemplo: (+ 2 2) que lo que haría sería sumar 2 + 2, ya que el primer símbolo + es la función de suma en Lisp.

Evaluando expresiones en Emacs

Para evaluar algo en emacs, lo mas sencillo es poner el cursor justo detrás de lo que queremos evaluar y pulsar la combinación de teclas C-x C-e. si por ejemplo tenemos dos listas una dentro de otra o queremos evaluar solamente un elemento de la lista podemos hacerlo colocando el cursor en el punto justo donde deseemos evaluar.

Por ejemplo con la siguiente lista: (+ 2 (+ 3 4)) si evaluamos después del último cierre de paréntesis el resultado devuelto será 9 pero si lo colocamos detrás del penúltimo cierre, el interprete nos devolverá 7 ya que estaremos evaluando solamente la expresión (+ 3 4). Es mas, si evaluamos justo después del 4 nos devolverá 4, ya que los números se devuelven a si mismo al evaluarse.

Generar mensajes de error

En el ejemplo anterior, si evaluásemos el símbolo + nos devolvería un error. Emacs abriría un nuevo buffer donde podríamos ver la descripción del error.

Variables

Para ver el contenido de una variable no debemos meterla dentro de una lista, se debe evaluar fuera de la lista, por ejemplo en el caso de la variable fill-column que viene ya definida en emacs, para ver el contenido deberíamos evaluarla así fill-column. En el caso de que la evaluemos de la siguiente manera: (fill-column) obtendríamos un error, ya que estaría intentando ejecutar fill-column como si se tratase de una función.

Un par de ejemplo de errores serían los siguientes:

Evaluar una variable como una función

    (fill-column)

Esto devolvería un error del tipo:

    ---------- Buffer: *Backtrace* ----------
Debugger entered--Lisp error: (void-function fill-column)
(fill-column)
eval((fill-column) nil)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
---------- Buffer: *Backtrace* ----------

Se puede ver que dice algo así como que no es una función.

Evaluar una función como una variable

Este es justo el caso anterior, en el que intentamos evaluar una función fuera de una lista, como por ejemplo evaluar el símbolo +

    +
---------- Buffer: *Backtrace* ----------
Debugger entered--Lisp error: (void-variable +)
eval(+)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
---------- Buffer: *Backtrace* ----------

Sería mas o menos que se intenta ejecutar una variable que no lo es o que no está declarada como tal.

Argumentos

Como en muchos lenguajes de programación, a cada elemento que se le pasa a una función se le llama argumento. El numero de elementos puede ser variable y el tipo de elemento también.

Si pasamos un número de elementos erróneo para una función está devolverá un error. Lo mismo pasará cuando el tipo de argumento no sea el correcto. En el caso del tipado el error devolverá el tipo necesario seguido de "-p", esa p viene de predicate. Por ejemplo si requiere una lista dirá "lisp" si debe ser zero nos dirá "zerop"

La función message

Hay una función en emacs llamada message que sirve para pintar en el buffer de echo del editor. Un ejemplo de su uso sería (message "texto a mostrar")

Conclusión

He decidido no publicar mas en este post, no tiene ni todo el capitulo 1 del libro. Personalmente me resulta un tanto caótico, ya que salta de unas cosas a otras y te mete cosas como por ejemplo la función message cuando está hablando de variables, cosa que no comprendo. Así que lo mismo intento publicar posts un poco mas cortos pero mas centrados.

-1:-- Introduccion a Emacs Lisp: Listas (Post )--L0--C0--April 14, 2019 02:41 PM

La Pipa Plena: Tutorial emacs

Entre un montón de elementos linuxeros hemos realizado una traducción del tutorial de emacs de: https://www.computerhope.com/unix/uemacs.htm Seguramente tiene bastantes deficiencias pero ahí queda para quien lo quiera usar. Lo hemos colgado en el apartado emacs de la cabecera i está en: http://lapipaplena.duckdns.org/emacs/emacs_tut.html M-x felices-orgasmos
-1:-- Tutorial emacs (Post la pipa plena)--L0--C0--March 24, 2019 05:15 PM

Podcast uGeek: Notas y Documentos en la nube para compartir, trabajar en equipo,...

Notas y Documentos en la nube para compartir, trabajar en equipo,...

Simplenote, es una aplicación de notas muy conocida de Software Libre, totalmente multiplataforma y gratuita...

Sigue leyendo el post completo de Notas y Documentos en la nube para compartir, trabajar en equipo,...

Visita uGeek Podcast

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Notas y Documentos en la nube para compartir, trabajar en equipo,... (Post )--L0--C0--March 11, 2019 04:45 AM

Jubilación Efectiva: GTD con org-mode. Primer intento.

Bueno, pues aquí estamos. Tras la formación GTD, Nivel 1, que os comenté en esta entrada anterior me he encontrado con un sistema GTD funcionando, que hay que aprovechar y sobre el que hoy os quiero hablar. Me parece importante comenzar a explicar los ajustes que, seguro, iré haciendo a mi sistema GTD para ver …

GTD con org-mode. Primer intento. Leer más »

La entrada GTD con org-mode. Primer intento. se publicó primero en Jubilación Efectiva.

-1:-- GTD con org-mode. Primer intento. (Post Antonio Simón)--L0--C0--February 17, 2019 09:55 PM

Jubilación Efectiva: Adquisición de hábitos con ayuda de org-mode.

Introducción. Cuando hablamos de «mejora personal«, utilizar un sistema como GTD es fundamental para realizar un seguimiento de las acciones realizadas, lo que favorece la revisión y el análisis de nuestras buenas o malas prácticas. Dentro de estas acciones hay una serie de ellas, conocidas como hábitos, que son una base fundamental de nuestro día …

Adquisición de hábitos con ayuda de org-mode. Leer más »

La entrada Adquisición de hábitos con ayuda de org-mode. se publicó primero en Jubilación Efectiva.

-1:-- Adquisición de hábitos con ayuda de org-mode. (Post Antonio Simón)--L0--C0--January 27, 2019 07:45 PM

Podcast uGeek: GNU-Linux, Emacs,.. ¿porqué?

GNU-Linux, Emacs,.. ¿porqué?

GNU-Linux, Emacs,.. ¿porqué?...

Sigue leyendo el post completo de GNU-Linux, Emacs,.. ¿porqué?

Visita uGeek Podcast

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- GNU-Linux, Emacs,.. ¿porqué? (Post )--L0--C0--November 21, 2018 08:53 PM

Podcast uGeek: Sincronización Selectiva en Syncthing, Markdown en Emacs, Blog Jekyll, Escritorio i3

Sincronización Selectiva en Syncthing, Markdown en Emacs, Blog Jekyll, Escritorio i3

Sincronización Selectiva en Syncthing, Markdown en Emacs, Blog Jekyll, Escritorio i3...

Sigue leyendo el post completo de Sincronización Selectiva en Syncthing, Markdown en Emacs, Blog Jekyll, Escritorio i3

Visita uGeek Podcast

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Sincronización Selectiva en Syncthing, Markdown en Emacs, Blog Jekyll, Escritorio i3 (Post )--L0--C0--October 29, 2018 07:06 PM

Podcast uGeek: Como gestiono Mis Notas Markdown

Como gestiono Mis Notas Markdown

Como gestiono Mis Notas Markdown...

Sigue leyendo el post completo de Como gestiono Mis Notas Markdown

Visita uGeek Podcast

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Como gestiono Mis Notas Markdown (Post )--L0--C0--October 14, 2018 10:34 PM

Podcast uGeek: Podcast: Iniciándonos en Emacs y Org Mode de un Modo muy muy Fácil.

Podcast: Iniciándonos en Emacs y Org Mode de un Modo muy muy Fácil.

Podcast: Iniciándonos en Emacs y Org Mode de un Modo muy muy Fácil....

Sigue leyendo el post completo de Podcast: Iniciándonos en Emacs y Org Mode de un Modo muy muy Fácil.

Visita uGeek Podcast

Visita uGeek Podcast

Suscribete al Blog de uGeek

Suscribete al Podcast de uGeek

-1:-- Podcast: Iniciándonos en Emacs y Org Mode de un Modo muy muy Fácil. (Post )--L0--C0--October 09, 2018 10:26 PM

Jubilación Efectiva: Mis maestros: Drymer, el Emacs en castellano.

Cuando descubrí org-mode y, como consecuencia, me topé con Emacs, me sentía bastante inseguro como para  trabajar en inglés sobre todo ello, y al hacer la recopilación de recursos, que por cierto creo debiera reorganizar :(, el descubrimiento del sitio de Planet Emacses, a día de hoy inactivo, fue una auténtica alegría y se convirtió …

Mis maestros: Drymer, el Emacs en castellano. Leer más »

La entrada Mis maestros: Drymer, el Emacs en castellano. se publicó primero en Jubilación Efectiva.

-1:-- Mis maestros: Drymer, el Emacs en castellano. (Post Antonio Simón)--L0--C0--October 05, 2018 04:19 PM

nba - GNU's Rock: temax

sucede que haciendo una prueba con el vps conectado via ssh queria dejar corriendo un comando

> youtube-dl -f best -ciw -v 'https://www.youtube.com/channel/UCbGYYbuGLFC6wIsyKXXW4cQ'

y salir de la sesion, dejando al vps a su bola, p-e-r-o, p-e-r-o, p-e-r-o si sales de la sesion ssh, tu comando tambien se corta

y esto no se soluciona poniendo un & al final del comando, por que este (supongo y sin idea) “proceso” es un “hijo” de tu shell que es un hijo de tu sesion y si la sesion se muere, el padre mata a todo mundo. Ja, ja, ja, ha

Como solucionar esto? pues teniendo un shell que sea “hijo de un demonio😈” que ande a su bola, e invocarlo cuando nos venga en gana

y todo esto que suena tan complicado y misterioso, es mas facil de lo que parece (creo). Encima podemos hacerlo con emacs, aunque igual, segun la situacion podriamos recurrir a otros dos programitos habitualmente disponibles en cualquier distribucion

emacs

emacs tiene un modo demonio que sirve para dos cosas:

  • cargar emacs una vez y luego lanzar instancias que comparten la misma sesion pero se manifiestan a la velocidad del rayo

  • volver independiente tu sesion de una shell, fuera esta en ssh o en modo texto o grafico

primero, para activar el modo demonio lanzamos el siguiente comando

> emacs --daemon

esto no lanzara ningun emacs, simplemente colocara bajo las sombras una sesion con la que podremos contactar. Para hacer esto necesitamos un comando particular llamado emacsclient. Como la mayoria de las cosas, no es tan sencillo. Si lo lanzamos tal cual

> emacsclient
emacsclient: file name or argument required
Try 'emacsclient --help' for more information

nos dira que intentemos ver la ayuda. Si bien, esta ayuda es basta, podriamos simplificarla a dos opciones utiles

> emacsclient -c

que nos lanza emacs en el buffer scratch.

dejemos una marca en dicho buffer para identificar nuestros pasos. Colocando por ejemplo, la frase "hola soy emacsclient uno"

bien, terminemos emacs como se haria habitualmente C-x C-c e invoquemos de nuevo a nuestro emacs-demonio emacsclient -c -nw

hala, nuestro mensaje sigue hay!

ahora en nuestra terminal (tilix) dividida, lanzamos de nuevo emacsclient -c -nw

de nuevo lo mismo

y si cerramos uno o todos los emacsclient da igual, lo que en ellos hagamos permanecera mientras no se apague el sistema o cerremos el modo demonio

la otra forma en la que podemos lanzar emacsclient, consiste en indicar que ficheros abrir

> emacsclient fichero1 fichero2 ...

y ahora con esto, podriamos resolver el problema inicial. Abrimos una shell, ponemos el comando a ejecutar, salimos (C-x C-c), cerramos el ssh y regresamos cuando lo creamos conveniente. El demonio de emacs con todos sus buffers y demas cosas, seguira realizando su labor!

y ahora? pues para terminar con el modo demonio, desde un emacsclient

M-x server-mode

nos dira que actualmente hay un servidor con clientes, que si lo queremos terminar de todas maneras, a lo que diremos que si.

cosas

emacs es un entorno centrado en el texto, que puede dividirse, expandirse y adaptarse de formas inimaginables, sin embargo, una terminal pura donde ejecutar programas visuales e interactivos escritos cada uno en su lenguaje, con sus propias librerias y forma de entender sus combinaciones de teclado, igual y queda en otra liga mas alla de los fines de emacs

tambien, aunque emacs posee su propia terminal (tonta) eshell, lo mejor es lanzar programas no interactivos. Ademas eshell, sola hay una y solo una, Emacs no es multiproceso, o hace una cosa o hace otra, pero no dos al mismo tiempo. Si lo que necesitamos son varias shell reales, lo mas conveniente seria recurrir a otras herramientas

GNU Screen

esto es un multiplexor de terminal, que segun la wikipedia:

es una aplicación de software que puede utilizarse para varias sesiones de inicio de sesión independientes basadas en seudoterminales dentro de una única pantalla de terminal, una ventana de emulador de terminal, una consola de sistema de PC/puesto de trabajo o una sesión de inicio de sesión remota, o para separar y volver a adjuntar sesiones de un terminal. Es útil para tratar con múltiples programas desde una interfaz de línea de comandos, y para separar programas de la sesión de la shell de Unix que inició el programa, particularmente para que un proceso remoto continúe ejecutándose incluso cuando el usuario está desconectado.

pero que en resumidas palabras, podria resumirse en un “emacs” para las terminales o como “un entorno de escritorio para las terminales”

y que podemos hacer con esto? tras instalar gnu screen (buscarlo como screen en su distribucion) y lanzarlo por primera vez

> screen

nos resivira con un bonito mensaje

tras presionar espacio, aparecera el prompt de nuestra shell de siempre, donde lanzar los comandos de siempre

bien no? pues si… a-u-n-q-u-e, cuando salimos de la terminal, no salimos de la terminal, saldremos de la terminal en screen

[screen is terminating]

volvamos a lanzarla de nuevo y veamos como demonios (ja, ja, que cachondo) utilizar este invento

primero, screen tiene algunas influencias emacseras, y como este, tiene un prefijo para hacer cosas, que por defecto es C-a (Control y a al mismo tiempo) seguido por una (o mas) combinaciones que serian el comando en si, por ejemplo, si presionamos C-a d saldremos de screen pero sin cerrar screen, que seguira en “segundo plano” a su rollo, rollo al que podemos regresar

como hacer esto? no es tan sencillo, primero deberemos averiguar el nombre de nuestra “sesion” y re-enlazar a ella

mientras haciamos el C-a d nos lanzaba la siguiente salida

[detached from 6469.pts-3.tachikoma]

un dato similar podemos obtenerlo con el siguiente comando

> screen -ls
There is a screen on:
	6469.pts-3.tachikoma	(Detached)
1 Socket in /run/screens/S-nasciiboy.

donde el dato importante es ese que va luego del punto del numero, hasta el primer espacio, es decir (y en este caso particular) pts-3.tachikoma. Dicho valor nos servira para recuperar la sesion

> screen -x pts-3.tachikoma

bonito no? ehhhh, mas o menos. Salgamos sin cerrar e iniciemos una nueva sesion con un nombre mas sencillo

> screen -S mi-sesion

de nuevo, tendriamos otra terminal…

repitiendo el listado de sesiones

> screen -ls
There are screens on:
	7832.mi-sesion	(Detached)
	6469.pts-3.tachikoma	(Detached)
2 Sockets in /run/screens/S-nasciiboy.

guaaa, que emocionante…

para contactar a esta nueva sesion

> screen -x mi-sesion

y? pues ahora un par de cosas medio chulas, primero podemos dividir la pantalla ¡en dos! presionando C-a S

luego puedes saltar a esta nueva division con C-a TAB. Ver el cursor en esta nueva seccion, apretar los botones a lo loco y ver que no pasa nada

hasta que invoques una shell en este espacio con el comando magico C-a c

dividir nuevamente la ventana (ahora en vertical) C-a |, saltar a esta C-a TAB, nueva shell C-a c y sonreir locamente

ahora como cerrar este conjunto, si salimos de la shell (C-d o con exit) la seccion no desaparecera, seguira hay hasta que presionemos C-a X

si por alguna razor quisieramos cambiar el prefijo C-a por otro distinto, por ejemplo C-b, tenemos dos opciones crear un fichero .screenrc en nuestro home con el contenido

escape ^Bb

con lo que el comando prefijo quedaria fijado a C-b por siempre jamas, o bien, lanzar screen de la siguiente manera

> screen -e^bB

y pocas cosas mas puedo comentar sobre screen y sus fabulosas cualidades. Para mas informacion dentro de la misma sesion presionar c-a ? invoca a la ayuda. tambien podriamos ver la pagina del manual

tmux

y… tmux es mas o menos como screen, tambien va a su rollo y puede sobrevivir al cuelgue de una sesion ssh, tiene combinaciones “tipo emacs” y sirve de “entorno de escritorio para las terminales”, p-e-r-o, p-e-r-o, p-e-r-o, por defecto es algo mas amigable y 🌈moderno🌈 (1987 vs 2007) aunque ambos estan escritos en c

y cual escogeria screen o tmux? pues, tmux! aunque si hay necesidad, se usar los dos!

y ahora, como usarlo

> tmux

como vemos, a diferencia de screen, tmux se nos comera una fila al final de la pantalla, muy a lo emacs. Otra diferencia particular, empieza por el prefijo, que en lugar de ser C-a pasa a ser C-b (y encuentro mas comodo). Ademas de eso al dividir la pantalla en sus diferentes formas

  • C-b " division horizontal
  • C-b % division vertical

aparecera una shell sin hacer nada mas

podemos deambular por las “divisiones” con

  • C-b o saltar a la siguiente
  • C-b ← saltar a la derecha
  • C-b ↑ saltar arriba
  • C-b → saltar a la derecha
  • C-b ↓ saltar abajo
  • C-b C-← redimencionar hacia la derecha
  • C-b C-↑ redimencionar hacia arriba
  • C-b C-→ redimencionar hacia la derecha
  • C-b C-↓ redimencionar hacia abajo

tambien centrar la atension en la shell actual sin romper la distribucion de las ventanas con C-b z (zoom) y luego restaurar con otro C-b z

o incluso y mas locochon, hacer que las shells cambien de sitio con C-b C-o

o hacer aparecer un reloc ascii gigante con C-b t

u otras cosas mas chulas como agregar “nuevos escritorios” con C-b c

e ir y venir entre escritorios con

  • C-b n siguiente
  • C-b p anterior
  • C-b 0, C-b 1 C-b …, escritorio 0, escritorio 1, …

o C-b w, que nos permite elegir visualmente

salir de esta secion sin cerrarla con C-b d y recuperarla con tmux attach

tambien, podriamos no salir de dicha sesion e ingresar en ella desde otra terminal, repitiendo tmux attach

que hace una cosa muy chula; adaptarse y limitar lo que se ve en la sesion con las dimenciones de la mas pequeña. Ademas, como en screen podemos darle un nombre a una sesion y vincularnos a ella

> tmux new-session -s mi-sesion # lanzar
> tmux attach -t mi-sesion      # conectar
> tmux list-sessions            # listar sesiones

esto y muchas cosas mas que pueden o no ser de interes, empiezan consultando la ayuda incluida C-b ?, su pagina man o si se desea un librillo con comentarios

https://leanpub.com/the-tao-of-tmux/read

aunque creo que el nombre “the tao of” le viene grande, pues no enseñan un flujo o estrategia de trabajo. Solo comandos con imagenes, que puedes descubrir por tu cuenta, como el obscuro proceso para congelar la pantalla, seleccionar texto y pegarlo en donde se nos ocurra aun sin sesion grafica!

en fin, yo estoy utilizando tmux para dejar corriendo en el servidor comandos de prolongado tiempo y tambien para ejecutar weechat “acumulando logs” por dias y dias en salas de irc… mera investigacion de la fauna…

happy hacking!

-1:-- temax (Post )--L0--C0--September 20, 2018 07:03 PM

MGallego: Ejecutando Test de PHPUnit en Emacs

phpunit logo

Hace un tiempo que dejé de usar php+-mode, mas que nada porque parece que lo han sacado de Melpa y me gusta tenerlo todo actualizado, así que decidí volver a php-mode, un modo que no usaba ya que php+-mode me parecía mas completo.

En php+ tenías proyectos donde podías configurar muchas cosas, como por ejemplo los tests, cosa que con php-mode no se puede, el tema es que para lo de los proyectos hace mucho que uso projectile, un modo imprescindible para programar, pero me faltaba la integración de phpunit. Por suerte tenemos phpunit.el una libreía con la cual podremos ejecutar nuestros tests.

Yo he tenido que añadir alguna cosa en mi configuración que no viene en la documentación oficial, como por ejemplo que coja el ejecutable de phpunit de una ruta de mi carpeta, si vosotros lo tenéis en el path del sistema no creo que tengáis problemas.

Pues bien, esta es toda la configuración que he tenido que añadir a mi fichero de configuración:

  (use-package phpunit
    :ensure t
    :config
    (add-hook 'php-mode-hook (lambda ()
                             (setq phpunit-default-program (concat (projectile-project-root) "bin/phpunit"))
                             ))
    )

Esto es lo que hace la configuración:

  • Hace que use-package se descargue el modo y lo instale. Si no usáis use-package deberíais echarle un ojo porque es bastante útil.
  • Añade un hook para que cuando entremos en modo php saque la ruta del ejecutable de phpunit usando la ruta del proyecto en el que nos encontramos.

Esto último me dio algunos problemas, ya que no se me había ocurrido ejecutarlo en el hook y se ejecutaba en la propia configuración, que al estar versionada con git pues también la tengo como proyecto.

Con esto ya podremos usar las funciones del modo phpunit, que podréis encontrar en su documentación. Lo suyo es que os las asignéis a alguna combinación de teclas, yo tengo que F2 me ejecute el test en el que me encuentro posicionado y F3 me ejecuta todos los tests de la clase.

  (global-set-key[f2] 'phpunit-current-test)
  (global-set-key[f3] 'phpunit-current-class)

Los tengo globales, porque es como los usaba en php+-mode, es algo que aún tengo pendiente de cambiar, en esos refactors infinitos que hacemos durante toda nuestra vida en la configuración de emacs.

Recursos

-1:-- Ejecutando Test de PHPUnit en Emacs (Post )--L0--C0--September 14, 2018 03:30 PM

MGallego: Usando Emacs Como Cliente De Correo

Una de las cosas que siempre he tenido ganas pero me ha dado mucha pereza ponerme a hacer ha sido configurar el correo para gestionarlo a través de emacs. Hace un par de días decidí dar el paso, hoy lo he estado probando y ha merecido la pena el esfuerzo

Aquí están todos los pasos que he tenido que dar para configurar una cuenta de Gmail en Emacs y en Debian.

Offlineimap

Lo primero que necesitamos es un cliente de imap. Este cliente será el que se encargue de actualizar nuestra cuenta de gmail, sincronizando los cambios entre nuestro local y el servidor de Google. Para eso he instalado offlineimap

sudo apt-get install offlineimap

Después de descargar el programa debemos configurarlo de la siguiente manera, comenzaremos creando un fichero de configuración en: ~/.offlineimaprc

El contenido del fichero es el siguiente. Esta es la configuración básica que he encontrado en los ejemplos, de aquí deberemos cambiar el usuario del email, en el ejemplo está como usuario@gmail.com. Importante fijarse que está en dos lineas.

También podremos cambiar la carpeta donde queramos que se descargue el correo. El password como podéis ver no está añadido, ese es el siguiente paso.

[general]
accounts = Gmail
maxsyncaccounts = 1
pythonfile = ~/.offlineimap.py

[Account Gmail]
localrepository = Local
remoterepository = Remote

[Repository Local]
type = Maildir
localfolders = ~/Maildir

[Repository Remote]
type = Gmail
remoteuser = usuario@gmail.com
remotepasseval = get_password_emacs("imap.gmail.com", "usuario@gmail.com", "993")
realdelete = no

folderfilter = lambda foldername: foldername not in ['[Gmail]/Spam', '[Gmail]/All Mail', '[Gmail]/Starred', '[Gmail]/Important']

holdconnectionopen = true
keepalive = 60
sslcacertfile = /etc/ssl/certs/ca-certificates.crt

Para no tener que guardar el password en texto plano en nuestra configuración de offlineimap debemos crear un par de ficheros mas y hacer alguna cosilla. Empezaremos por crear un fichero ~/.offlineimap.py con el siguiente contenido dentro:

#!/usr/bin/python
import re, os

def get_password_emacs(machine, login, port):
    s = "machine %s login %s port %s password ([^ ]*)\n" % (machine, login, port)
    p = re.compile(s)
    authinfo = os.popen("gpg -q --no-tty -d ~/.authinfo.gpg").read()
    return p.search(authinfo).group(1)

Del fichero .py no hay que tocar nada, simplemente se encarga de leer un fichero que crearemos ahora donde se encontrará la contraseña.

El siguiente paso es crear el fichero ~/.authinfo, en este fichero deberemos introducir lo siguiente, cambiando usuario@gmail.com por nuestro usuario y aquivaelpassword por nuestra contraseña.

machine imap.gmail.com login usuario@gmail.com port 993 password aquivaelpassword
machine smtp.gmail.com login usuario@gmail.com port 587 password aquivaelpassword

Y ahora viene el encriptado del fichero, ya que si lo dejamos así estaría en texto plano.

El cifrado lo realizaremos desde emacs, ejecutando el siguiente comando y seleccionado el fichero .authinfo que acabamos de crear.

M-x epa-encrypt-file

Esto nos generará un fichero ~/.authinfo.gpg, una vez creado debemos eliminar el original.

Y con esto ya tenemos configurado nuestro imap lo siguiente sería sincronizar con el siguiente comando y tomarnos algo mientras tanto, porque tardará bastante.

$ offlineimap

¿Qué pasa si tengo doble factor de autenticación en mi correo?

Posiblemente tendréis habilitado un segundo factor de autenticación en vuestra cuenta, en ese caso no podréis usar vuestra contraseña, para solucionar eso tenemos dos opciones:

  • Crear una aplicación Oauth en Google y usarla con offlineimap. Esta opción no la he probado, así que no se como se haría, si que he visto algún post comentando como se hace.
  • Crear un pasword de aplicación para el correo electrónico desde vuestra cuenta de google y usarlo como password. Aquí teneis como se realiza.

He visto quien desaconseja esta última opción ya que sería como quitar el doble factor de autenticación y recomiendan usar el token de Oauth. Mi impresión es que estaríamos en las mismas, ya que el password de aplicación tiene también la opción de cancelarlo y así invalidar esa aplicación.

Posible error con gpg

Al ejecutar todo el proceso en otra máquina me encontré con el siguiente error a la hora de ejecutar offlinimap: gpg: Sorry, no terminal at all requested - can't get input

La solución mas sencilla que he encontrado ha sido cambiar en el script de Python gpg por gpg2. Quizás antes tengais que instalarlo, en Debian sería con apt-get install gnupg2 y habría que dejar el script ~/.offlineimap.py de la siguiente manera:

#!/usr/bin/python
import re, os

def get_password_emacs(machine, login, port):
    s = "machine %s login %s port %s password ([^ ]*)\n" % (machine, login, port)
    p = re.compile(s)
    authinfo = os.popen("gpg2 -q --no-tty -d ~/.authinfo.gpg").read()
    return p.search(authinfo).group(1)

Creando el indice

Una vez ya ha terminado offlineimap de sincronizar debemos indexar, para ello nos hará falta mu, como también nos hará falta mu4e lo instalamos e indexamos.

sudo apt-get install mu4e

mu index --maildir=~/Maildir

Cron

Lo siguiente que he hecho y que mas me ha costado encontrar es como hacer estas tareas cada X tiempo, no por que sea complejo si no porque no he visto nada relacionado. Yo he decidido crear un cron que lo ejecute cada 5 minutos.

crontab -e

Y como contenido:

*/5 * * * * offlineimap -u quiet && mu index --maildir=~/Maildir

Envío de correos

Para envíar los correos desde emacs hace falta instalar lo siguiente en Ubuntu/Debian

sudo apt-get install gnutls-bin

Configurando Emacs

Aún no he tocado demasiado, estoy aún aprendiendo el modo mu4e, así que esta configuración es opcional. Dejo aquí la mía como ejemplo.

Imap

       (require 'mu4e)

       ;; default
       (setq mu4e-maildir (expand-file-name "~/Maildir"))

       (setq mu4e-drafts-folder "/[Gmail].Borradores")
       (setq mu4e-sent-folder   "/[Gmail].Enviados")
       (setq mu4e-trash-folder  "/[Gmail].Papelera")

       ;; don't save message to Sent Messages, GMail/IMAP will take care of this
       (setq mu4e-sent-messages-behavior 'delete)

       ;; setup some handy shortcuts
       (setq mu4e-maildir-shortcuts
             '(("/INBOX"             . ?i)
               ("/[Gmail].Enviados" . ?s)
               ("/[Gmail].Papelera"     . ?t)))

       ;; allow for updating mail using 'U' in the main view:
       (setq mu4e-get-mail-command "offlineimap")

       (setq
        user-mail-address "usuario@gmail"
        user-full-name  "Nombre Apellido"
       )

SMTP (envío)

    (require 'smtpmail)

    (setq message-send-mail-function 'smtpmail-send-it
          starttls-use-gnutls t
          smtpmail-starttls-credentials
          '(("smtp.gmail.com" 587 nil nil))
          smtpmail-auth-credentials
          (expand-file-name "~/.authinfo.gpg")
          smtpmail-default-smtp-server "smtp.gmail.com"
          smtpmail-smtp-server "smtp.gmail.com"
          smtpmail-smtp-service 587
          smtpmail-debug-info t)

Alertas

Nos pintará en nuestra barra un sobrecito con el número de correos sin leer, lo ejecutará cada minuto y además mostrará alertas del sistema.

  (use-package mu4e-alert
    :ensure t
    :after mu4e
    :init
    (setq mu4e-alert-interesting-mail-query
      (concat
       "flag:unread AND maildir:/INBOX AND NOT flag:trashed "
       ))
    (mu4e-alert-enable-mode-line-display)
    (defun gjstein-refresh-mu4e-alert-mode-line ()
      (interactive)
      (mu4e~proc-kill)
      (mu4e-alert-enable-mode-line-display)
      )
    (run-with-timer 0 60 'gjstein-refresh-mu4e-alert-mode-line)
    )

Como podéis ver este código por ahora es prácticamente copiado y pegado de las fuentes, como he dicho aún no he tenido tiempo de tocarlo demasiado y quizá tampoco me haga falta.

mu4e

Pues poco puedo contar de este modo, aún tengo que aprender a manejarlo bien. Si ejecutáis en emacs M-x mu4e os mostrará un pequeño dashboard donde podréis comenzar a usarlo, con documentación incluida.

Conclusión

Solo llevo un día de uso y me ha resultado muy útil, sobre todo para hacer limpieza de correos. Me costó un poco configurarlo todo, pero una vez conseguido ha merecido mucho la pena.

Una recomendación que me gustaría daros es que no uséis gmail, en este caso lo hice porque es el correo del trabajo, podéis usar cualquier correo que acepte IMAP y SMTP y seguramente con algún protocolo mas también. Os dejo con un listado de servicios y herramientas que si tienen en cuenta la privacidad del usuario, ahí podréis encontrar buenos servicios de email.

Cualquier duda puedes preguntarme por gnusocial.net.

Fuentes

-1:-- Usando Emacs Como Cliente De Correo (Post )--L0--C0--September 07, 2018 06:44 PM

nba - GNU's Rock: elipo

Recuerda, “No tiene que gustarte Emacs para que te guste”––Emacs puede tener diferentes colores, diferentes comandos y diferentes atajos que el Emacs por defecto. {AItPiEL}

An Introduction to Programming in Emacs Lisp

git clone https://gitlab.com/nasciiboy/elipo.git
# o
git clone https://notabug.org/nasciiboy/elipo.git

para descarga en formato zip, tar, o bien visionar directamente en version web en ingles y español

“Una introducción a la programación en Emacs Lisp” es una guia turistica por los conceptos basicos de la programacion, recorriendo las entrañas mas emblematicas en “las fuentes” de GNU Emacs, el “editor extensible”.

El documento es un primer acercamiento gentil, mas o menos claro y muy reiterativo a Emacs Lisp, que a un iniciado en la programacion deseoso por utilizar el verdadero potencial de emacs le vendra de maravilla. Menciono que a un iniciado, por que asi es mi caso, y me costaria recomendarlo como primer libro de programacion. Aun asi, utiliza buenas analogias e introduce los conceptos base de forma tan gradual como para no descartarlo (por completo) como libro novel.

A lo largo del material, aprenderemos ademas de los fundamentos de la programacion (variables, bucles, recursividad, funciones, …, listas), a crear atajos personalizados para las funciones de Emacs, como tambien a definir las nuestras propias, a manipular y construir listas lisp, visitar buffers, mover el punto, utilizar la region, crear funciones interactivas, a conocer el anillo de la muerte y en ultima instancia a enterarnos con certeza de lo que hacemos con nuestro init.el

…bueno, el texto esta un poco anticuado fue escrito con la version 22 (2007-2008) en mente, pero en la practica (practicamente) todo el codigo aun es aplicable, exeptuando algunas pocas funciones y configuraciones relacionadas con X Window

Antes ya habia realizado otros acercamientos a lisp como “The land of Lisp” (traduciendolo “informalmente” como hasta un 2X%) y tambien con ANSI Common Lisp, pero este ha sido el primer libro que termino y donde (mas o menos) llego a comprender las bases de Lisp… sin masterizarlo a profundidad, pues el libro no abarca conceptos como la metaprogramacion, macros y el potencial de las funciones lambda (quien sabe que signifique todo eso…)

De momento Lisp me continua pareciendo un lenguaje curioso, con algo de elegancia (no demaciada), medianamente “retro” y un poco tosco en lo que a adquirir documentacion y uso de librerias se refiere

Muchos aspectos son forzados a encajar en el molde de las listas y en otros tantos, como las “formas especiales”, simplemente se ignoran en pro de la practicidad

Mi calificacion?

  • No es una perdida de tiempo

  • Necesario si quieres profundizar en emacs o descubrir la superficie de lisp

  • Sin ser una lectura ipnotizante, tampoco es soporifera. En ocaciones cuesta seguir las ideas del autor, pero es apreciable que sin ser un escritor de profesion o vocacion (supongo) se esforza por plasmar su conocimento lo mas claro que le fue posible

porg

No recuerdo si fue en alguna busqueda de Emacs-material, en irc o directamente el la pagina de David Arroyo donde con alegria incontrolable descubri la existencia de una traduccion al español (en apariencia terminada) de este titulo, que ademas de tener una version en PDF y texinfo, contaba con el material impreso.

Con la mayor alegria que puede albelgar un aprendis del silicio y en particular usuario de Emacs que poco entiende del lenguaje ingles, procedi a descargar el PDF para recorrerlo con deseo. Sin embargo, al poco de leer, fue evidente que la version tenia defectos apresiables aun para un completo perdido del engrish.

Incredulo, supuse que la version digital y la impresa tenian algun (compresible) desfase comercial y fui directamente al repositorio donde se albergaba la fuente. Para descubrir que el material era tal cual el del repositorio

No negare que un fuerte sentimiento de desilucion aparecio al ver que habria que hecharle esfuerzo para tener un material compresible. Aunque viendolo desde otro angulo, ya habia personas que habian invertido tiempo y energia preparando el material. Que menos que unirse a la causa para sumar al material, o tan siquiera dejarlo en un punto que fuera util a mis egoistas fines

Segun el repo, la primer contribucion que hice fue el 30-05-16, pero aunque intente mantenerme constante, encontre que traducir mediante un fichero .po que ademas esta documentado en texinfo es bastante engorroso. Sumado a esto, las taras ortograficas y traductorias que cargo que son bastas (e incorregibles…), como resistirme a colocar acentos o a pasar un corrector ortografico y ademas tener en esas fechas algunos experimentos bizarros para un lenguaje de marcas ligero que cumpliera todas mis ridiculas exigencias, condujeron a que hiciera un “fork” del proyecto

“fork” etre comillas, porque no cargue con el material original. Fue una adaptacian express al lenguaje experimental de aquel tiempo (aun sin exportador, ni nada) y tras “corregir” cerca del 30% perdi la motivacion….

el asunto se fue aparcando, el formato de marcado ligero cambiando y poco interes tenia por actualizar

hasta que por diciembre del 2017 lo retome esporadicamente y luego de bastantes seciones, pues lo doy por “usable” y digno de ser compartido bajo unos pobres estandares.

Eso si, no sera ningun logro literario, pero no negare que visualmente tanto las versiones web y en morg, tienen un acabado de puta madre. Ha quedado bien chido y “profecional”

Sin embargo, la parte de la traduccion que no se como inicio, pero creo fue obra del traductor de google (y en un inico continue con la tradicion hasta que aparecio deepl) (por mi parte) consistio apenas en darle sentido a los parrafos

En muchas (por no decir que en todas) las seciones, terminaba por entrar en una face cercana al sueño y dejando presionada una tecla indefinidamente. Iniciaba una alerta de regresar a la consciencia, y… volvia a controlar la somnolencia, unos minutos mas antes de desistir.

Otro de los bellos detalles que inclui, fueron palabras con sus caracteres en posiciones alteradas de sitio. Asi como palabras repetidas y poca atencion al formato

Hay varios sitios donde es necesario hacer mas digerible la transmicion de ideas y otros donde por la falta de conocimiento del engrish solo intuia el sentido e inventaba el resto

Algunas traducciones no son consistentes, otras dificiles de transladar y unas mas se asume que ya se entienden, por ejemplo las funciones y conceptos narrow y widen, que deje como reducir y extender

Donde decia “computer” al principio substitui con computador, pero termino como ordenador, y asi otros tantos detalles

Por el lado del codigo, el proyecto de traduccion original (de libre-manuals) planeaba adaptar el codigo a una version reciente. Por parte mia, y ya que segun la wikipedia el autor de esta obra (y otras mas) Robert J. Chassel murio en 2017, he preferido dejarlo (casi en su mayoria) tal cual. (Alguna cosa cambie pero no recuerdo que exactamente.)

Otra cosa importante, es que todas las regiones de texto en el original dentro de un bloque texinfo ignore, las extripe de las versiones a “morg”. Considere que eran comentarios y ya que estaban inconclusos los quite.

Asocia la tecla ‘Bloq Mayus’ a ‘Control’ (Una interfaz de usuario tan rota, sugiere que los fabricantes de teclados piensan que las computadoras son máquinas de escribir de 1885.) {AItPiEL}

Y luego del momento de monolo, el producto central esta en los siguientes repos

git clone https://gitlab.com/nasciiboy/elipo.git
git clone https://notabug.org/nasciiboy/elipo.git

tambien hay uno en github, pero los repos hay presentes (todos inconclusos) los he congelado y/o estan en proceso de migracion hacia gitlab

Para quien desee intervenir el material, recomendaria primero leer acerca del (cambiante y experimental) lenguaje de marcas ligeras morg y si se quiere profundizar mas, seguir la etiqueta morg en este blog.

El fichero donde deben realizarce las modificaciones tanto en español, como en ingles es emacs-lisp-intro_es.porg

Para facilitar la labor, utilizo org-mode para algunas funcionalidades, como escribir listas y tener outline-mode. Algunas de las configuraciones que se pueden agregar a init.el para ayudar un poco, son:

(add-to-list 'auto-mode-alist '("\\.morg\\'" . org-mode))
(add-to-list 'auto-mode-alist '("\\.porg\\'" . org-mode))

;;; resaltado primitivo y no siempre certero de la sintaxis
(add-hook 'org-mode-hook
          (lambda ()
            (highlight-regexp "@[^[<({]+[[<({][^]>})]+[]>})]" 'hi-green-b)
            (highlight-regexp "@[[<({][^]>})]+[]>})]" 'hi-red-b)
            (highlight-regexp "@[^[<({]+[[<({][]>})]" 'hi-red-b)
            (highlight-regexp "[[:space:]]@[[:space:]]" 'hi-yellow)
            (highlight-regexp "@[a-zA-Z]+[[:space:]]" 'hi-yellow)
            (highlight-regexp "^ *@ +.*" 'hi-pink)
            )
          )

me parece que el programa que esta en los repositorios y el que utilizo en mi sistema para realizar la exportacion, difieren un poco… estaba en proceso de refactorizacion e inesperadamante cai en un bucle de poscastinacion y falta de ideas.

En los planes esta que las versiones finales de ficheros (en|es|..|xx|).morg puedan mesclarze, traducirse automaticamente, compararse, reformatearse y demas. Pero ante mi ineficacia, para este material recurri a simples trucos para generar la versiones finales apartir del fichero .porg

para producir la traduccion en español, solo tienen que borrarse todas las lineas que inicien con #. Para generar la version en ingles, mantener todas las lineas vacias y que inicien con #, y luego eliminar el # inicial mas un caracter en blanco (si lo hubiera)

he colocado unas cripticas instrucciones en el .porg, para generar ambas versiones.

De .porg a en.morg y ademas exportacion a html, seria:

awk 'length == 0 || /^#/' emacs-lisp-intro_es.porg | sed -e 's/^# \?//' | sed '8,11d' > emacs-lisp-intro.morg && morg toHtml emacs-lisp-intro.morg

y de .porg a es.morg con exportacion a html:

morg unPorg emacs-lisp-intro_es.porg && morg toHtml emacs-lisp-intro_es.morg

Si se desea verificar que los enlaces en las exportaciones html apuntan a algun lado, se puede utilizar linkchecker (presente en los repositorios de debian)

linkchecker emacs-lisp-intro_es.html --check-extern

algunas convenciones

cuando despues de un atajo se incluye el nombre de la funcion que invoca “entre parentesis”, utilizo la sintaxis @%c(nombre-de-funcion)

cuando despues de un palabro en español o ingles se coloca su equivalente en el otro idioma, utilizo la sintaxis @%i(traduccion/original)

En el documento origital varias “piezas de codigo” se colocaban entre comillas simples. Cuando lo considere pertinente y que ofrecia un mejor resaltado utilice @'c(pieza-de-codigo)

Por falta de mejora en el exportador, y sombretodo, como un apaño, dentro de los bloques de codigo, deben respetarse los espacios en blanco. Si un bloque de codigo en el original tiene una linea de espacio en blanco, debe intercaralse forzosamente el codigo en ingles, colocando la traduccion al español y que ambos bloques compartan la linea en blanco

En el original, habia condiciones para que al exportar el fuente los enlaces externos a los manuales de Emacs y Emacs Lisp estubieran accesibles desde info y en caso de exportar en un formato diferente, desde la ruta web.

un proposito futuro, es replicar este comportamiento (una vez adaptadas esas dos obras a morg), pero eso puede tardar mucho o nunca suceder. Para mantener la funcionalidad, en principio substitui toda referencia a dichos recursos con la ruta web al manual mono-pagina. Pero para evitar peticiones de varios megas a gnu.org, con la lentinud que ello conlleba, termine por colocar en el repositorio verciones locales de estos en formato web mono-pagina

En el original creo que las citas con comillas dobles y sencillas y ---, se aplicaban mediante sintaxis texinfo. Para mejorar la legibilidad en el fuente, se modificaron a “cosas”, ‘cosas’y ––. El formato morg, tiene comandos para aplicar los mismos efectos: @"(cosas), @'(cosas) y @-(cosas). Sin embargo el ultimo no esta adaptado para casos “especiales” si las cosas tienen llave de apertura pero no de cierre. Aun considero cambiar todas las apariciones “legibles a simple vista” por su version en comando, pero no lo termino de decidir

Disfrut! Bienvenidas las peleas, asesorias programacionales a morg, los exportadores de texinfo a morg, los tenedores, monitores 2K y sobre todo, el sucio dinero!

-1:-- elipo (Post )--L0--C0--July 29, 2018 05:19 PM

nba - GNU's Rock: pwds

Por lo habitual, mi uso de Emacs va emparejado con una terminal y auxiliado por el navegador de ficheros (y firefox). Asi que lo mas conveniente seria poder sincronizar las rutas de trabajo entre Emacs, Tilix (terminal) y Nautilus (navegador grafico de ficheros) sin tener que escribir cada vez la ruta entera, o andar pinchando con el raton en botones visuales

la solucion (quitando el glamour de la frace “sincronizar las rutas de trabajo de …“) consiste simplemente en copiar la ruta actual de cada programa al portapapeles

tilix

la eleccion de este emulador de terminal (ademas de por su gnomero estilo y su personalizacion de atajos profunda) se encuentra fundamentada en incorporar marcadores de fabrica. Sin embargo, optener la ruta actual y copiarla directamente al portapapeles no es una de sus caracteristicas… y por ello la solucion puede aplicarse a cualquier emulador de terminal.

para saldar la limitacion usaremos el programa xclip (buscar en el repositorio de su distribucion), en conjuncion con pwd y tr (para eliminar el salto de linea producido por pwd)

pwd | tr -d '\n' | xclip -sel clip

el comando se explica por si mismo…

otro comando que tambien suelo utilizar habitualmente para “ajustar” las fechas en los post de este blog:

date --iso-8601=seconds | tr -d '\n' | xclip -sel clip

si bien, el recordar estos comandos a primera vista parece (y lo es) una meta imposible, ya que utilizo fish como interprete y como este se encuentra en modo historial permanentemente, solo tengo que ingresar o pwd o data y el solito se encarga de completar el comando. De esa forma evito crear un script especifico para copiar cosas entre el terminal y el resto del entorno grafico

nautilus

pues nada, aunque tiene sus marcadores, si se presiona la combinacion C-l nos muestra y selecciona la ruta actual… Copiar, modificar o pegar!

Emacs

los marcadores en emacs, ademas de diferenciarlo del resto de la “competencia” lo convierten en un asistente muy potente. La cuestion es como comunicar las rutas de trabajo con el portapapeles del entorno

La solucion mas sencilla es entrar en modo dired para seleccionar y matar la ruta actual, y como la ultima entrada en el anillo de la muerte tiene comunicacion directa con el cortapapeles, tendriamos resuelto el problema… pero, ya que emacs se puede adaptar a nuestras necesidades, extendamos su funcionalidad para que copie directamente en el clipboard tanto la ruta de trabajo, como la ruta del buffer actual

(defun pwd-to-kill-ring ()
  "Agrega la ruta actual al kill-ring."
  (interactive)
  (kill-new default-directory))

(defun buffer-path-to-kill-ring ()
  "Agrega la ruta del buffer actual al kill-ring."
  (interactive)
  (if (buffer-file-name)
      (kill-new (buffer-file-name))
    (message "El buffer actual no esta ligado a un fichero")))

(global-set-key "\C-cp" 'pwd-to-kill-ring)
(global-set-key "\C-cf" 'buffer-path-to-kill-ring)

listo! con unas modificaciones minusculas tenemos nuevas funcionalidades y atajos vinculados a estas. C-c p para optener el pwd y C-c f (si el buffer actual esta vinculado a un fichero) para optener la ruta absoluta a la fuente del buffer, o en su defecto un amigable mensaje “El buffer actual no esta ligado a un fichero”

(mencionar que emacs posee el comando cd con el que podemos modificar manualmente el pwd al que apunta, como tambien un comando nativo pwd. Este pwd cambia automagicamente segun el buffer en el que estemos)

ido-mode

como el shell fish tiene un sistema de autocompletado de rutas automagico (fusionado con el historial), emacs no podia ser menos y deberia proveernos ayuda con el autocompletado de las rutas.

el modo ido nos proporciona autocompletado con “busqueda difusa” de patrones y esta disponible para la busqueda de ficheros, directorios y buffers

de inicio, es un poco lioso y si presionas tap sin antes ver que es lo que hace ido puedes verte creando ficheros en rutas inesperadas. Uno llega a cogerle el truco, pero en ultima instancia es posible desactivar sus “ayudas”

ido forma parte de la distribucion estandar, asi que no tenemos que instalar nada, solo configurarlo un poco

(require 'ido)                    ; invocar a ido
(setq ido-enable-flex-matching t) ; activar busqueda difusa
(ido-mode t)                      ; activar ido

con esto (hasta donde he podido percatarme) ido usurpara el lugar de los comandos vinculados a C-x C-f, C-x d, C-x C-d, C-x i, C-x C-w y C-x b.

Para utilizarlo basta con escribir tap para completar automagicamente y usar las flechas derecha e izquierda para navegar entre las opciones.

No hara falta escribir el nombre preciso del siguiente elemento en la ruta, con escribir algunos caracteres, por ejemplo la extencion de lo que buscamos, seguramente sea suficente.

en caso de que queramos desactivar ido y regresar temporalmente al comando que este suplantando, basta con presionar C-f. Si con esto no es suficiente y se desea apagar ido pues M-x ido-mode, o siendo mas radical, (mientras nos habituamos) podemos vincular su activacion/desactivacion a un atajo

(global-set-key (kbd "C-c .") 'ido-mode)

compile

la mayoria de los programas que realizan algun tipo de inspeccion en un fichero, como pueden ser compiladores, exportadores de formatos o programas de busqueda de patrones, suelen lanzar resultados con el formato

ruta-de-fichero:linea: "cosas"

o

ruta-de-fichero:linea:columna: "cosas"

el comando compile de emacs, se aprovecha de esta convencion para permitirnos navegar entre los ficheros que indique nuestro programa, de una forma mas comoda de lo que seria buscar directamente a mano el fichero, su linea y columna.

cuando se invoca al comando compile (M-x compile) nos pedira un comando (del sistema) a ejecutar, este podria ser por ejemplo gcc mis-cosas.c, make o por que no, grep!

Para buscar todas las coincidencias en una ruta!

M-x compile RET grep -Rn patron [ruta-opcional]

(M-x compile RET grep -Rn package ~/nconf/emacsRocks/)

sorprendente!

para navegar, entre las coincidencias podemos cambiar entre ventanas (C-x o) y dar enters en las lineas resaltadas, o, presionar C-h m y averiguar que combinaciones trae por defecto compile.

ja, ja, ja, aunque la utilidad del comando es evidente, a los peresosos emacsers les da mas por laborar una vez y descanzar eternamente. Por ello tenemos dos modos disponibles para hacer busquedas “a lo grep”.

El primero viene incorporado y se llama occur, vinculado a M-s o. El inconveniente es que las busquedas se limitan al buffer actual.

El segundo, basa su funcionalidad en un (nuevo) comando del sistema llamado ag (The Silver Searcher) que es algo asi como un grep super rapido, configurado para actuar recursivamente por defecto

hay un modo para unir en armonia tanto a compile como a ag para ello (como recomiendan en su repositorio) tendriamos que clonar el fuente y agregar lo siguiente a nuestro init:

;; source: git clone https://github.com/philsnow/ag.el
(add-to-list 'load-path "~/ruta/a/carpeta/ag.el")
(require 'ag)
(setq ag-highlight-search t)

para utilizar el comando: M-x ag RET patron RET ruta

… y eso es todo, happy hacking!

-1:-- pwds (Post )--L0--C0--April 26, 2018 09:07 PM

MGallego: Lanzando Hook al Guardar Buffer en Un Modo en Particular de Emacs

Para programar en PHP me gusta usar el modo mayor php+-mode y uno de los modos menores que uso es ac-php para usar company-mode y realizar el autocompletado. Este modo menor es bastante útil, sobre todo porque crea una tabla de tags muy buena, pero no he encontrado una forma automática de crearla, cada cierto tiempo ejecutaba el comando de generación de tags para autocompletar.

Tenía previsto desde hace mucho tiempo hacer que se regenere cuando guardo un buffer en modo php+ pero por pereza lo he ido dejando, incluso asigné una tecla al comando de tags, pero al final me decidí a hacer las cosas bien.

Actualizando tags de PHP cuando guardo un fichero en modo PHP

Este es el código que finalmente he añadido a mi configuración, a continuación os lo explico.

   (defun remake-ac-php-tags ()
   "Remake php tags from current buffer"
   (when (eq major-mode 'php+-mode)
      (ac-php-remake-tags))
    )

   (add-hook 'after-save-hook #'remake-ac-php-tags)
   

Como veis lo primero que hago es crear una función que será la que lanzaremos con el hook, podría decirle al hook que lanzase directamente la de generación de tags, pero la que he creado también filtra por el modo en el que nos encontramos.

(when (eq major-mode 'php+-mode) (ac-php-remake-tags))) Aquí está lo interesante, la condicion que dice que el modo mayor debe ser php+-mode y dentro la ejecución del comando que deseamos.

(add-hook 'after-save-hook #'remake-ac-php-tags) El siguiente paso ya es simplemente añadir la función al hook que se lanzará siempre que se guarde un fichero.

Al final el código es sencillo a mas no poder, es mas la pereza de buscar el cómo se hace, que el hacerlo. Espero que os sirva de ayuda a la hora de lanzar vuestras acciones al guardar un fichero.

Debería mejorarlo para que en realidad mirase si está el modo menor ac-php activo, pero la verdad es que aún no se como hacerlo.

-1:-- Lanzando Hook al Guardar Buffer en Un Modo en Particular de Emacs (Post )--L0--C0--April 18, 2018 08:26 PM

nba - GNU's Rock: Keep Regexp

es muy vergonZoSo sentirse capaz y al enfrentar un reto quedarse congelado al borde del fracaso

El asunto es el siguiente, tenemos un fichero con correos (muchos correos, 79 exactamente). El fichero ademas de los correos incluye nombres y comas y la meta es obtener unicamene los correos.

Empece el reto substituyendo comas por saltos de linea, luego probe una complicada regexp para buscar los correos, pero tras muchos fallidos intentos, abandone la idea… ademas, que esperaba encontrando la regexp? no es como si la coincidencia colocara la region en la coincidencia y luego se pudiera “cortar” y “pegar”

Lo siguiente, fue utilizar el comando flush-lines para borrar las lineas que no coincidieran con el patron [^@], “obviamente” no funciono, auque en mi ignorancia culpe al patron… (risa histerica) y bueno, sucede que no te aclaras y hasta se te olvida utilizar la ayuda del emacs

un par de intentos mas tarde, termine por utilizar una poco elegante macro, que cumplia el objetivo chapuceramente

luego, tras ver la primer solucion, mas simple, conpacta, no del todo “segura”, pero para el caso efectiva

cat lista_correos.txt | tr " " '\n' | grep @ | xargs

e inmediatamente despues un vi-liever solucionaba el asunto con

:%s/  */^M/g
:v/@/d
:%join

como podia evitar la inminente culpa y herida en el orgullo klingon-emacsero?

intetentando superar la frustracion, dio inicio un aprendizage formal y profundo de las regexes en emacs y alguno que otro comando mas. Pero antes de pasar a ello, fue nesesario aminorar el trauma implementando una solucion en awk y otra en C….

# esto a un fichero, por ejemplo a.awk
1 {
    for( i=1; i<=NF; i++ )
        if( $i ~ /@/ ){
            printf( "%s\n", $i)
        }
}

# y luego ejecutar con:
# $ awk -f a.awk lista_correos.txt

aca la solucion con C. Compilar con gcc a.c regexp4.c y ejecutar con $ a.out lista_correos.txt

Un dia despues, con la agonia mental aun fresca, llego la solucion en emacs

M-<
M-x replace-regexp RET " +\|," RET C-o RET
M-<
M-x keep-lines RET "@" RET

(no conocia keep-lines si tu tampoco, te la presento. Ignorar las comillas son para delimitar la cadena de entrada)

ciertamente mas extensa que vi, pero consideremos que emacs no tiene una simbiosis con el comando sed, ni tampoco una implementacion de sus comandos de tal forma que puedan ejecutarse “en bloques”. No esta tan mal, supongo.

aqui es donde se podria iniciar una “guerra santa”. Pero bueno, la naturaleza extensible e ilimitada de emacs para un tema concreto puede ser menos eficiente, es cierto… aunque, nada impide que se implemente un comando interprete tipo sed e incluso otro para aplicar acciones por lineas y de manera global (sin recurrir a macros)

Supongo que los usuarios del modo maligno, han hecho algo asi, mas profanar emacs con tales paganismos, ni utilizar “modos” que fuerzan a presionar ESC de forma inconciente, son algo a contemplar por mi parte, las cosas “modales” son un dolor, ya es suficientemente modal tener que usar el firefox, o el navegador de ficheros y andar presionando ahi teclas de otros “modos”

o, por aca un semi-equivalente en elisp de la solucion

(defun emailtor ()
  "Separa los correos en lista_correos.txt"
  (interactive)
  (goto-char (point-min))
  (while (re-search-forward " +\\|," nil t)
    (replace-match "\n" nil nil))
  (goto-char (point-min))
  (delete-non-matching-lines "@"))

ha, no es lo mas fino, pero para el caso cumple

regexp

  • Conjunto []. Conjunto inverso [^]. Dentro de los conjuntos (con la syntaxis completa [[:clase:]]) se permiten las clases

    • [:alnum:] caracter alfanumerico
    • [:alpha:] una letra, incluidos caracteres unicode
    • [:blank:] espacio y tabulacion
    • [:cntrl:] caracteres ASCII de control
    • [:digit:] numeros ascii del 0 al 9
    • [:graph:] cualquier caracter visible, exepto espacios en blanco
    • [:print:] cualquier caracter visible, incluidos espacios en blanco
    • [:lower:] caracteres en minusculas
    • [:upper:] caracteres en mayusculas
    • [:punct:] signos de puntuacion
    • [:space:] espacios en blanco
    • [:word:]caracteres que formen parte de las palabras
    • [:xdigit:] caracteres hexadecimales (0-9, a-f y A-F)
    • [:ascii:] caracter ASCII
    • [:nonascii:] cualquier caracter no ASCII
    • [:multibyte:] caracteres unicode multibyte
    • [:unibyte:] caracteres codificados en un solo byte (basicamente todo ASCII)
  • punto .

  • metacaracter \

  • agrupacion y captura \(\)

  • coincidencia con la anterior captura \d. (Substituir d por el numero de captura)

  • agrupacion sin captura \(?:\)

  • alternativa \|

  • cuantificadores

    • ? cero o uno
    • * cero o mas
    • + uno o mas
    • \{n\} exactamente n
    • \{n,\} n o mas
    • \{n,m\} entre n y m
  • modificadores

    • $ coincidencia al fin de linea
    • ^ coincidencia al inicio de linea
    • \= coincidencia en la posicion del punto
    • \' coincidencia al final del buffer
    • \` coincidencia al inicio del buffer
  • fin o inicio de palabra \b

  • (deacuerdo al modo) un caracter que forme palabras \w o \sW

  • (deacuerdo al modo) un carac,ter que no forme palabras \W o \Sw

  • espacios \s- o \s (”\s”)

  • symbolos \s_

  • delimitador de apertura \s(

  • delimitador de cierre \s)

  • caracteres de puntuacion \s.

comandos de utilidad

  • (search-forward) busqueda de texto hacia adelante
  • (search-backward) busqueda de texto hacia atras

  • C-s (isearch-forward) busqueda de texto de forma interactiva hacia adelante

  • C-r (isearch-backward) busqueda de texto de forma interactiva hacia atras

  • (search-forward-regexp) busqueda de regexp hacia adelante

  • (search-backward-regexp) busqueda de regexp hacia atras

  • C-M-s (isearch-forward-regexp) busqueda de regexp de forma interactiva hacia adelante

  • C-M-r (isearch-backward-regexp) busqueda de regexp de forma interactiva hacia atras

  • M-s o (occur) listado interactivo de lineas que coinciden con la regexp

  • (replace-string) substitucion de texto

  • (replace-regexp) substitucion de regexp

  • M-% (query-replace) substitucion interactiva de texto

  • C-M-% (query-replace-regexp) substitucion interactiva de regexp

  • (highlight-lines-matching-regexp) resaltar cualquier linea que coincida con una regexp

  • (highlight-regexp) resaltar una regexp

  • (unhighlight-regexp) des-resaltar regexp

  • (flush-lines) eliminar lineas que coincidan con la regexp. (el patron ^$ eliminara todas las lineas en blanco)

  • (keep-lines) se eliminan las lineas que no coincidan con la regexp

  • (align-regexp) alinea (verticalmente la parte en varias lineas que coincida con la regexp

re-builder, isearch, isearch+

De entre las muchas cosas relacionadas con regexes, el modo re-builder es uno muy interesante, pues nos permite escribir y editar una regexp con suma facilidad y luego copiar el resultado.

Supongo que este modo, es una facilidad para los programadores de emacs, basandome en que la expresion esta entrecomillada y al copiar la regexp con el comando reb-copy (C-c C-w) incluye las comillas y ademas el formato de escape de caracteres esta dispuesto a la forma que requiere el codigo fuente en elisp.

Dicho escape de caracteres y metacaracteres, se debe a la naturaleza de las cadenas en C de hay que las cosas suelan requerir escapes para los escapes. Por defecto re-builder viene en modo de syntaxis read que es de la que hablo, pero tambien podemos cambiar a sintaxis string (la que utiliza isearch), bien presionando la combinacion C-c TAB y escribiendo string o directamente colocando lo siguiente en nuestra configuracion

;; re-builder
(setq reb-re-syntax 'string)

pese a la facilidad de edicion y creacion de regexes, me pregunto la razon de no vincular este modo con isearch. Mas adelante (o no) una posible razon y un par de soluciones.

los comandos basicos de utilidad

  • C-c C-w copiar regexp (comillas incluidas)
  • C-c C-q salir del modo
  • C-c TAP cambiar syntaxis de entrada
  • C-c C-r ir a coincidencia previa
  • C-c C-s ir a coincidencia siguiente

isearch en sus modalidades mas conocidas isearch-forward-regexp (C-M-s) e isearch-backward-regexp nos permiten buscar expresiones regulares hacia adelante y hacia atras del punto interactivamente, mas no dejeis que os engañen las funciones basicas de estos comandos, pues no son simples comandos, son modos por si mismos, podemos averiguar sus muchas posibilidades (ya dentro de isearch) presionando C-h m o con la documentacion de la funcion C-h f isearch-forward-regexp

quiza el comando mas conocido de las busquedas interactivas sea C-w que toma la entrada sobre y delante del punto como texto de entrada (dividida por palabras). Pero ademas de esa combinacion tenemos otras muy interesantes

  • M-s e para editar “con papeles” la regexp, aunque no interactivamente
  • C-M-y ingresar a la regexp el caracter del buffer sobre el que esta el punto
  • C-M-w borrar el ultimo caracter de la regexp
  • M-s C-e ingresar a la regexp el resto de la linea apartir de la posicion del punto
  • C-y traer ultima cadena del anillo de la muerte
  • M-y iterar sobre el contenido del anillo de la muerte
  • M-c cambiar la sensivilidad a las mayusculas-minusculas
  • C-s siguiente coincidencia
  • C-r anterior coincidencia

y muchas otras cosas misticas y confusas mas trae el modo. La cuestion problematica tiene que ver con la forma en que isearch incorpora el contenido del anillo de la muerte a la busqueda, pues si por ejemplo matamos la cadena \(group\)[set] al hacer el yank (C-y) en lugan de ingresar \(group\)[set] escapara los caracteres significativos en la regexp, dejando \\(group\\)\[set] lo que obligaria a editar de forma penosa la expresion

preguntando en reddit, el unico lugar donde aparecen respuestas prontas y en ociones con feliz resultado, oantolin proporcionaba el siguiente comando alternativo para hacer el yank con su contenido tal cual dentro de la expresion

(defun isearch-yank-kill-literally ()
  "Pull string from kill ring into search string literally."
  (interactive)
  (setq isearch-yank-flag t)
  (let ((string (current-kill 0)))
    (isearch-process-search-string
     string
     (mapconcat 'isearch-text-char-description string ""))))

(define-key isearch-mode-map (kbd "C-S-y") #'isearch-yank-kill-literally)

como puede verse, se sugiere la vinculacion al atajo Control-Super-y, pero en mi caso me es incompatible con otro comando… lo que sirvio fue suplantar directamente el comando yank de isearch dejando como nombre de la nueva definicion solamente isearch-yank-kill

cabe aclarar, que la copia tal cual del contenido del anillo de la muerte, no es una caracteristica considerada de inicio en isearch, por lo que al hacer un M-y, el demas contenido del anillo seguira siendo modificado con escapes. De hay que otro colega, 00-11, suguiriera el uso del modo isearch+, que si considero esta necesidad en su base

isearch+ (supongo) es una capa sobre el modo isearch que ademas de agregar la posivilidad de hacer yanks sin modificar el contenido, nos colorear la busqueda en secciones y proporciona varios comandos de utilidad extra. Todo esto manteniendo los atajos de isearch (casi) intactos

isearch+, no viene en el repositorio melpa, para instalarlo deberemos copiar directamente su codigo desde emacswiki a un fichero, y luego cargarlo “a mano”.

https://www.emacswiki.org/emacs/download/isearch%2b.el

En el mismo fichero proponen cargar el modo con el comando

(eval-after-load "isearch" '(require 'isearch+))

pero he preferido agregar lo siguiente en mi init

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PACKAGE*: isearch+            ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; source: https://www.emacswiki.org/emacs/download/isearch%2b.el
(load-file "~/.emacs.d/plugins/isearch+.el")

vamos con la justificacion de utilizar isearch+, que era poder hacer yanks.

En la linea 2547, tenemos la variable customizable isearchp-regexp-quote-yank-flag que si la ponemos a nil, asi

    (defcustom isearchp-regexp-quote-yank-flag nil

nos dara el resultado que buscamos.

Si, se puede hacer el cambio de la varible en el init, pero ya que tenemos y vamos a cargar el codigo directamente, mejor dejarse de historias y hacer el cambio in-situ

(nota: al cargar isearch+ substituye automaticamente a isearch. He probado el modo con emacs 25 sin ninguna extencion y funciona sin problemas)

ahora si, despues de tener isearch+ configurado, podemos escribir nuestra funcion en re-builder (modo de syntaxis string) y copiar la regexp (manualmente) ignorando los parentesis, para luego “pegarlo” directamente en isearch(+) con un yank

Enlaces, fuentes y otras cosas

-1:-- Keep Regexp (Post )--L0--C0--April 08, 2018 04:50 PM

nba - GNU's Rock: The Holy War

Post original (04/12/2001) -> https://www.linux.com/news/emacs-vs-vi-endless-geek-holy-war

Author: JT Smith

Ahí van de nuevo. El presidente de nuestro grupo local de usuarios de Linux envió el mensaje de que el tutorial de la semana sería cancelado. El hecho de que el tutorial fuera sobre el uso del editor de texto vi fue suficiente para iniciar una nueva ronda de tiros de última hora.

Greg Menke disparó la primera salva. Usar vi? ¿Qué tan difícil puede ser? Envió por correo electrónico sus propios pasos para usar vi. Fueron estos:

  1. Adquirir un pecado, de cualquier tipo, longitud > 30 cm

  2. Congelarlo durante la noche

  3. Siéntese frente a la PC, ejecute vi

  4. Sosteniendo el pez por la cola, golpéelo repetidamente contra su frente hasta que decida darle una oportunidad a EMACS porque las escamas de pescado están volando alrededor de su cabeza y comienza a doler.

Menke, por supuesto, insinuaba que no sólo vi era insensatamente obstinado sino que los usuarios de vi también lo eran por negarse a admitir cómo se estaban infligiendo a sí mismos brutales golpes en la cabeza con un pescado congelado.

No tardó mucho para que los amantes de vi devolvieran el fuego. Uno sugirió a Menke que agregara esta línea a sus instrucciones: Escriba 'emacs' antes del paso 1, para que cuando el paso 4 esté hecho, finalmente haya terminado de cargarse.

¿Intentaba decir que EMACS es lento?

Al igual que los batallones fatigados por la lucha llegan a una tregua temporal pero se niegan a abandonar la guerra, los usuarios de vi y EMACS mantienen un intranquilo punto muerto en GNU/Linux, SAGE y muchas comunidades virtuales relacionadas con computadoras. Es el tipo de empate que puede permanecer inactivo durante meses, pero sólo se necesita una pizca de vaguedad de un lado para que una vez más las llamas se propaguen por los grupos de noticias y las listas de correo. Porque justo por debajo de su conducta civilizada, cada bando siente que el editor que usa es el mejor de todos los editores posibles y aquellos que usan cualquier otro editor, particularmente ese otro editor, son tontos que se daran cuenta de su erronea forma de pensar aunque sólo sea posible a base de muchas burlas.

Ahora, una escision sobre cual editor de texto en Unix es una construccion del mismisimo Dios puede no parecer significativa dados todos los problemas del mundo, un empate de Coca-Cola vs. Pepsi sin consecuencias, sin motivaciones más allá de la simple unión grupal (¡Vamos Equipo!).

Pero, ¿por qué esta diferencia de puntos de vista ha seguido siendo un divisor de la cultura de los programadores durante más de dos décadas? ¿Por qué ha permanecido intacta en el PC, luego de que las interfaces gráficas de usuario, el ratón, Internet y el código abierto han alteraron el panorama computacional?

Desde que tengo uso de razon, la población de hackers se ha dividido 50/50 [entre] EMACS [y] vi, escribe en un email Eric Raymond, quien tiene varios roles en las comunidades de software de código abierto y hackers como antropólogo observador y participante desde hace mucho tiempo. Pico, Joe, MicroEmacs, y otros editores han estado básicamente abajo en el ruido estadístico durante todo el período. Raymond puede datar personalmente la división vi/EMACS en 1985 y estipula que, con toda probabilidad, fue mucho antes de eso.

Ya en 1991, Raymond registro la guerra santa vi vs. EMACS en el Jargon File, quizás la colección definitiva de la terminología hacker.

Cuando se presiona, la mayoría de la gente familiarizada con ambos editores dirá que la diferencia entre los dos es de velocidad vs. flexibilidad, con los usuarios de vi señalando lo rápido que pueden moverse y los amantes de EMACS pregonando su inmenso número de opciones. Los usuarios de vi se burlan de EMACS por ser innecesariamente ostentosos; los usuarios de EMACS se burlan de vi por ser difícil de aprender y tener un alcance limitado.

Así que el gran debate del editor de textos de nuestro tiempo se reduce al equivalente técnico del gustos menos/o-mas relleno. Bueno, sí, más o menos. Pero como en todos los asuntos relacionados con la religion ––o la guerra––, cuanto más se profundiza, más oscuros se vuelven los temas.

Pero aqui hay algo significativo. Estos editores son la tabula rasa sobre la que se ha construido gran parte del ciberespacio. El hecho de que estas herramientas, cada una diseñada para ser transparente para el usuario final, estén sujetas a lealtades tan feroces y competitivas, revela algo acerca de algunas suposiciones primordiales que la gente tiene acerca de las mejores maneras de hacer las cosas.

Vi: ¿El editor que el tiempo olvidó?

A primera vista, los forasteros podrían ver a vi como el editor que el tiempo olvidó. No es sólo que tienes que abrir una ventana de terminal sólo para usar la cosa. Esa también es la mejor manera de conseguir EMACS. Pero incluso con VIM, la versión actualizada que la mayoría de los usuarios de vi emplean hoy en día, uno no puede evitar maravillarse (o frustrarse) por la falta de intuición sobre su funcionamiento.

Incluso el webmaster de la página de inicio de los Amantes de VI admite que la curva de aprendizaje es empinada. Vi no es mas veloz antes de conocer 25 comandos más o menos, escribe Thomer Gil, oriundo de Ámsterdam, que actualmente trabaja en un doctorado en ciencias de la computación en el Instituto Tecnológico de Massachusetts.

Gil ha sido comparado por sus compañeros de oficina con un cavernícola que blandía un hacha y un garrote por su uso de VIM.

De todas las deficiencias percibidas en vi, tal vez la más notable sea la necesidad de ingresar la tecla de inserción sólo para escribir cualquier cosa en la pantalla. Vi tiene dos modos: Uno es el modo insertar en el que se puede introducir texto. Se accede a este modo pulsando la tecla insertar del teclado. Pero también existe el modo de comando en el que no se puede introducir texto, sino comandos relevantes. Desde el modo de inserción puede llegar a este ultimo pulsando la tecla de escape.

Así que imagínese al usuario desprevenido escribiendo por primera vez y que accidentalmente presiona la tecla de escape, sólo para descubrir que no sólo no puede ingresar más texto, sino que sus pulsaciones envian extrañas instrucciones al programa .

El Jargon File observa secamente que esta característica de vi tiende a frustrar infinitamente a los nuevos usuarios, ya que no toma comandos mientras espera texto de entrada ni viceversa, y la configuración predeterminada no proporciona ninguna indicación del modo en el que se encuentra el editor.

Los múltiples modos asustan a la gente, admite Gil.

Vi fue escrito por Bill Joy en 1976, quien lo forjó a partir de dos herramientas de edición aún más primitivas, ed y ex. Vi significaba interfaz visual, que en 1976 estaba en la vanguardia de la informática, según una entrevista a Joy en la Linux Magazine.

Intentaba hacerlo utilizable con un módem de 300 baudios. Esa también es la razón por la que tienes todos estos comandos divertidos. Apenas funcionaba usar un editor de pantalla sobre un módem, dijo Joy, Así que el editor estaba optimizado para que pudieras editar y sentirte productivo cuando pintaba más lento de lo que pensabas.

En esa entrevista, Joy contrastó el entorno de desarrollo de vi con el de EMACS, dijo que fue escrito para sistemas con enlaces de canales de fibra y un monstruo PDP-10.

Así que podrían tener comandos divertidos con la pantalla brillando y todo eso, y mientras tanto, estoy sentado en casa en una especie de vivienda excedente de la Segunda Guerra Mundial en Berkeley con un módem y un terminal que apenas puede sacar el cursor de la línea de fondo, dijo Joy, tal vez sonando un poco envidioso. La gente no sabe que vi fue escrito para un mundo que ya no existe.

Sin embargo, aunque vi debería haber desaparecido a principios de los años 80 a medida que aumentaba la velocidad de la red y del procesador, ha florecido. Las VI Pages listan cerca de 30 clones vi desde elvis y VIM hasta obscuridades tales como WinVi y vigor.

Tim O'Reilly, autor intelectual de la editorial O'Reilly & Associates, señaló en la columna Ask Tim de su empresa, que su empresa vende el doble de libros de vi que de EMACS. Además, O'Reilly apoya un juego de pintura de vi vs. EMACS en alguna convención, invariablemente el doble de voluntarios se inscriben para defender el honor de vi sobre EMACS.

Entonces, ¿cuál es el atractivo? Esto se describe mejor en el Culto de VI, en el que John Arundel escribe: Al ver a un gurú de vi haciendo una edición intensa en un archivo, mientras sus dedos sobrevuelan las teclas y las transformaciones textuales barren la pantalla, uno podría creer que está en presencia de poderes sobrenaturales.

Gil publica algunos ejemplos de esta magia en su sitio web. Un concepto clave en vi es combinar una determinada acción (borrar, copiar a búfer, escribir en mayúsculas, etc. con un movimiento (ir a la línea 25, ir al final del documento, ir a la siguiente coincidencia de 'foo', ir a la segunda coincidencia del carácter 'x' en esta línea, etc.)).

¿Eh? Le envié un correo electrónico.

Gil devuelve un ejemplo: Si, por ejemplo, un documento contiene las líneas: 'a b c d e f g h' y el cursor está situado en 'b', luego puedo escribir d/f.

La primer d significa borrar, la / es una función de búsqueda, así que lo que hará este comando es borrar de b a f.

No se requieren circunstancias especiales para usar esto... Borrar palabras, oraciones. Vuelve a donde estaba antes. Oh, no, salta de nuevo. Deshacer lo que hice, rehacerlo, escribe Gil.

Gil estipula que también puedes hacer trucos como este en EMACS. Sin embargo, se requiere memorizar combinaciones de teclas apestosas Ctrl-X Ctrl-c Alt-F4 para su ejecución.

Otro truco que Gil revela es cómo VI permite a los usuarios moverse dentro de los ficheros. La manera estúpida es usar las teclas de flecha; hay muchas otras maneras más avanzadas de moverse, escribe Gil. Entre las formas avanzadas de movimiento que ofrece vi se encuentra la opción de saltar a los últimos saltos del cursor, o a la siguiente ocurrencia de una palabra en particular, o a la siguiente oración o párrafo.

Incluso la característica de modo dual se vuelve transparente para los usuarios. Hace un año entrevisté a Jon Lasser para escribir sobre su entonces reciente libro Think Unix, (cuyo manuscrito, me dijo, fue compuesto enteramente en vi). La conversación finalmente llegó a vi, y me quejé de los dos modos.

Lasser explicó que no veía ninguna diferencia entre trabajar en vi y en procesadores de texto como StarOffice o Microsoft Word. En Word, cuando mueve el puntero fuera del área de pantalla, no puede escribir texto. De hecho, pasar del modo de inserción al modo de comando. Es lo mismo, explica.

Como O'Reilly escribió sobre vi: Como muchas cosas sobre UNIX, sólo parece difícil.

Más es más con EMACS?

Cuando el lealista de vi O'Reilly escribió en Ask Tim que primero cambió de EMACS a vi sólo después de que su perfil personalizado de EMACS fue destrozado, fue uno de esos jabs sutiles que a los usuarios de vi les gusta usar en contra de EMACS.

EMACS contrasta con la prístina limitación de comandos de vi, con su personalización casi infinita. Sin embargo, dado que la naturaleza humana es lo que es, tal poder en manos de los usuarios puede no ser siempre lo mejor.

Como dice el Emacs-Beginner-HOWTO, EMACS puede ser un editor de texto, un cliente de correo, un lector de noticias, un procesador de texto, un editor de scripts y un entorno de desarrollo integrado para lenguajes de programación.

La clave para esto son los múltiples modos, cada uno con un conjunto de comandos único, que EMACS ofrece. ¿Quieres comprobar el correo electrónico? Sólo tienes que pasar al modo de correo electrónico. ¿Quieres escribir un programa en C++? Utiliza el modo C++. ¿Necesita crear algunas páginas Web? Salta dentro del modo html-helper.

Y además de todo esto, también puedes personalizar EMACS e incluso añadir nuevas funciones, normalmente modificando su código en Lisp.

Es por todo esto que muchos usuarios de vi lo ven como terriblemente presuntuoso para lo que se supone que es un simple editor de texto, sin mencionar que distrae al usuario. La broma en curso sobre EMACS es que es un sistema operativo con un editor de texto adjunto.

EMACS como tal comenzó como un proyecto de estándares, escribe Guy Steele, uno de los creadores de EMACS, junto con Richard Stallman, quien más tarde fundó la Free Software Foundation.

Tal y como recuerda Steele, Stallman mantuvo un primer editor para el PDP-10 llamado TECO, que significaba Text Editor and COrrector. A pesar de que ciertas pulsaciones de teclas realizaban comandos de edicion, Stallman creo una tabla programable por el usuario, de manera que cada pulsación de tecla realizaba una búsqueda en la tabla que describía qué hacer para esa pulsación, según dice Steele. Una opción era ejecutar una macro TECO especificada por el usuario.

Usando esta funcionalidad de macros, los usuarios estaban programando conjuntos personalizados de macros para ser vinculados a varias pulsaciones de teclas, pero esto se volvió problemático cuando los programadores comenzaron a colaborar en programas y descubrieron que tenían pocas pulsaciones de teclas comunes entre ellos.

La comunidad de usuarios se había fragmentado con respecto a las habilidades de edición de textos (y programas), escribe Steele. Así que Steele, junto con David Moon y Stallman, asumió el proyecto de integrar todas las ideas en un conjunto de comandos unificado.

Inventé una matriz en papel y corrí mucho de un lado a otro entre los implementadores y usuarios de los distintos paquetes de macros, dice Steele en un correo electrónico.

Recuerdo esto muy bien, recuerda Dan Weinreb, quien fue uno de los primeros alfa testers de EMACS. El tipo tenía un portapapeles con un pedazo de papel que mostraba todas los atajos, y recogió cuidadosa y diplomáticamente los comentarios de todo el mundo para unificarlos, en atajos estándar.

Después de unos meses, Steele, ocupado tratando de terminar su tesis de maestría, entregó la obra a Stallman. Y el resto es historia.

El hecho de que la flexibilidad se horneara desde el inicio le da a EMACS su ventaja, dicen los usuarios hardcore.

Pienso en EMACS como la navaja suiza de los editores, menciona en un correo electrónico a Debra Cameron, coautora de Learning GNU Emacs y presidenta de Cameron Consulting. Es un ambiente de trabajo completo, un microcosmos. Si piensas en algo que desearías que hiciera, probablemente descubrirás (después de mirar a tu alrededor) que ya lo hace. Si no lo hace, puedes extenderlo y hacer que haga lo que quieras que haga.

¿No podemos llevarnos todos bien?

Entonces, ¿cómo difiere EMACS de vi?

He visto a usuarios de vi muy hábiles hacer algunos trucos bastante ingeniosos, pero sigo pensando que vi es (sólo) un editor, incluso si para algunos es un gran editor, menciona Cameron. Siempre, siempre funciona de la misma manera. En este sentido, vi es como McDonald's; no importa a donde vayas, es exactamente lo mismo.

¿Quieres un editor que se adapte a tus necesidades y peculiaridades y que haga muchas, muchas cosas o simplemente quieres ser capaz de editar archivos rápidamente en cualquier máquina? pregunta ella. Para la gente que tiene que moverse de un ordenador a otro constantemente, esta consistencia puede ser una ventaja real.

En otras palabras, EMACS = flexibilidad, mientras que vi = uniformidad?

Aquí es donde las cosas se ponen turbias.

EMACS es ciertamente más complejo que vi, pero no creo que sea más poderoso de ninguna manera útil, porque vi fue diseñado para ser parte de un sistema UNIX e interactuar con esas herramientas, replica Jon Lasser.

Tenga en cuenta que, para Lasser, útil significa la forma en que vi le permite leer documentos directamente desde una tubería UNIX desde otro proceso, como lo haría en cualquier otra aplicación UNIX, explica. Así, la cadena arcana de pulsaciones de teclas <esc> :r !ls<enter> introducidas en vi (en modo comando, recuerde) lee en el búfer la salida del programa ls, o una lista de archivos del directorio actual. Y una tubería de cualquier otro programa UNIX también funcionaría.

En cuanto a la edición automática de un gran número de archivos en vi, Lasser dice que es por eso que tenemos sed, awk, y todas las demás herramientas de procesamiento de texto UNIX.

El procesamiento de texto es para lo que UNIX fue diseñado, y vi fue diseñado para ser parte de ese sistema, escribe Lasser.

Tal vez el problema subyacente entre EMACS y vi no es el de la uniformidad frente a la flexibilidad en absoluto. Después de todo, ambos editores ofrecen flexibilidad, es sólo que con vi, lo hace a través del propio UNIX, mientras que EMACS lo logra construyendo sobre el sistema.

Y, para el caso, el único punto de la flexibilidad es hacer que el trabajo vaya más rápido. Si desea un procesamiento de texto sencillo y sin complicaciones, puede optar por Pico, que ofrece sólo una pantalla en blanco y ninguna de las características de vi o EMACS que confunden a los novatos. Lo que ambos editores ofrecen son formas avanzadas de reducir la distancia entre la velocidad de los dedos en el teclado y la velocidad del cerebro del programador.

En otras palabras, ¿podría ser que estos editores ofrezcan lo mismo, pero exijan diferentes maneras de pensar a sus usuarios? Vi requiere la paciencia para aprender sus extravagantes formas, aunque una vez que las dominas, eres libre de llevar tu acto a cualquier sistema UNIX. EMACS te da la libertad de personalizar tu configuración como mejor te parezca, aunque si no eres cuidadoso, te convertirás en prisionero de tu propia configuración.

En algún momento durante la gran caminata de mejora de la auto-eficiencia que todos los buenos programadores toman, los usuarios de vi y EMACS se cruzan, cada uno viniendo de una dirección diferente. Y cuando se encuentran, normalmente se tiran piedras unos a otros.

Pero todo está bien.

No creo que haya una gran diferencia en la funcionalidad. Ambos editores hacen un buen trabajo y todo se reduce a lo que la gente aprende primero, escribe Gil. Ya que la mayoría de las personas conocen EMACS, les enseñarán a otros EMACS. Por lo tanto, la mayoría de la gente usa EMACS, etc.

Y así la disputa continuará...

(Nota: Las mayúsculas de EMACS, UNIX y vi pueden haber sido cambiadas en comillas a sus formas originales, excepto en los títulos directos de libros y páginas Web).

-1:-- The Holy War (Post )--L0--C0--April 08, 2018 03:35 PM