Integrazione della shell
- Integrazione della shell
A partire da Terminale 1.15 Anteprima, il Terminale Windows ha iniziato a supportare in modo sperimentale alcune funzionalità di "integrazione della shell". Queste funzionalità semplificano l'uso della riga di comando. Nelle versioni precedenti veniva abilitata la shell per indicare al terminale la directory di lavoro corrente. Ora è stato aggiunto il supporto per altre sequenze per consentire alla shell di descrivere semanticamente parti dell'output del terminale come "prompt", "comando" o "output". La shell può anche indicare al terminale se un comando ha avuto esito positivo o negativo.
Questa è una guida ad alcune delle funzionalità di integrazione della shell implementate a partire da Terminale v1.18. Stiamo pianificando di creare ancora più funzionalità in futuro, quindi ci piacerebbe ottenere un feedback aggiuntivo sul modo in cui le persone le usano.
Nota: a partire dal terminale 1.21, i contrassegni sono ora una funzionalità stabile. Prima della versione 1.21, i contrassegni sono stati abilitati solo per le build di anteprima del terminale. Se si usa una versione di Terminale precedente alla 1.21, l'impostazione
showMarksOnScrollbar
è denominataexperimental.showMarksOnScrollbar
eautoMarkPrompts
è denominataexperimental.autoMarkPrompts
.
Come funziona?
L'integrazione della shell funziona con la shell (o qualsiasi applicazione della riga di comando) per scrivere "sequenze di escape" speciali nel terminale. Queste sequenze di escape non vengono stampate nel terminale, ma forniscono bit di metadati che il terminale può usare per saperne di più su cosa sta succedendo nell'applicazione. Se si aggiungono queste sequenze al prompt della shell, è possibile che la shell fornisca continuamente informazioni al terminale che solo la shell conosce.
Per le sequenze seguenti:
OSC
è"\x1b]"
per la stringa: un carattere di escape, seguito da]
ST
è il carattere di terminazione stringa e può essere\x1b\
(un carattere ESC, seguito da\
) o\x7
(il carattere BEL)- Gli spazi sono semplicemente illustrativi.
- Le stringhe in
<>
sono parametri che devono essere sostituiti da un altro valore.
Le sequenze di integrazione della shell supportate pertinenti a partire da Terminale v1.18 sono:
OSC 133 ; A ST
("FTCS_PROMPT") - L'inizio di un prompt.OSC 133 ; B ST
("FTCS_COMMAND_START") - L'inizio di una riga di comando (READ: la fine del prompt).OSC 133 ; C ST
("FTCS_COMMAND_EXECUTED") - L'inizio dell'output del comando/la fine della riga di comando.OSC 133 ; D ; <ExitCode> ST
("FTCS_COMMAND_FINISHED") - La fine di un comando.ExitCode
SeExitCode
viene specificato, il terminale considererà0
come "esito positivo" e qualsiasi altro elemento come errore. Se omesso, il terminale lascerà solo il segno di colore predefinito.
Come abilitare i contrassegni di integrazione della shell
Il supporto di queste funzionalità richiede la cooperazione tra la shell e il terminale. È necessario abilitare entrambe le impostazioni nel terminale per usare queste nuove funzionalità, nonché modificare il prompt della shell.
Per abilitare queste funzionalità nel terminale, è necessario aggiungere quanto segue alle impostazioni:
"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 modalità di abilitazione di questi contrassegni nella shell varia da shell a shell. Di seguito sono riportate le esercitazioni per CMD, PowerShell e Zsh.
PowerShell (pwsh.exe
)
Se il prompt di PowerShell non è mai stato modificato in precedenza, è consigliabile consultare prima about_Prompts.
È necessario modificare il file prompt
per assicurarsi che il terminale sia in grado di comunicare con la CWD e contrassegnare il prompt con i contrassegni appropriati. PowerShell consente anche di includere il codice di errore del comando precedente nella sequenza 133;D
, che consentirà al terminale di colorare automaticamente il contrassegno in base all'esito positivo o negativo del comando.
Aggiungere quanto segue al profilo di 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
Usando oh-my-posh? È consigliabile modificare leggermente il codice precedente per eliminare il prompt originale, quindi aggiungerlo di nuovo al centro delle sequenze di escape di integrazione della 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 dei comandi
Le origini del prompt dei comandi vengono richieste dalla variabile di ambiente PROMPT
. CMD.exe legge $e
come ESC
carattere. Sfortunatamente, CMD.exe non ha un modo per ottenere il codice restituito del comando precedente nel prompt, quindi non è possibile fornire informazioni sull'esito positivo/negativi nei prompt CMD.
È possibile modificare il prompt dell'istanza CMD.exe corrente eseguendo:
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
In alternativa, è possibile impostare la variabile dalla riga di comando per tutte le sessioni future:
setx PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
Questi esempi presuppongono che l'oggetto corrente PROMPT
sia solo $P$G
. È invece possibile scegliere di eseguire il wrapping del prompt corrente con un messaggio simile al seguente:
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\%PROMPT%$e]133;B$e\
Bash
È possibile aggiungere quanto segue alla fine di per abilitare l'integrazione della ~/.bashrc
shell in bash:
PS1="\[\033]133;D;\007\]\[\033]133;A;\007\]$PS1\[\033]133;B;\007\]"
Verrà eseguito il wrapping dell'esistente $PS1
con le sequenze necessarie per abilitare l'integrazione della shell.
Nota: la shell preferita non è indicata qui? Se lo si scopre, è possibile contribuire a una soluzione per la shell preferita.
Funzionalità di integrazione della shell
Aprire nuove schede nella stessa directory di lavoro
Mostrare segni per ogni comando nella barra di scorrimento
Passare automaticamente tra i comandi
In questo modo vengono usate le scrollToMark
azioni definite in precedenza.
Selezionare l'intero output di un comando
In questa gif viene usata l'azione selectOutput
associata a ctrl+g
per selezionare l'intero output di un comando.
Di seguito viene usata l'impostazione experimental.rightClickContextMenu
per abilitare un menu di scelta rapida del pulsante destro del mouse nel terminale. Con l'integrazione di tale e shell abilitata, è possibile fare clic con il pulsante destro del mouse su un comando per selezionare l'intero comando o il relativo output.
Suggerimenti recenti per i comandi
Con l'integrazione della shell abilitata, è possibile configurare l'interfaccia utente dei suggerimenti per visualizzare anche i comandi recenti.
È possibile aprire questo menu con l'azione seguente:
{
"command": { "action": "showSuggestions", "source": "recentCommands", "useCommandline": true },
},
(Per altre info, vedi Documentazione dei suggerimenti)