Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
- 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
showMarksOnScrollbara été nomméexperimental.showMarksOnScrollbaretautoMarkPromptsa é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 :
-
OSCest la chaîne"\x1b]": un caractère d’échappement, suivi de] -
STest 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.ExitCodeSiExitCodeest fourni, le terminal traite0comme 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 nous permet également d’inclure le code d’erreur de la commande précédente dans la 133;D séquence, ce qui permet au terminal de coloriser automatiquement la marque en fonction de la réussite ou de l’échec de la commande.
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 source son invite à partir de 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 sourcer le script suivant vers un interpréteur de commandes actif avec source ou . des commandes intégrées bash ou l’ajouter à la fin de votre ${HOME}/.bash_profile (pour les interpréteurs de commandes de connexion) ou ${HOME}/.bashrc (pour les interpréteurs de commandes sans connexion) pour activer une intégration complète de l’interpréteur de commandes avec bash des versions supérieures ou égales à bash-4.4 (où la PS0 variable intégrée a été implémentée initialement).
L’intégration complète de l’interpréteur de commandes signifie que chaque fonctionnalité de terminal annoncée fonctionne comme conçue.
Note
Il convient de souligner que, s’il existe PROMPT_COMMAND, PS1PS0ou PS2 des variables déjà affectées à des valeurs non par défaut susceptibles d’entraîner des résultats imprévisibles. Il serait préférable de tester d’abord le script avec l’interpréteur de commandes « propre » en exécutant env --ignore-environment bash --noprofile --norc et en approvisionnant le fichier décrit comme indiqué précédemment.
# .bash_profile | .bashrc
function __set_ps1() {
local PS1_TMP="${__PS1_BASE}"
if [ ! -z "${__IS_WT}" ]; then
local __FTCS_CMD_FINISHED='\e]133;D;'"${1}"'\e\\'
PS1_TMP="\[${__FTCS_CMD_FINISHED}\]${__PS1_BASE}"
fi
printf '%s' "${PS1_TMP}"
}
function __prompt_command() {
# Must be first in the list otherwise the exit status will be overwritten.
local PS1_EXIT_STATUS=${?}
PS1="$(__set_ps1 ${PS1_EXIT_STATUS})"
}
# ---------------------------------------------------------------------------
# PROMPT (PS0..PS2).
# The given variable might be linked to a function detecting whether `bash`
# actually runs under `Microsoft Terminal` otherwise unexpected garbage might
# be displayed on the user screen.
__IS_WT='true'
printf -v __BASH_V '%d' ${BASH_VERSINFO[*]:0:2}
if [ ${__BASH_V} -ge 44 ]; then
__PS0_BASE=''
fi
# The following assignments reflect the default values.
__PS1_BASE='\s-\v\$ '
__PS2_BASE='> '
if [ ! -z "${__IS_WT}" ]; then
__FTCS_PROMPT='\e]133;A\e\\'
__FTCS_CMD_START='\e]133;B\e\\'
if [ ${__BASH_V} -ge 44 ]; then
__FTCS_CMD_EXECUTED='\e]133;C\e\\'
__PS0_BASE="\[${__FTCS_CMD_EXECUTED}\]"
fi
__PS1_BASE="\[${__FTCS_PROMPT}\]${__PS1_BASE}\[${__FTCS_CMD_START}\]"
# Required, otherwise the `PS2` prefix will split and corrupt a long
# command.
__PS2_BASE=''
fi
PROMPT_COMMAND=__prompt_command
if [ ${__BASH_V} -ge 44 ]; then
PS0="${__PS0_BASE}"
fi
# `PS1` is set with the `__prompt_command` function call.
PS2="${__PS2_BASE}"
Cela encapsule tous les assortiments de variables d’invite bash (PS0PS1etPS2) avec les séquences nécessaires pour activer l’intégration complète de l’interpréteur de commandes.
En outre, ${HOME}/.inputrc il peut également être nécessaire d’ajuster pour supprimer les signes « notification du mode d’édition » et « lignes modifiées » :
# .inputrc
set mark-modified-lines Off
set show-mode-in-prompt Off
C’est ce qu’il doit ressembler si tout est fait correctement :
$ env --ignore-environment bash --noprofile --norc
bash-5.2$ . /tmp/msft-terminal-bash.sh
bash-5.2$ echo "|${PS0}|"
|\[\e]133;C\e\\\]|
bash-5.2$ echo "|${PS1}|"
|\[\e]133;D;0\e\\\]\[\e]133;A\e\\\]\s-\v\$ \[\e]133;B\e\\\]|
bash-5.2$ echo "|${PS2}|"
||
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)