터미널 1.15 미리 보기부터 Windows 터미널은 일부 "셸 통합" 기능을 실험적으로 지원하기 시작했습니다. 이러한 기능을 사용하면 명령줄을 더 쉽게 사용할 수 있습니다. 이전 릴리스에서는 셸을 사용하여 터미널에 현재 작업 디렉터리가 무엇인지 알릴 수 있도록 했습니다. 이제 셸이 터미널 출력의 일부를 "프롬프트", "명령" 또는 "출력"으로 의미상 설명할 수 있도록 더 많은 시퀀스에 대한 지원을 추가했습니다. 셸은 명령의 성공 또는 실패 여부를 터미널에 알릴 수도 있습니다.
터미널 v1.18에서 출시한 셸 통합 기능 중 일부에 대한 가이드입니다. 향후 이러한 기능을 기반으로 더 많은 기능을 빌드할 계획이므로 사람들이 이러한 기능을 사용하는 방법에 대한 추가 피드백을 얻고 싶습니다.
참고: 터미널 1.21을 기준으로 표시는 이제 안정적인 기능입니다. 1.21 이전에는 터미널의 미리 보기 빌드에만 표시를 사용할 수 있었습니다. 1.21 이전 버전의 터미널을 사용하는 경우 설정의
showMarksOnScrollbar이름이 지정experimental.showMarksOnScrollbar되고autoMarkPrompts이름이 지정experimental.autoMarkPrompts되었습니다.
어떻게 작동하나요?
셸 통합은 셸(또는 명령줄 애플리케이션)이 터미널에 특수한 "이스케이프 시퀀스"를 쓰도록 하여 작동합니다. 이러한 이스케이프 시퀀스는 터미널에 인쇄되지 않습니다. 대신 터미널에서 애플리케이션에서 진행 중인 작업을 자세히 파악하는 데 사용할 수 있는 메타데이터 비트를 제공합니다. 이러한 시퀀스를 셸의 프롬프트에 고정하면 셸에서 셸만 알고 있는 정보를 터미널에 지속적으로 제공할 수 있습니다.
다음 시퀀스의 경우:
-
OSC은(는) 이스케이프 문자"\x1b]"와 그 뒤에 오는 문자열]임 -
ST은(는) "문자열 종결자"이며,\x1b\(ESC 문자 뒤에\이(가) 오는 문자) 또는\x7(BEL 문자) 중 하나일 수 있음 - 공백은 단지 예시일 뿐입니다.
-
<>의 문자열은 다른 값으로 대체해야 하는 매개 변수입니다.
터미널 v1.18을 기준으로 지원되는 관련 셸 통합 시퀀스는 다음과 같습니다.
-
OSC 133 ; A ST("FTCS_PROMPT") - 프롬프트의 시작입니다. -
OSC 133 ; B ST("FTCS_COMMAND_START") - 명령줄의 시작(읽기: 프롬프트의 끝)입니다. -
OSC 133 ; C ST("FTCS_COMMAND_EXECUTED") - 명령 출력의 시작/명령줄의 끝입니다. -
OSC 133 ; D ; <ExitCode> ST("FTCS_COMMAND_FINISHED") - 명령의 끝입니다.ExitCodeExitCode이(가) 제공된 경우 터미널은0을(를) "성공" 및 기타 모든 것을 오류로 처리합니다. 생략하면 터미널은 표시를 기본 색으로 그대로 둡니다.
셸 통합 표시를 사용하도록 설정하는 방법
이러한 기능을 지원하려면 셸과 터미널 간의 협력이 필요합니다. 터미널에서 이러한 새로운 기능을 사용하도록 설정하고 셸의 프롬프트를 수정해야 합니다.
터미널에서 이러한 기능을 사용하도록 설정하려면 설정에 다음을 추가해야 합니다.
"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" }, },
]
셸에서 이러한 표시를 사용하도록 설정하는 방법은 셸마다 다릅니다. CMD, PowerShell 및 Zsh에 대한 자습서는 다음과 같습니다.
PowerShell(pwsh.exe)
이전에 PowerShell 프롬프트를 변경한 적이 없는 경우 먼저 about_Prompts를 확인해야 합니다.
CWD에 대해 터미널에 알리고 프롬프트를 적절한 표시로 표시하려면 prompt을(를) 편집해야 합니다. 또한 PowerShell을 사용하면 명령이 성공하거나 실패한 경우 터미널에서 133;D 자동으로 표시 색을 지정할 수 있도록 이전 명령의 오류 코드를 시퀀스에 포함할 수 있습니다.
다음을 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
}
오 마이 포쉬 설정
오- 마이 포쉬를 사용? 위의 내용을 약간 수정하여 원래 프롬프트를 숨긴 다음 셸 통합 이스케이프 시퀀스의 중간에 다시 추가하려고 합니다.
# 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 . CMD.exe 문자로 읽습니다 $eESC . 안타깝게도 CMD.exe는 프롬프트에서 이전 명령의 반환 코드를 가져올 방법이 없으므로 CMD 프롬프트에서 성공/오류 정보를 제공할 수 없습니다.
다음을 실행하여 현재 CMD.exe 인스턴스에 대한 프롬프트를 변경할 수 있습니다.
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
또는 이후의 모든 세션에 대한 명령줄에서 변수를 설정할 수 있습니다.
setx PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\
이러한 예제에서는 현재 사용자의 PROMPT이(가) $P$G(이)라 가정합니다. 대신 다음과 같이 현재 프롬프트를 래핑하도록 선택할 수 있습니다.
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\%PROMPT%$e]133;B$e\
Bash
다음 스크립트를 사용하거나 기본 제공 bash 명령을 사용하여 활성 셸 source 에 원본을 지정하거나.(로그인 셸의 ${HOME}/.bash_profile 경우) 또는 ${HOME}/.bashrc (로그인되지 않은 셸의 경우) 전체 셸을 더 크거나 같은 버전(기본 제공 변수가 처음 구현된 위치PS0)과 통합 bash 할 bash-4.4 수 있도록 할 수 있습니다.
완전한 셸 통합은 발표된 모든 터미널 기능이 설계된 대로 작동한다는 것을 의미합니다.
비고
예측할 수 없는 결과를 초래할 수 있는 기본값이 아닌 값에 이미 할당된 변수 또는 PS2 변수가 있는 경우 PROMPT_COMMANDPS0PS1 이를 지적해야 합니다. 앞에서 설명한 대로 설명된 파일을 실행하고 env --ignore-environment bash --noprofile --norc 소싱하여 먼저 "clean" 셸로 스크립트를 테스트하는 것이 좋습니다.
# .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}"
이렇게 하면 전체 셸 통합을 사용하도록 설정하는 데 필요한 시퀀스로 프롬프트 변수(PS0PS1및PS2)의 bash 모든 구색을 래핑합니다.
또한 ${HOME}/.inputrc "편집 모드 알림" 및 "수정된 줄" 기호를 제거하기 위해 조정이 필요할 수도 있습니다.
# .inputrc
set mark-modified-lines Off
set show-mode-in-prompt Off
모든 것이 올바르게 수행되면 다음과 같이 표시됩니다.
$ 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}|"
||
참고: 즐겨찾는 셸이 여기에 표시되지 않나요? 당신이 그것을 알아 내는 경우, 원하는 셸에 대한 솔루션을 기여 주시기 바랍니다!
셸 통합 기능
동일한 작업 디렉터리에서 새 탭 열기
스크롤 막대에서 각 명령에 대한 표시 보이기
명령 간에 자동으로 이동
위에서 정의한 scrollToMark 대로 작업을 사용합니다.
명령의 전체 출력 선택
이 gif에서는 바인딩된 selectOutputctrl+g 작업을 사용하여 명령의 전체 출력을 선택합니다.
다음은 이 설정을 사용하여 experimental.rightClickContextMenu 터미널에서 마우스 오른쪽 단추로 클릭하는 상황에 맞는 메뉴를 사용하도록 설정합니다. 해당 및 셸 통합을 사용하도록 설정하면 명령을 마우스 오른쪽 단추로 클릭하여 전체 명령 또는 해당 출력을 선택할 수 있습니다.
최근 명령 제안
셸 통합을 사용하도록 설정하면 최근 명령도 표시하도록 제안 UI를 구성할 수 있습니다.
다음 작업을 사용하여 이 메뉴를 열 수 있습니다.
{
"command": { "action": "showSuggestions", "source": "recentCommands", "useCommandline": true },
},
(자세한 내용은 다음을 참조하세요 .제안 설명서)
추가 리소스
Windows Terminal