PS1의 ANSI 이스케이프 시퀀스로 인해 잘못된 길이 계산이 발생함

PS1의 ANSI 이스케이프 시퀀스로 인해 잘못된 길이 계산이 발생함

PS1내 설정에는 .zshrc여러 ANSI 이스케이프 시퀀스가 ​​포함되어 있습니다. 동등한 정의는 Bash에서는 잘 작동하지만 Zsh(v5.8.1)에서는 셸이 프롬프트 너비를 잘못 계산하는 것으로 보입니다. 따라서 더 긴 명령을 입력하면 명령줄이갑자기 사라지다, 터치 타이핑 중입니다. 어떤 경우에는 PS1개행 문자가 포함되지 않은 경우에도 커서가 프롬프트 뒤의 다음 줄에 위치하게 됩니다 .

나는 이미 사용하고 있습니다\001…\002이스케이프 시퀀스readline은 이를 사용하여 각 ANSI 이스케이프 시퀀스의 길이 계산을 조정합니다. 불행히도 이것은 Zsh에 충분하지 않은 것 같습니다(아래 예에서는 Zsh가 없는 것 같습니다).어느효과가 있었지만 실제 더 복잡한 경우에는 PS1상황이 개선되는 것 같았습니다.일부, 적어도).

다음은 문제를 보여주는 예입니다(주석은 대괄호로 묶어야 한다고 생각하는 ANSI 이스케이프 시퀀스 부분을 강조합니다 \001…\002).

PS1=$'\001\e[38;2;1;1;1m\e[48;5;250m\002}\001\e[38;5;250m\e[48;2;1;1;1m\002} '
#     \001--------------------------\002 \001--------------------------\002

이 프롬프트와 80열 터미널을 사용하면 25자를 입력하면 프롬프트를 포함한 전체 명령이 사라집니다. 백스페이스 키를 사용하면 문자가 다시 나타나지 않고 대신 커서가 이전 줄로 이동합니다.

이것은 이 행동에 대한 Asciinema의 설명입니다.

이 데모에서는 셸의 다른 모든 사용자 정의를 비활성화했습니다.

(저는 실제로 nf-pl-left_hard_dividerU+E0B0을 사용하고 있습니다.대단하다 글꼴s 대신에 사용되지만 }이는 문제에 영향을 미치지 않습니다. )

내가 뭘 잘못했나요? Zsh 프롬프트 정의에서 ANSI 이스케이프 시퀀스를 사용하는 방법은 무엇입니까?

답변1

에서는 이스케이프 문자를 사용 하고 프롬프트 zsh할 수 있습니다 . ~에서%{%}info zsh 'prompt expansion':

%{...%}
리터럴 이스케이프 시퀀스로 문자열을 포함합니다. 중괄호 안의 문자열은 커서 위치를 변경해서는 안 됩니다. 지원 쌍은 중첩될 수 있습니다.

%와 { 사이의 양수 인수는 아래 %G에 대해 설명된 대로 처리됩니다.

따라서 PS1='%{\e[...m%}'zsh에는 대부분의 시각적 효과에 대한 자체 힌트 확장 연산자가 있으므로 이스케이프 시퀀스를 하드코딩할 필요가 없다는 점만 제외하면 됩니다.

예를 들어, 256 팔레트의 배경색을 FRGB로 설정 #010101하고 배경색을 250으로 설정하려면 다음을 수행합니다.B

PS1='%F{#010101}%K{250}Text%f%k%# '

이를 사용 print -P하여 힌트 확장을 수행하여 해당 이스케이프 시퀀스가 ​​생성되고 있는지 확인할 수도 있습니다.

$ print -rP '%F{#010101}%K{250}' | sed -n l
\033[38;2;1;1;1m\033[48;5;250m$

트루 컬러 이스케이프 시퀀스를 지원하지 않지만 256 팔레트를 지원하는 터미널의 사양에 zsh/nearcolor가장 가까운 색상을 제공하는 모듈도 있습니다.#RRGGBB

$ zmodload zsh/nearcolor
$ print -rP '%F{#010101}%K{250}' | sed -n l
\033[38;5;16m\033[48;5;250m$

관련 정보