eshell
(Mickey Petersen)
https://masteringemacs.org/article/complete-guide-mastering-eshell

eshell.png

1 Dominar eshell

En emacs hay varios shells, pero ninguno puede igualar la versatilidad y la integración con Emacs como Eshell. Eshell es un intérprete de comandos escrito completamente en Emacs-Lisp y replica la mayoría de las características y comandos de GNU CoreUtils y las shells tipo Bourne. Entonces, al volver a escribir comandos comunes como ls y cp en Emacs-Lisp, Eshell funcionará de manera idéntica en cualquier entorno en el que Emacs se ejecute.

Desafortunadamente hay un problema: Eshell está lamentablemente poco documentada, algo raro en GNU Emacs, así que compilé esta guía para ayudar a las personas a hacer un uso completo de lo que Eshell tiene para ofrecer.

2 Visión de conjunto

A diferencia de los otros shells en Emacs, Eshell no hereda de comint-mode, el modo predeterminado para interactuar con procesos inferiores en Emacs. Pero como Eshell no es un proceso inferior, no tiene que usar comint; pero si bien puede parecer algo bueno, significa que los hooks y las rutinas escritos para el modo comint no funcionarán con Eshell.

Sin embargo, casi todos los comandos de Emacs comunes en Comint-Mode se vuelven a implementar de forma nativa en Eshell y la mayoría comparten los mismos enlaces de teclado, pero hay algunos nuevos que no se han transferido a Eshell, como spiffy comint-history-isearch-backward-regexp en Emacs 23.2, obligado M-r

Eshell funciona bien en cualquier plataforma en la que Emacs se ejecute, ya que Eshell interactúa con un middleware común (es decir, la biblioteca fuente Emacs-Lisp/C) y ese middleware se comunicará con su sistema operativo sobre cómo copiar archivos y qué tiene usted . Ese soporte de middleware permite a Eshell tomar ventaja tambien a TRAMP.

Dado el origen UNIX de Emacs, Eshell emula shells UNIX tradicionales como bash y la cadena de herramientas GNU. Esta es una buena noticia si está usando Windows y no se quiere molestar con Cygwin, o si necesita un Emacs completamente portátil con pocas o ninguna dependencia externa.

Y, de hecho, el soporte de Windows en Eshell es mucho mejor, en muchos sentidos, que el bash de cygwin. No tiene que lidiar con /cygdrive/c, ya que Eshell admite nativamente las rutas de disco de Windows/MS-DOS (entonces cd D: y D: ambos funcionan igual de bien).

A pesar de todas las ventajas que ofrece Eshell, hay algunos puntos que quiero especificar y que parecen confundir a algunas personas:

1- Eshell no es un emulador de terminal. No habla con una shell, ya que es el shell. Todo lo que hace, desde mostrar cosas en la pantalla, hasta buscar el contenido de un directorio, lo hace a través de Emacs y Emacs a su vez habla con su sistema operativo. 2- Debido a la forma en que Eshell habla con otros procesos (especialmente los asíncronos), puede haber problemas con la forma en que almacena el texto y cómo funcionan las interrupciones. 3- Eshell no admite programas interactivos (o "visuales" en el lenguaje Eshell), como top, directamente; debe decirle a Eshell que los lance en una instancia de ansi-term separada. 4- No es bash o zsh o incluso csh; no lo trates como tal, a pesar de que está fuertemente inspirado por ellos. Para usar Eshell de manera efectiva, debe tratarlo como si estuviera utilizando un shell completamente ajeno.

3 Comandos

Eshell es capaz de invocar casi cualquier función elisp cargada en Emacs. Ese tipo de flexibilidad no tiene igual; no hay nada capaz de aproximarse a lo que Eshell puede hacer. De hecho, esta funcionalidad es muy utilizada (¡y alentada!) Por Eshell. Si desea abrir el archivo foobar.txt en Emacs, simplemente invoque el archivo find foobar.txt y Eshell lo correlacionará con la llamada elisp (find-file "foobar.txt") y abrirá el archivo por usted.

4 Detalles técnicos

Todos los comandos evaluados por Eshell tienen una orden de evaluación, que es una lista ordenada por la que debe pasar su comando para determinar qué parte de Eshell lo maneja. Si no hay nada en la lista que quiera evaluar su comando, se le informará que su comando no es válido.

Suponiendo que desea ejecutar el comando cp, el orden de evaluación es:

1- Un archivo completo (por ejemplo */bin/cp*) ejecuta cp in */bin*
2- Busca el prefijo del comando, *eshell-explicit-command-char* (predeterminado es *) si lo encuentra, busca el comando en la ruta de búsqueda.
4- Busca un alias definido por el shell (comando de alias)
4- Busca *cp* en la ruta de búsqueda, *$PATH* (o *eshell-path-env*)
5- Busca una función Lisp llamada *cp* o la función elisp *eshell/cp*

La variable eshell-prefer-lisp-functions hace que las llamadas elisp internas tengan prioridad sobre las llamadas externas. Eso significa que cuando se configura en t Eshell buscará primero una función elisp, en lugar de la última. Si se especifica el prefijo del comando, esta directiva se ignora.

5 Comandos incorporados

Eshell tiene un puñado de comandos escritos en Emacs-Lisp que emulan de forma muy parecida a un gran subconjunto de lo que tiene el GNU Coreutils real (o su shell favorita). Esos comandos se llaman Funciones de alias.

EShell solo implementa un subconjunto de la funcionalidad proporcionada por los comandos reales, pero si le pasa un argumento desconocido a Eshell, diferirá automáticamente de la herramienta de línea de comandos real (si está instalada).

Esto es lo que Eshell actualmente implementa de nuevo en elisp:

cat, cp, ls, cd, export, dirs, du, echo, env, kill, ln, mkdir, mv, alias, popd, pushd, pwd, rm, rmdir, time, umask.

Hay gran voluntad en adherirse a la funcionalidad original de GNU, por lo que es improbable que el hecho de que se emulen le cause ningún problema.

6 Intercepción de comandos

Eshell tiene un mecanismo genial donde ciertos comandos son interceptados y transmitidos a Emacs propiamente dicho. Esto le permite invocar un comando como man ls y hacer que el formateador integrado de Emacs lo maneje. Esta funcionalidad es especialmente importante para los comandos interactivos que no funcionarian correctamente en Eshell ya que Eshell no podría llamarlos.

Pero donde la función realmente brilla es con comandos complejos como grep o diff, ya que Emacs viene con increíbles herramientas grep y diff integradas. Esta característica por sí sola muestra la potencia de Eshell.

Los siguientes comandos se redirigen a Emacs propiamente dicho:

agrep, diff, egrep, fgrep, glimpse, grep, info, jobs, locate, man, occur, su, sudo, whoami

Los comandos su, sudo y whoami son comandos de TRAMP (en Emacs 23.2), por lo que si está conectado a un shell remoto, funcionan como se esperaba.

7 Subshells

Puede usar $() para hacer llamadas elisp en línea y usar sus resultados como argumentos, de la misma manera que lo haría en bash. La única advertencia aquí es que no puede usar la comilla inversa (backtick) para generar una subshell, pero esa sintaxis nunca fue universalmente compatible de todos modos. También es posible (aunque no lo recomendaría, porque hay casos en que no funciona) utilizar un formulario elisp estándar como este: (form …) - por lo que es igual a la sintaxis de subshell que expliqué anteriormente, pero sin el $.

8 Comandos útiles de elisp

Eshell viene con una selección de funciones auxiliares que hacen que su vida cotidiana sea justa **. Eso, combinado con el poder de invocar casi cualquier función elisp, significa que tienes una increíble flexibilidad y control sobre tu shell. Algunos de los comandos que he enumerado en la siguiente tabla se escribieron específicamente para Eshell y el resto son comandos elisp que considero útiles.

He compilado una tabla de funciones elisp (algunas están hechas para Eshell, otras no).

listify ARGS

Analiza una cadena de argumentos en notación de lista elisp y la imprime en la pantalla. Es lo suficientemente inteligente como para manejar la sintaxis del argumento estilo MS-DOS/Windows y POSIX.

addpath PATH

Agrega el argumento, que debe ser una ruta, a la variable de entorno $PATH. Si no se especifica ningún argumento, las rutas existentes están impresas en la pantalla.

  • unset ENV-VAR

Desactiva una variable de entorno existente

  • find-file FILE

Encuentra el archivo FILE y lo abre en Emacs. Esta función es compatible con TRAMP y, por lo tanto, funcionará de forma remota.

  • dired DIRECTORY

Abre un búfer directo en DIRECTORY.

  • calc-eval EXPR

Ejecuta EXPR a través de la calculadora Emacs.

  • upcase STR/downcase STR

Convierte STR a mayúsculas o minúsculas.

  • vc-dir DIRECTORY

Informa el estado de un directorio controlado por la versión (equivalente al comando de estado en la mayoría de los VCS)

  • ediff-files FILE1 FILE2

Diferencias entre FILE1 y FILE2 usando ediff, el motor de diferencias de Emacs.

Si usted es un usuario de Eshell y utiliza comandos de elisp que no figuran en la tabla anterior, publique un comentario y dígame qué es.

9 Aliasing

Aliasing en Eshell funciona de la misma manera que en otras shells mainstream, excepto que se puede mezclar libremente comandos elisp y Eshell. El alias de comando toma un alias-nombre y una definición. La definición debe estar rodeada por comillas simples. Puede usar las referencias habituales de argumentos conocidas de otros shells: $1 para el primer argumento, $2 para el segundo, …, o $ para usar todos los argumentos, u omitirlos por completo ya que Eshell los agregará mágicamente al final de un comando si no fueron referenciados en la definición.

Para eliminar un alias, simplemente omita el argumento de definición y se eliminará automáticamente. Para enumerar todos los alias, omita ambos argumentos.

Eshell escribirá las definiciones de alias en el eshell-aliases-file, que a su vez se rige por el Eshell-directory-name y el conjunto significa que su archivo de alias se colocará en ~/.Eshell/alias de forma predeterminada. Esto se hace cada vez que se modifica un alias.

Otra cosa útil que debe saberse es el aliasing de autocorrección. Si se escribe un comando no válido más de 3 veces, que es la cantidad maxima de fallos establecida por defecto (eshell-bad-command-tolerance), Eshell ofrecerá un alias para el dicho comando. Si 3 veces se considera poco, puede subirse la variable mencionada a un número más grande.

10 Ejemplos útiles

Vamos a mapear el incómodo comando find-file a ff más manejable:

alias ff 'find-file $1'

Y vamos a hacer un mapeo de dired a d:

alias d 'dired $1'

11 Comandos visuales

Algunos comandos son demasiado complejos para ser visualizados directamente por Eshell y requieren un manejo especial. Un ejemplo sería top, un programa que no funcionará con una terminal tonta. Para admitir estos comandos, Eshell ejecutará una sesión de terminal cuando invoque un comando que Eshell considera visual.

Para modificar la lista de comandos visuales, puede alterar los comandos de eshell-visual-commands.

12 Historial de Comando

Eshell viene con una función de historial de comandos rica en funciones. Como Eshell no usa comint-mode, no tiene todas las funciones de historial disponibles, pero la mayoría de ellas se pueden implementar.

  • M-r / M-s

Buscar hacia atrás o hacia adelante para un comando por regexp

  • M-p / M-n

Retrocede o avanza en la lista de historial de comandos

  • C-p / C-n

Salta a la posición de comando anterior o siguiente en Eshell

  • C-c M-r / C-c M-s

Salta al comando anterior o siguiente que comparte el comando utilizado actualmente como entrada. Entonces salta a otras instancias del comando foo si esa es la entrada actual.

Desafortunadamente, el nuevo y mejorado comint-history-isearch-backward-regexp (vinculado a M-r en comint-mode) no funciona en Eshell porque no hereda de comint (y por lo tanto se pierde en las actualizaciones).

13 Interacción con "history"

Al igual que bash y otras shells, Eshell tiene soporte para modificar e interaccionar con history. Probablemente sea más fácil remitir al manual de información de bash para obtener información detallada sobre cómo funciona la interacción con history. He incluido una pequeña tabla a continuación que describe la mayor parte de la sintaxis histórica compatible con Eshell.

  • !!

Repite el último comando

  • ! ls

epite el último comando que empieza con ls

  • !? ls

Repite el último comando que contiene ls

  • ! ls: n

Extraer el enésimo argumento del último comando que comience con ls

  • ! ls <tab>

Usando pcomplete, muestre los resultados de finalización coincidente con ls

  • ^old^new

Sustitución rápida. Usando el último comando, reemplaza el viejo por el nuevo y lo ejecuta nuevamente. Parece tener errores.

  • $

Devuelve el último parámetro del último comando ejecutado.

Eshell también tiene algún soporte para los modificadores del history de bash (como !!:s/old/new/) y la referencia bash en la interacción del historial sería un buen lugar para repasar eso.

14 El prompt de Eshell

Puede personalizarse el prompt de Eshell modificando eshell-prompt-function, una variable que toma una función que define lo que debería contener el prompt. Al relegar la configuración rápida a elisp, puede hacer casi cualquier cosa que quiera con ella. El único problema es, por supuesto, que Eshell necesitará que le digan qué aspecto tiene el prompt, por lo que también se debe editar la variable eshell-prompt-regexp para que Eshell sepa cuál es el prompt.

15 La linea de comando (commandline)

Eshell admite la barra (\) para escapar de nuevas líneas y admite la entrada rudimentaria de varias líneas de esa manera. Otra forma de hacer cadenas literales multilínea es con comillas simples: comience una comilla simple y presione enter, y podrá ingresar texto hasta que se encuentre el delimitador de comillas de cierre. Si usa comillas dobles, Eshell expandirá los comandos de subshell y expandirá las variables.

Debido a la forma en que Eshell funciona, incluso puede retroceder y modificar el texto que ingresó, entre comillas. Esto es muy útil ya que puedes regresar y cambiar cosas que no gustan y hacerlo mejor que la primera vez.

16 Keybindings

Eshell viene equipada con un par de mejoras que hacen que interactuar con Emacs y Eshell sea mucho más fácil.

  • C-c M-b

Inserta el nombre del buffer en el punto del cursor

  • C-c M-i

Inserta el nombre del proceso en el punto del cursor

  • C-c M-v

Inserta un nombre de variable de entorno en el punto del cursor

  • C-c M-d

Alterna entre la entrada directa y la entrada retrasada (enviar en RET).

Útil para algunos programas que no funcionan correctamente con la entrada almacenada en el búfer.

17 Predicados de argumento

Los predicados de argumento son una excelente manera de filtrar rápidamente listas de archivos o incluso listas elisp. La sintaxis del predicado se basa en la que se usa en zsh, por lo que si está familiarizado con la predicación del argumento en zsh, puede aplicar la mayoría de sus conocimientos a la versión de Eshell.

A diferencia de la mayoría de las demás áreas de Eshell, los argumentos predicados están documentados en Eshell. Puede acceder a los archivos de ayuda escribiendo eshell-display-predicate-help o eshell-display-modifier-help.

Filtrar listas globbed de archivos es muy útil, ya que le ahorra la molestia de utilizar herramientas como find o abusar de ls para hacer lo suyo.

El archivo de ayuda es bastante espartano y solo sirve como una referencia simple, así que he incluido una pequeña guía aquí; pero en realidad, la única manera real de aprender algo tan flexible como la predicación de argumentos es simplemente por ensayo y error.

18 Referencia de sintaxis

He optado por no reimprimir la considerable lista de predicados y modificadores, ya que el manual de Eshell (véanse los comandos anteriores) hace un buen trabajo al explicar cómo funcionan.

19 Globbing

El englobamiento en Eshell sigue las mismas reglas que en la mayoría de las otras shells comunes: es la shell la que hace la expansión de los globs y pasa la lista expandida de coincidencias a comandos como ls. Es por eso que cuando se usa find y xargs juntos, es fundamental que pase -print0 a find y -0 a xargs. Si no lo hace, los nombres de archivos con caracteres oscuros o espacios en ellos pueden tropezar con xargs; al utilizar el carácter NUL como separador, se garantiza que la tokenización se realiza correctamente ya que el carácter NUL es un carácter no válido (junto con /) en los archivos.

20 Listas de Elisp

Las "listas" de Eshell son en realidad listas elisp tanto en su forma impresa como interna. Eso hace la vida mucho más simple si lo piensas, ya que Eshell puede quitar el manejo de la lista para elisp, que es algo que Lisp hace bien.

El ejemplo más simple de glob es echo *, que muestra una lista de todas las coincidencias de comodines en el directorio actual. Porque, como acabo de mencionar, la expansión del comodín se lleva a cabo en línea y puedo aplicar inmediatamente un modificador al * comodín de arriba.

Vamos a mayúsculas el conjunto de resultados globbed:

$ echo *(:U)
("BAR" "BIN/" "DEV/" "ETC/" "FOO" "HOME/" "LIB/" "TMP/" "USR/" "VAR/")

Observe cómo usé () inmediatamente después del patrón de glob. Los parentesis son los que hacen posible los modificadores o predicados de argumento. Los modificadores son cosas que modifican (¡gran sorpresa!) La lista resultante. Los comandos de modificación siempre comienzan con : y los predicados no.

Otro ejemplo, pero esta vez filtro directorios usando un predicado:

$ echo *(^/)
("bar" "foo")

El circunflejo, ^, en este caso, como en expresiones regulares, es negación. El / significa "directorios" solamente.

Pero no tengo que usar globs para aplicar modificadores o predicados a las listas:

$ echo ("foo" "bar" "baz" "foo")(:gs/foo/blarg/)
("blarg" "bar" "baz" "blarg")

Esta vez reemplacé todas las apariciones de foo con blarg. Observe que la sintaxis es idéntica, excepto que en lugar de usar globs para obtener una lista de archivos, utilicé una lista de mi elección.

Las ventajas proporcionadas por los predicados y modificadores de argumento reducirán en gran medida el desorden de la línea de comandos ya que los predicados cubren los permisos, la propiedad, los atributos del archivo y mucho más.

21 Agregar nuevos modificadores y predicados

Incluso puede agregar sus propios predicados (eshell-predicate-alist) o modificadores (eshell-modifier-alist):

(add-to-list 'eshell-modifier-alist '(?X . '(lambda (lst) (mapcar 'rot13 lst))))

Aquí he vinculado X rot13, el cifrado de sustitución:

$ echo ("foo" "bar" "baz")(:X)
("sbb" "one" "onm")

22 Plan 9 Smart Shell

Eshell viene con un facsímil simplificado de Plan 9 de terminal, llamado pantalla inteligente Eshell. La pantalla inteligente está destinada a mejorar el ciclo de escritura-ejecución-revisión que atraviesan todos los piratas informáticos. Funciona al no permitir que el punto siga la salida de un comando que ejecute, como lo haría un terminal normal. En cambio, el punto se mantiene en la línea del comando que ejecutó, lo que le permite revisarlo fácilmente sin tener que usar M-p y M-n o los comandos de modificación del history.

Si la pantalla inteligente está habilitada, también le permitirá revisar la salida de los comandos de ejecución prolongada mediante el uso de SPC para desplazarse hacia abajo en una página y RET para avanzar una página. Si se presiona cualquier otra tecla, saltará al final del búfer, actuando de la misma manera que si la pantalla inteligente no estuviera habilitada.

Básicamente, si Eshell detecta que se desea revisar el último comando ejecutado, le ayudará a hacerlo; si, por el contrario, no lo hace, Eshell saltará al final del búfer. Es muy inteligente al respecto y hay interruptores que puedes alternar para ajustar el comportamiento.

Donde realmente brilla la pantalla inteligente es que le permite modificar el comando que acaba de ejecutar utilizando las teclas de movimiento, como lo haría normalmente, para cambiar el comando, digamos para corregir un error tipográfico o modificar un argumento.

La pantalla inteligente también se puede configurar para no usar este "modo de edición" extendido si el comando regresa con éxito, y sin mostrar la salida, como chown, por ejemplo. Así es como lo prefiero.

Para habilitarlo, coloque esto en su archivo .emacs:

(require 'eshell)
(require 'em-smart)
(setq eshell-where-to-jump 'begin)
(setq eshell-review-quick-commands nil)
(setq eshell-smart-space-goes-to-end t)

Si Eshell ya se ha inicializado (es decir, ya ha lanzado una instancia de Eshell en Emacs), entonces la evaluación de los cambios anteriores no funcionará. Debe cambiar al búfer de Eshell y escribir M-: (shell-smart-initialize) o reiniciar Emacs.

La pantalla inteligente es una característica muy útil y no se pondrá en su camino una vez que esté acostumbrado. Simplemente escribiendo nuevos comandos hará que Eshell salte al final del búfer como si el cursor ya estuviera allí. Redirección

La redirección en Eshell funciona de la misma manera que en otros shells. La diferencia clave es que Eshell tiene que emular los pseudodispositivos, ya que pueden no estar presentes (o pueden no estar presentes de la misma forma) en plataformas como Windows donde /dev/null es realmente NUL.

Otra advertencia es que Eshell no admite la redirección de entrada, aunque admite la redirección de salida. Para evitar la falta de redirección de entrada, debe usar tuberías en su lugar.

El redireccionamiento a stdout, stdin y stderr funciona como era de esperar, y puede enviar cosas a múltiples destinos también, lo cual es muy bueno.

23 Para Emacs

Debido a que Eshell tiene que volver a implementar pseudodispositivos internamente, no está a merced de tratar solo con archivos de dispositivo UNIX; de hecho, es capaz de implementar sus propios pseudodispositivos.

Un buen ejemplo sería la redirección a un búfer de su elección, y eso se puede hacer con la siguiente sintaxis:

$ cat mylog.log >> #<buffer *scratch*>

La combinación de teclas que mencioné antes C-c M-b insertará el nombre de un buffer.

También puede enviar directamente a un símbolo elisp (pero tenga cuidado de no freir las configuraciones incorrectas):

$ echo foo bar baz > #'myvar
$ echo $(cadr myvar)
bar

Si establece eshell-buffer-shorthand en t, puede usar la abreviatura #'scratch en su lugar, pero significa que no podrá redirigir directamente a los símbolos elisp.

24 Para pseudo-dispositivos

Eshell vuelve a implementar los siguientes pseudodispositivos:

  • /dev/eshell

Imprime la salida interactivamente a Eshell.

  • /dev/null

Envía la salida al dispositivo NULL.

  • /dev/clip

Envía la salida al portapapeles.

  • /dev/kill

Envía la salida al anillo de matar.

Aquí se aplican las reglas de redirección habituales, como sobrescribir (>) y añadir (>>).

25 Para objetivos virtuales personalizados

Puede diseñar sus propios objetivos virtuales modificando eshell-virtual-targets, una lista que toma el nombre del pseudodispositivo que desea crear y una función que toma un parámetro, modo, que determina si se sobrescribe, agrega o inserta .

26 TRAMP

Eshell ahora es compatible con TRAMP de forma nativa, lo que significa que comandos como su, sudo y whoami ahora consultan el sistema remoto si el directorio en el que se encuentra Eshell es remoto.

Para usar la funcionalidad TRAMP simplemente ingrese la misma cadena de comando TRAMP que usaría en C-x C-f y listo. El soporte de TRAMP en Eshell puede ser un poco escaso, pero te da una shell remota cortesía de TRAMP. No tiene que limitar su uso de TRAMP a shells remotos, ya que TRAMP también es capaz de usar sudo y su para uso local.

Cubriré a TRAMP con más detalle en un artículo aparte, pero el manual oficial es un buen lugar para comenzar.

27 Scripts de inicio

Al igual que la mayoría de las shells, Eshell admite los scripts de inicio de sesión y profile/rc. Los caminos de archivo completos para ambos se almacenan en las variables eshell-login-script y eshell-rc-script, pero de forma predeterminada los archivos de inicio de sesión y el perfil se almacenan en ~/.eshell/.

Cabe mencionar que la sintaxis de comentario es #.

28 Más personalización …

Eshell tiene cientos de opciones que puede ajustar a su gusto. Para configurar Eshell, escriba M-x customize-group RET eshell RET.

29 Conclusión

Uf. Creo que he cubierto todas las áreas principales de Eshell y espero que lo describa con una buena perspectiva. Eshell es notablemente versátil gracias a su estrecha integración con Emacs. No es un reemplazo completo para bash y su emulador de terminal favorito, pero hará la mayor parte de las cosas de línea de comandos que inevitablemente terminaremos haciendo. Si usa muchos programas interactivos, es probable que Eshell no sea muy útil, ya que debe generar una instancia separada para cada programa visual que ejecute.

Eshell tiene soporte TRAMP, pseudodispositivos personalizados, un REPL elisp de bolsillo y muchos comandos de utilidad útiles como poder buscar archivos o direccionar cualquier directorio o archivo en el que se encuentre, y eso lo convierte en una herramienta confiable en mi caja de herramientas. .

Fecha: 2018