Tutorial: Habilitación de la integración del shell en Terminal Windows

A partir de Terminal 1.15 Preview, Terminal Windows ha empezado a admitir experimentalmente algunas características de "integración del shell". Estas características facilitan el uso de la línea de comandos. En versiones anteriores, se habilitó el shell para indicar al Terminal el directorio de trabajo actual. Ahora, hemos agregado compatibilidad con más secuencias para permitir que el shell describa semánticamente partes de la salida del terminal como un "símbolo del sistema", un "comando" o una "salida". El shell también puede indicar al terminal si un comando se ejecutó correctamente o no.

Esta es una guía de algunas de las características de integración del shell que hemos implementado a partir de Terminal v1.18. Estamos planeando crear incluso más características sobre estas en el futuro, por lo que nos encantaría recibir algunos comentarios adicionales sobre cómo los usuarios las usan.

Nota: En particular, las "marcas" siguen siendo experimentales y solo están habilitadas para las compilaciones en versión preliminar del Terminal. La configuración de estas características puede cambiar en una versión futura.

¿Cómo funciona?

La integración de shell funciona haciendo que el shell (o cualquier aplicación de línea de comandos) escriba "secuencias de escape" especiales en el Terminal. Estas secuencias de escape no se imprimen en el Terminal, sino que proporcionan bits de metadatos que el terminal puede usar para tener más información sobre lo que sucede en la aplicación. Al colocar estas secuencias en el símbolo del sistema del shell, puede hacer que el shell proporcione continuamente información al terminal que solo conoce el shell.

En las secuencias siguientes:

  • OSC es la cadena "\x1b]", un carácter de escape, seguido de ].
  • ST es el "terminador de cadena" y puede ser \x1b\ (un carácter ESC, seguido de \) o \x7 (el carácter BEL).
  • Los espacios son meramente ilustrativos.
  • Las cadenas de <> son parámetros que deben reemplazarse por algún otro valor.

Las secuencias de integración del shell admitidas más importantes a partir de Terminal v1.18 son:

  • OSC 133 ; A ST ("FTCS_PROMPT"): el inicio de un símbolo del sistema.
  • OSC 133 ; B ST ("FTCS_COMMAND_START"): el inicio de una línea de comandos (READ: el final del símbolo del sistema).
  • OSC 133 ; C ST ("FTCS_COMMAND_EXECUTED"): el inicio de la salida del comando o el final de la línea de comandos.
  • OSC 133 ; D ; <ExitCode> ST ("FTCS_COMMAND_FINISHED"): el final de un comando. ExitCode Si se proporciona ExitCode, el Terminal tratará 0 como "correcto" y cualquier otra cosa como error. Si se omite, el terminal simplemente dejará la marca del color predeterminado.

Habilitación de marcas de integración del shell

La compatibilidad con estas características requiere la cooperación entre el shell y el Terminal. Para usar estas nuevas características, tendrá que habilitar la configuración en el Terminal y modificar el símbolo del sistema del shell.

Para habilitar estas características en el Terminal, puede agregar los siguientes valores a la configuración:

"profiles":
{
    "defaults":
    {
        // Marks in general
        "experimental.showMarksOnScrollbar": true,

        // Needed for both pwsh and CMD shell integration
        "experimental.autoMarkPrompts": true,

        // Add support for a right-click context menu
        // You can also just bind the `showContextMenu` action
        "experimental.rightClickContextMenu": true,
    },
}
"actions":
[
    { "keys": "ctrl+up",   "command": { "action": "scrollToMark", "direction": "previous" }, },
    { "keys": "ctrl+down", "command": { "action": "scrollToMark", "direction": "next" }, },

    // Add the ability to select a whole command (or its output)
    { "keys": "ctrl+shift+w", "command": { "action": "selectOutput", "direction": "prev" }, },
    { "keys": "ctrl+shift+s", "command": { "action": "selectOutput", "direction": "next" }, },

    { "keys": "ctrl+alt+shift+w", "command": { "action": "selectCommand", "direction": "prev" }, },
    { "keys": "ctrl+alt+shift+s", "command": { "action": "selectCommand", "direction": "next" }, },
]

La forma de habilitar estas marcas en el shell varía de un shell a otro. A continuación, se muestran tutoriales para CMD y PowerShell.

PowerShell (pwsh.exe)

Si nunca ha cambiado el símbolo del sistema de PowerShell, primero debe consultar about_Prompts.

Tendremos que editar prompt para asegurarnos de que le indicamos al Terminal el CWD y marcaremos el símbolo del sistema con las marcas adecuadas. PowerShell también nos permite incluir el código de error del comando anterior en la secuencia 133;D, lo que permitirá al terminal colorear automáticamente la marca en función de si el comando se ha ejecutado correctamente o no.

Agregue lo siguiente al perfil de PowerShell:

$Global:__LastHistoryId = -1

function Global:__Terminal-Get-LastExitCode {
  if ($? -eq $True) {
    return 0
  }
  $LastHistoryEntry = $(Get-History -Count 1)
  $IsPowerShellError = $Error[0].InvocationInfo.HistoryId -eq $LastHistoryEntry.Id
  if ($IsPowerShellError) {
    return -1
  }
  return $LastExitCode
}

function prompt {

  # First, emit a mark for the _end_ of the previous command.

  $gle = $(__Terminal-Get-LastExitCode);
  $LastHistoryEntry = $(Get-History -Count 1)
  # Skip finishing the command if the first command has not yet started
  if ($Global:__LastHistoryId -ne -1) {
    if ($LastHistoryEntry.Id -eq $Global:__LastHistoryId) {
      # Don't provide a command line or exit code if there was no history entry (eg. ctrl+c, enter on no command)
      $out += "`e]133;D`a"
    } else {
      $out += "`e]133;D;$gle`a"
    }
  }


  $loc = $($executionContext.SessionState.Path.CurrentLocation);

  # Prompt started
  $out += "`e]133;A$([char]07)";

  # CWD
  $out += "`e]9;9;`"$loc`"$([char]07)";

  # (your prompt here)
  $out += "PWSH $loc$('>' * ($nestedPromptLevel + 1)) ";

  # Prompt ended, Command started
  $out += "`e]133;B$([char]07)";

  $Global:__LastHistoryId = $LastHistoryEntry.Id

  return $out
}

Símbolo del sistema

Orígenes del símbolo del sistema que se solicitan desde la variable de entorno PROMPT. CMD.exe lee $e como si fuera el carácter ESC. Por desgracia, CMD.exe no tiene una manera de obtener el código de retorno del comando anterior en el símbolo del sistema, por lo que no podemos proporcionar información de éxito o error en los mensajes de CMD.

Puede cambiar el símbolo del sistema de la instancia de CMD.exe actual mediante la ejecución de:

PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\

O bien, puede establecer la variable desde la línea de comandos para todas las sesiones futuras:

setx PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\

En estos ejemplos se supone que el valor actual de PROMPT es simplemente $P$G. En su lugar, puede optar por encapsular el símbolo del sistema actual con algo parecido a esto:

PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\%PROMPT%$e]133;B$e\

Nota: ¿No ve su shell favorito aquí? Si consigue descubrir el problema, no dude en aportar una solución para su shell favorito.

Demostraciones de integración del shell

Abrir nuevas pestañas en el mismo directorio de trabajo

Open new tabs in the same working directory

Mostrar marcas para cada comando de la barra de desplazamiento

Show marks for each command in the scrollbar

Saltar automáticamente entre comandos

Automatically jump between commands

Seleccionar la salida completa de un comando

Select the entire output of a command

Select the command using the right-click context menu