Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
- Integração do shell
A partir da versão prévia do Terminal 1.15, o Terminal do Windows começou a dar suporte experimental a alguns recursos de "integração do shell". Esses recursos facilitam o uso da linha de comando. Em versões anteriores, habilitamos o shell para informar ao Terminal qual é o diretório de trabalho atual. Agora, adicionamos suporte para mais sequências para permitir que o shell descreva semanticamente partes da saída do terminal como um "prompt", um "comando" ou "saída". O shell também pode informar ao terminal se um comando foi bem-sucedido ou falhou.
Este é um guia para alguns dos recursos de integração do shell que implantamos a partir do Terminal v1.18. Estamos planejando criar ainda mais recursos no futuro, então adoraríamos receber alguns comentários adicionais sobre como as pessoas usam esses recursos.
Observação: a partir do Terminal 1.21, as marcas agora são um recurso estável. Antes da 1.21, as marcas só eram habilitadas para builds de Versão prévia do Terminal. Se você estiver usando uma versão do Terminal anterior à 1.21, a configuração
showMarksOnScrollbarfoi nomeadaexperimental.showMarksOnScrollbareautoMarkPromptsfoi nomeadaexperimental.autoMarkPrompts.
Como isso funciona?
A integração do shell funciona fazendo com que o shell (ou qualquer aplicativo de linha de comando) escreva "sequências de escape" especiais no Terminal. Essas sequências de escape não são impressas no Terminal. Em vez disso, elas fornecem bits de metadados que o terminal pode usar para saber mais sobre o que está acontecendo no aplicativo. Ao colocar essas sequências no prompt do shell, você pode fazer com que o shell forneça continuamente informações ao terminal que somente o shell conhece.
Para as seguintes sequências:
-
OSCé a cadeia de caracteres"\x1b]"– um caractere de escape, seguido por] -
STé o "terminador de cadeia de caracteres" e pode ser\x1b\(um caractere ESC, seguido por\) ou\x7(o caractere BEL) - Espaços são meramente ilustrativos.
- Cadeias de caracteres em
<>são parâmetros que devem ser substituídos por algum outro valor.
As sequências de integração de shell com suporte relevantes a partir do Terminal v1.18 são:
-
OSC 133 ; A ST("FTCS_PROMPT") – o início de um prompt. -
OSC 133 ; B ST("FTCS_COMMAND_START") – o início de uma linha de comando (LEIA: o final do prompt). -
OSC 133 ; C ST("FTCS_COMMAND_EXECUTED") – o início da saída do comando/o final da linha de comando. -
OSC 133 ; D ; <ExitCode> ST("FTCS_COMMAND_FINISHED") – o fim de um comando.ExitCodeSeExitCodefor fornecido, o Terminal tratará0como "êxito" e qualquer outra coisa como um erro. Se omitido, o terminal deixará apenas a marca da cor padrão.
Como habilitar marcas de integração do shell
O suporte a esses recursos requer cooperação entre o shell e o Terminal. Você precisará habilitar as configurações no Terminal para usar esses novos recursos, bem como modificar o prompt do shell.
Para habilitar esses recursos no Terminal, você precisará adicionar o seguinte às suas configurações:
"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" }, },
]
A forma como você habilita essas marcas no shell varia de shell para shell. Abaixo estão os tutoriais para CMD, PowerShell e Zsh.
PowerShell (pwsh.exe)
Se você nunca alterou o prompt do PowerShell antes, confira primeiro about_Prompts.
Precisaremos editá-lo prompt para garantir que comuniquemos o Terminal sobre o CWD e marquemos o prompt com as marcas apropriadas. O PowerShell também nos permite incluir o código de erro do comando anterior na sequência 133;D, permitindo que o terminal destaque automaticamente a marca com base em se o comando foi bem-sucedido ou falhou.
Adicione o seguinte ao seu perfil do 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
}
Configuração do Oh My Posh
Usando oh-my-posh? Você vai querer modificar um pouco o acima, para esconder o prompt original e, em seguida, adicioná-lo de volta no meio das sequências de escape de integração do shell.
# 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
}
Prompt de Comando de Administrador
O Prompt de Comando origina seu prompt da PROMPT variável de ambiente. CMD.exe lê $e como um caractere ESC. Infelizmente, CMD.exe não tem uma maneira de obter o código de retorno do comando anterior no prompt, portanto, não podemos fornecer informações de êxito/erro em prompts cmd.
Você pode alterar o prompt para a instância CMD.exe atual executando:
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
Ou você pode definir a variável da linha de comando para todas as sessões futuras:
setx PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
Esses exemplos pressupõem que o atual PROMPT seja apenas $P$G. Em vez disso, você pode optar por encapsular seu prompt atual com algo como:
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\%PROMPT%$e]133;B$e\
Bash
Você pode gerar o script a seguir para um shell ativo com source ou . comandos internos ou adicioná-lo bash ao final de seu ${HOME}/.bash_profile (para shells de logon) ou ${HOME}/.bashrc (para shells sem logon) para habilitar uma integração completa do bash shell com versões maiores ou iguais a bash-4.4 (em que a PS0 variável interna foi implementada inicialmente).
A integração completa do shell significa que cada recurso de terminal anunciado funciona conforme projetado.
Observação
Deve-se destacar que, se houver variáveis PROMPT_COMMAND, PS0, PS1 ou PS2 já atribuídas a quaisquer valores não padrão que possam levar a resultados imprevisíveis. Seria melhor testar o script primeiro com o shell "limpo", executando env --ignore-environment bash --noprofile --norc e fazendo o sourcing do arquivo descrito, conforme indicado anteriormente.
# .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}"
Isso encapsula toda a variedade de variáveis de bash prompt (PS0PS1ePS2) com as sequências necessárias para habilitar a integração completa do shell.
Além disso, ${HOME}/.inputrc também pode ser necessário um ajuste para remover os sinais de "notificação do modo de edição" e "linhas modificadas":
# .inputrc
set mark-modified-lines Off
set show-mode-in-prompt Off
É assim que deve ser se tudo for feito corretamente:
$ 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}|"
||
Nota: não encontrou seu shell favorito aqui? Se você descobrir, sinta-se à vontade para contribuir com uma solução para o seu shell preferido.
Recursos de integração do shell
Abrir novas guias no mesmo diretório de trabalho
Mostrar marcas para cada comando na barra de rolagem
Saltar automaticamente entre comandos
Isso usa as ações scrollToMark como as definimos acima.
Selecionar a saída inteira de um comando
Neste gif, usamos a ação selectOutput associada a ctrl+g para selecionar toda a saída de um comando.
O mostrado a seguir usa a configuração experimental.rightClickContextMenu para habilitar um menu de contexto de clique com o botão direito do mouse no Terminal. Com essa integração de shell habilitada, você pode clicar com o botão direito do mouse em um comando para selecionar todo o comando ou a saída dele.
Sugestões de comando recentes
Com a integração do shell habilitada, a interface do usuário de Sugestões pode ser configurada para mostrar também seus comandos recentes.
Você pode abrir este menu com a seguinte ação:
{
"command": { "action": "showSuggestions", "source": "recentCommands", "useCommandline": true },
},
(Para obter mais informações, consulte a Documentação de sugestões)
Recursos adicionais
Windows Terminal