쉘에서 제어 문자 (^ C, ^ D, ^ [,…)를 다르게 표시하는 방법


13

쉘에 제어 문자를 입력하면 "캐럿 표기법"을 사용하여 표시됩니다. 예를 들어 탈출 ^[은 캐럿 표기법으로 작성됩니다 .

bash 쉘을 멋지게 보이게 커스터마이징하고 싶습니다. 나는 예를 들어 내 변경 PS1과는 PS2색상 화 될 수 있습니다. 이제 제어 문자가 고유 한 모양을 갖도록하고 일반 문자와 구별하기 쉽기를 원합니다.

$ # Here I type CTRL-C to abort the command.
$ blahblah^C
          ^^ I want these two characters to be displayed differently

쉘 강조 제어 문자를 다르게 만드는 방법이 있습니까?

굵은 글꼴로 표시하거나 일반 텍스트와 다른 색상으로 표시 할 수 있습니까?

여기에 bash 쉘을 사용하고 있지만 bash다른 쉘에 적용되는 솔루션이 있기 때문에 질문에 태그를 지정하지 않았습니다 .

참고 내가 제어 문자의 강조 어떤 수준에서 모르는이 일어난다. 나는 그것이 껍질 자체에 있다고 생각했습니다. 이제 제어 문자가 bash 와 같은 쉘에있는 방법을 제어하는 readline 이라고 들었습니다 . 그래서 질문에 태그가 붙어 있으며 여전히 답을 찾고 있습니다.readline


왜 껍질이 그것들을 강조하고 있다고 생각합니까? 위해 bash가되는 readline그 물건을 취급, 대부분의 다른 사람을 위해 그것은 TTY 드라이버입니다.
mikeserv

몰랐어요 내가 메모를 쓴 이유입니다. 다른 응용 프로그램 이 일반 텍스트와 다르게 제어 문자를 좋아 vi하고 less자주 강조 하기 때문에 내 추측이었습니다 . 이 정보로 질문을 편집하겠습니다. 감사합니다!
wefwefa3

말이 되네요 그런 종류의 물건은 쉘이 두 번째 우선 순위이기 때문에 더 어렵습니다. 편집기에서 전체 작업은 화면 <> 파일 인터페이스를 제공하는 것이지만 셸은 먼저 해석 된 언어에 대한 명령 인터프리터이며 두 번째로 라인 편집기입니다 (또는 전혀 아님) .
mikeserv

Readline와는 다른 프로그램에서 사용되는, 또한 그것은 이다 배쉬의 일부 : 그것은에 링크 라이브러리입니다. 그리고 오늘날의 껍질, 특히 배쉬는 생각할 수있는 거의 모든 것을합니다.
Alexis

zsh상자에서 꺼내는 것을 사용 하십시오.
Stéphane Chazelas

답변:


20

를 누르면 Ctrl+X터미널 에뮬레이터가 바이트 0x18을 의사 터미널 쌍의 마스터 측에 씁니다.

다음에 일어날 일은 tty 라인 원칙 (에뮬레이터의 제어하에있는 마스터 측과 터미널에서 실행되는 응용 프로그램과 상호 작용하는 슬레이브 측 사이에있는 커널의 소프트웨어 모듈)이 어떻게 구성되어 있는지에 달려 있습니다.

tty line discipline 을 구성하는 stty명령 이 명령입니다.

이와 같은 벙어리 응용 프로그램을 실행할 때 catstdin이 터미널인지 여부를 신경 쓰지 않고 신경 쓰지 않는 경우 터미널은 기본 표준 모드에 있으며 tty 라인 규칙은 조잡한 라인 편집기를 구현합니다 .

원유 편집기 보다 더 많은 일부 대화식 응용 프로그램은 일반적으로 시작시 해당 설정을 변경하고 떠나면 복원합니다. 프롬프트에서 현대 쉘 은 그러한 응용 프로그램의 예입니다. 그들은 자신의 고급 라인 편집기를 구현합니다.

일반적으로 명령 행을 입력하는 동안 쉘은 tty 행 규율을 해당 모드로 설정하고 Enter를 눌러 현재 명령을 실행하면 쉘은 일반 tty 모드를 복원합니다 (프롬프트를 실행하기 전의 상태).

stty -a명령 을 실행 하면 dumb 응용 프로그램 에 현재 사용중인 설정이 표시 됩니다 . 당신은 볼 가능성이있어 icanon, echoechoctl설정이 활성화된다.

그 의미는 다음과 같습니다.

  • icanon: 원유 라인 편집기가 활성화되었습니다.
  • echo: 입력 한 문자 (터미널 에뮬레이터가 마스터 측에 쓰는 문자)가 에코 됩니다 (터미널 에뮬레이터가 읽을 수 있도록).
  • echoctl: 대신되는 에코 Asis으로, 제어 문자가되어 반향 으로 ^X.

을 입력한다고 가정 해 봅시다 A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.

터미널 에뮬레이터가 다음을 전송 AB\bC\x18\b\r합니다.. 라인 규칙은 에코 백 : AB\b \bC^X\b \b\b \b\r\n이며 슬레이브 측 ( /dev/pts/x) 에서 입력을 읽는 응용 프로그램은을 읽습니다 AC\n.

모든 응용 프로그램은 AC\n이며 프레스를 누를 때만 표시 Enter되므로 출력을 제어 할 수 없습니다 ^X.

넌위한 것을 알 에코 , 가장 먼저 ^H( ^?일부 단말기와 상기 참조 erase설정)의 결과 \b \b를 다시 단말기로 전송된다. 즉, 두 번째는 동안, 다시, 이동 커서, 커서 등을 이동 공간을 덮어 순서의 ^H결과 \b \b\b \b두 삭제 ^X문자를.

^X(0x18) 자체로 변환되고 있었다 ^X출력. 마찬가지로 BBackspace로 삭제했기 때문에 응용 프로그램에 적용되지 않았습니다.

\r(aka ^M)는 에코로 ( ), 응용 프로그램 으로 \r\n( )로 변환되었습니다 .^M^J\n^J

그래서 그 바보 같은 응용 프로그램에 대한 우리의 옵션은 무엇입니까?

  • 비활성화 echo( stty -echo). 그것은 아무것도 제어하지 않고 제어 문자가 표시되는 방식을 효과적으로 변경합니다. 실제로 해결책은 아닙니다.
  • disable echoctl. 제어 문자 ( ^H, ^M... 및 라인 편집기에서 사용되는 다른 모든 문자 )가 에코 되는 방식이 변경 됩니다. 그런 다음 그대로 에코 됩니다. 예를 들어, ESC 문자는 \e( ^[/ 0x1b) 바이트 (터미널에 의해 이스케이프 시퀀스의 시작으로 인식됨)로 ^G전송되며, \a(BEL, 터미널에서 경고음을냅니다.) .
  • 원유 라인 편집기를 비활성화합니다 ( stty -icanon). 조잡한 응용 프로그램이 훨씬 덜 유용하게 사용될 수 있으므로 실제로는 옵션이 아닙니다.
  • 커널 코드를 편집하여 tty 라인 규칙의 동작을 변경하여 제어 문자 의 에코\e[7m^X\e[m 가 단지 대신 전송 되도록합니다 ^X( \e[7m대개 대부분의 터미널에서 반전 비디오를 활성화합니다).

rlwrap바보 같은 응용 프로그램에 멋진 라인 편집기를 추가하는 더러운 해킹 과 같은 래퍼를 사용하는 옵션이 있습니다 . 이 래퍼 read()는 터미널 장치에서 간단한 s를 readline line editor (tty line discipline의 모드를 변경하는)에 대한 호출 로 대체하려고 시도합니다 .

심지어 더 나아가, 당신도 같은 솔루션을 시도 할 수 이것 (하이라이트로 발생 zsh을의 라인 에디터를 통해 이동하는 터미널에서 모든 입력 탈취 ^XGNU 화면의에 의존 역상들) :exec기능입니다.

이제 자체 라인 편집기를 구현하는 응용 프로그램의 경우 에코 수행 방법을 결정하는 것은 응용 프로그램의 몫 입니다. bash제어 문자의 에코 방법을 사용자 정의 할 수없는 readline을 사용합니다.

에 대해서는 다음 zsh을 참조하십시오.

info --index-search='highlighting, special characters' zsh

zsh기본적으로 인쇄 할 수없는 문자를 강조 표시합니다. 예를 들어 다음과 같이 강조 표시를 사용자 정의 할 수 있습니다.

zle_highlight=(special:fg=white,bg=red)

해당 특수 문자에 대한 빨간색 강조 표시의 흰색입니다.

해당 문자의 텍스트 표현은 사용자 정의 할 수 없습니다.

수정 UTF-8 로켈에서 0x18은 다음과 같이 표현 될 것이다 ^X, \u378, \U7fffffff로 (이 할당되지 않은 유니 코드 코드 포인트) <0378>, <7FFFFFFF>, \u200b등 (하지 않은 정말 인쇄 가능한 유니 코드 문자) <200B>.

\x80iso8859-1 로켈에서 ^�... 등 으로 렌더링됩니다 .


3

내 코드는 .bashrc 파일에 있습니다.

function get_exit_status()
{
        local code=$?
        if [ $code -ne 0 ]
        then
                printf $'\001\033[31m\002'"($code)"$'\001\033[0m\002'" "
        fi
}

그런 다음 PS1에서이 함수를 호출합니다.

PS1='\u@\h \w $(get_exit_status)'

이것으로 ^ C를 누르면 프롬프트에서 볼 수 있습니다

I@mycomputer ~ ^C
I@mycomputer ~ (130)

"0"이 아닌 모든 종료 상태 코드가 프롬프트됩니다.


$? 에서 종료 상태에 펼쳐지는 PS1 예를 들어, PS1 = '$ \ U @ \ H \ w?'
teknopaul
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.