Intégration de l’interpréteur de commandes
- Intégration de l’interpréteur de commandes
À compter de la préversion du Terminal 1.15, le Terminal Windows a commencé à prendre en charge expérimentalement certaines fonctionnalités d’« intégration de l’interpréteur de commandes ». Ces fonctionnalités facilitent l’utilisation de la ligne de commande. Dans les versions antérieures, nous avons activé l’interpréteur de commandes pour indiquer au Terminal le répertoire de travail actuel. Nous avons désormais ajouté la prise en charge d’autres séquences pour permettre à l’interpréteur de commandes de décrire sémantiquement des parties de la sortie du terminal sous la forme d’« invite », de « commande » ou de « sortie ». L’interpréteur de commandes peut également indiquer au terminal si une commande a réussi ou échoué.
Il s’agit d’un guide de certaines fonctionnalités d’intégration de l’interpréteur de commandes déployées à partir du Terminal v1.18. Nous prévoyons de créer des fonctionnalités supplémentaires à l’avenir. Nous aimerions donc obtenir des commentaires supplémentaires sur la façon dont les utilisateurs les utilisent.
Remarque: à partir de Terminal 1.21, les marques sont désormais une fonctionnalité stable. Avant la version 1.21, les marques étaient uniquement activées pour les builds en préversion du terminal. Si vous utilisez une version de Terminal antérieure à la version 1.21, le paramètre
showMarksOnScrollbar
a été nomméexperimental.showMarksOnScrollbar
etautoMarkPrompts
a été nomméexperimental.autoMarkPrompts
.
Comment cela fonctionne ?
L’intégration de l’interpréteur de commandes fonctionne ainsi : l’interpréteur de commandes (ou à toute application en ligne de commande) écrit des « séquences d’échappement » spéciales dans le terminal. Ces séquences d’échappement ne sont pas imprimées dans le terminal. Elles fournissent à la place des métadonnées que le terminal peut utiliser pour en savoir plus sur ce qui se passe dans l’application. En collant ces séquences dans l’invite de votre interpréteur de commandes, vous pouvez demander à l’interpréteur de commandes de fournir en continu des informations au terminal que seul l’interpréteur de commandes connaît.
Pour les séquences suivantes :
OSC
est la chaîne"\x1b]"
: un caractère d’échappement, suivi de]
ST
est le « terminateur de chaîne ». Il peut être\x1b\
(un caractère d’échappement, suivi de\
) ou\x7
(le caractère d’appel)- Les espaces sont simplement illustratifs.
- Les chaînes dans
<>
sont des paramètres qui doivent être remplacés par une autre valeur.
Voici les séquences pertinentes d’intégration d’interpréteur de commandes prises en charge à partir de Terminal v1.18 :
OSC 133 ; A ST
("FTCS_PROMPT") : début d’une invite.OSC 133 ; B ST
("FTCS_COMMAND_START") : début d’une ligne de commande (READ : fin de l’invite).OSC 133 ; C ST
("FTCS_COMMAND_EXECUTED") : début de la sortie de la commande/fin de la ligne de commande.OSC 133 ; D ; <ExitCode> ST
("FTCS_COMMAND_FINISHED") : fin d’une commande.ExitCode
SiExitCode
est fourni, le terminal traite0
comme une « réussite » et tout autre résultat comme une erreur. En cas d’omission, le terminal laisse simplement la marque avec la couleur par défaut.
Guide pratique pour activer les marques d’intégration de l’interpréteur de commandes
La prise en charge de ces fonctionnalités nécessite une coopération entre votre interpréteur de commandes et le terminal. Vous devez à la fois activer les paramètres dans le terminal pour utiliser ces nouvelles fonctionnalités et modifier l’invite de votre interpréteur de commandes.
Pour activer ces fonctionnalités dans le terminal, vous devez ajouter les éléments suivants à vos paramètres :
"profiles":
{
"defaults":
{
// Enable marks on the scrollbar
"showMarksOnScrollbar": true,
// Needed for both pwsh, CMD and bash shell integration
"autoMarkPrompts": true,
// Add support for a right-click context menu
// You can also just bind the `showContextMenu` action
"experimental.rightClickContextMenu": true,
},
}
"actions":
[
// Scroll between prompts
{ "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)
{ "command": { "action": "selectOutput", "direction": "prev" }, },
{ "command": { "action": "selectOutput", "direction": "next" }, },
{ "command": { "action": "selectCommand", "direction": "prev" }, },
{ "command": { "action": "selectCommand", "direction": "next" }, },
]
La procédure pour activer ces marques dans votre interpréteur de commandes varie d’un interpréteur de commandes à l’autre. Vous trouverez ci-dessous des didacticiels pour CMD, PowerShell et Zsh.
PowerShell (pwsh.exe
)
Si vous n’avez jamais changé votre invite PowerShell auparavant, vous devez d’abord consulter about_Prompts.
Nous devons modifier votre prompt
pour nous assurer que nous informons le Terminal du CWD et appliquons les marques appropriées à l’invite. PowerShell permet également d’inclure le code d’erreur de la commande précédente dans la séquence 133;D
, ce qui permet au terminal de coloriser automatiquement la marque selon une commande ayant réussi ou échoué.
Ajoutez ce qui suit à votre profil 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
}
Oh My Posh setup
En utilisant oh-my-posh ? Vous souhaiterez légèrement modifier l’invite d’origine, puis l’ajouter au milieu des séquences d’échappement d’intégration de l’interpréteur de commandes.
# initialize oh-my-posh at the top of your profile.ps1
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\gruvbox.omp.json" | Invoke-Expression
# then stash away the prompt() that oh-my-posh sets
$Global:__OriginalPrompt = $function:Prompt
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 {
$gle = $(__Terminal-Get-LastExitCode);
$LastHistoryEntry = $(Get-History -Count 1)
if ($Global:__LastHistoryId -ne -1) {
if ($LastHistoryEntry.Id -eq $Global:__LastHistoryId) {
$out += "`e]133;D`a"
} else {
$out += "`e]133;D;$gle`a"
}
}
$loc = $($executionContext.SessionState.Path.CurrentLocation);
$out += "`e]133;A$([char]07)";
$out += "`e]9;9;`"$loc`"$([char]07)";
$out += $Global:__OriginalPrompt.Invoke(); # <-- This line adds the original prompt back
$out += "`e]133;B$([char]07)";
$Global:__LastHistoryId = $LastHistoryEntry.Id
return $out
}
Invite de commandes
L’invite de commandes trouve l’invite dans la variable d’environnement PROMPT
. CMD.exe lit $e
en tant que caractère ESC
. Malheureusement, CMD.exe n’est pas en mesure d’obtenir le code de retour de la commande précédente dans l’invite. Nous ne pouvons donc pas fournir d’informations indiquant une réussite/erreur dans les invites CMD.
Pour modifier l’invite pour l’instance CMD.exe actuelle, exécutez :
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
Vous pouvez également définir la variable à partir de la ligne de commande pour toutes les sessions futures :
setx PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
Ces exemples supposent que votre PROMPT
actuel est simplement $P$G
. À la place, vous pouvez choisir d’inclure votre invite actuelle dans un wrapper de cette manière :
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\%PROMPT%$e]133;B$e\
Bash
Vous pouvez ajouter les éléments suivants à la fin de votre ~/.bashrc
pour activer l’intégration de l’interpréteur de commandes dans bash :
PS1="\[\033]133;D;\007\]\[\033]133;A;\007\]$PS1\[\033]133;B;\007\]"
Cela encapsule votre $PS1
existante avec les séquences nécessaires pour activer l’intégration de l’interpréteur de commandes.
Remarque : vous ne voyez pas votre interpréteur de commandes favori ici ? Dans ce cas, n’hésitez pas à contribuer à l’ajout d’une solution d’une solution pour l’interpréteur de commandes de votre choix !
Fonctionnalités d'intégration de l’interpréteur de commandes
Ouvrir de nouveaux onglets dans le même répertoire de travail
Afficher les marques pour chaque commande dans la barre de défilement
Saut automatique entre les commandes
Cela utilise les actions scrollToMark
comme nous les avons définies ci-dessus.
Sélectionner la sortie entière d’une commande
Dans ce gif, nous utilisons l’action selectOutput
liée à ctrl+g
pour sélectionner l’intégralité de la sortie d’une commande.
Les éléments suivants utilisent le paramètre experimental.rightClickContextMenu
pour activer un menu contextuel en cliquant avec le bouton droit dans le Terminal. Lorsque l’intégration de l’interpréteur de commandes est activée, vous pouvez cliquer avec le bouton droit sur une commande pour sélectionner la commande entière ou sa sortie.
Suggestions de commande récentes
Une fois l’intégration de l’interpréteur de commandes activée, l’interface utilisateur Suggestions peut être configurée pour afficher vos commandes récentes.
Vous pouvez ouvrir ce menu avec l’action suivante :
{
"command": { "action": "showSuggestions", "source": "recentCommands", "useCommandline": true },
},
(Pour plus d’informations, consultez la documentation Suggestions)