바인딩 -x는 터미널을 ^V와 유사한 상태로 만듭니다.

바인딩 -x는 터미널을 ^V와 유사한 상태로 만듭니다.

나는 다음과 같이 쉘 키 바인딩을 정의했습니다 ~/.bashrc.

bind -x '"\e\C-w":"/usr/bin/reset"'

이렇게 하면 실행 파일이 Ctrl-Alt-w시작 됩니다 reset. 그러나 터미널은 Enter 키를 누르는 것과 유사한 상태로 유지됩니다 Ctrl-v. 예를 들어, 이 방법으로 재설정한 후 바로 키를 누르면 Ctrl-p바로가기 동작(이전 명령 반복)을 호출하는 대신 ^P인쇄가 됩니다.

이 문제의 원인과 해결 방법을 아시나요?

편집하다: 제가 하려는 작업을 재현하는 Python 프로그램을 첨부했습니다 reset. 멀티스레드 애플리케이션을 디버깅할 때 이런 상황이 자주 발생합니다.

import pdb, thread, time

def interrupt():
    time.sleep(2)
    pdb.set_trace()

thread.start_new_thread(interrupt, ())
raw_input('? ')

pdb.set_trace()혼란스러운 상황을 재현하려면 위의 코드를 실행하고 디버거가 호출되는 것을 볼 때 Enter를 누르십시오(프로그램을 실행한 후 약 2초 후에 끝에 많은 텍스트가 인쇄되고 초기 프롬프트가 나타납니다).

답변1

실행하면 reset터미널 디스플레이가 지워지고 모든 입력 설정이 기본값으로 재설정됩니다. 특히 입력 모드를 다음으로 설정합니다.요리즉, 터미널은 한 번에 한 라인을 읽은 다음 전체 라인을 애플리케이션(여기서 애플리케이션은 bash)에 보냅니다. 터미널의 라인 편집기는 백스페이스 키만 이해하는 매우 원시적인 편집기이며, 멋진 기능은 없습니다. Bash는 터미널을 원시 모드로 전환하고 각 문자를 입력하자마자 애플리케이션으로 전송되는 정교한 라인 편집기를 제공합니다.

터미널이 엉망인 경우(라인 버전이 없거나 bash 프롬프트에 에코가 없음) 복구하는 가장 쉬운 방법은 명령을 실행 reset하거나 를 stty sane실행하는 것 입니다 Return. 이것이 작동하지 않는 경우(예를 들어 터미널이 쿠킹 모드에 있고 줄 제출 문자가 기본 문자가 아니기 때문에) reset 2>/dev/pts/42(터미널 재초기화) 또는 stty sane </dev/pts/42(입력 구성 재초기화)를 실행할 수 있습니다(다른 리디렉션 참고). /dev/pts/42쉘을 실행하는 터미널은 어디입니까? 터미널 이름에서 명령을 실행할 수 없는 경우 터미널 이름을 찾으려면 추측이 필요할 수 있습니다. 터미널 내에서 이 명령을 tty실행하면 표시됩니다. 출력에서 올바른 bash 프로세스를 찾을 수 있는 경우 앞에 가 붙은 해당 열이 ps필요합니다 .TTY/dev

bash 프롬프트에 입력하여 이러한 명령을 실행하는 것은 정확하지만 readline 매크로의 일부로 실행하는 것은 아닙니다. Bash는 새 프롬프트를 인쇄할 때마다 터미널 설정을 재설정하므로 줄을 편집하는 동안 수행한 작업은 후속 명령에 유지되지 않습니다.

또한 이는 줄 편집 중에 실행하는 경우 bash가 의존하는 매개변수를 엉망으로 만듭니다 reset. 특히 터미널 모드를 "cooked"로 설정하는 반면, bash 줄 편집에서는 줄 편집기가 입력 문자를 문자별로 수신해야 합니다. bash 명령줄 버전의 bash 프롬프트 도중과 외부의 출력을 비교해 보면 stty다음과 같은 설정이 필요하다고 생각합니다.

bind -x '"\e\C-w": "reset; stty -icrnl -icanon -echo </dev/tty"'

reset단지 화면을 지우려고 전화하는 경우에는 대신 전화하세요.tput rs1 rs2 rs3 rfreset

위에서 쓴 것처럼 터미널 설정을 재설정하는 올바른 방법은 resetbash 프롬프트에서 실행하는 것입니다. bash가 다음 프롬프트를 표시할 때 이전 애플리케이션(터미널 설정을 망친 애플리케이션)이 남긴 설정을 복원하기 때문에 키 바인딩의 일부로 실행하면 작동하지 않습니다. Bash에는 터미널 설정을 일반 기본값으로 재설정하는 내장 기능이 없다고 생각하지만 필요한 경우 사용자 구성을 통해 수행하고 다음 줄을 사용할 수 있습니다 .bashrc.

PROMPT_COMMAND="$PROMPT_COMMAND
stty sane"

줄 편집 중에 터미널 설정을 재설정하는 키 바인딩을 정말로 원한다면 좀 더 정교한 것이 필요합니다. bash가 reset(편집 명령의 일부가 아닌) 프롬프트에서 명령을 실행하도록 한 다음 현재 편집을 재개합니다. 바인딩은 readline 매크로나 bash 함수만 가능하고 이 둘을 혼합할 수 없기 때문에 bash에서는 이를 수행하기가 쉽지 않습니다. 다음 코드는 ++를 readline 매크로 Ctrl에 바인딩합니다 . 이 매크로는 바인딩을 통해 bash 함수를 호출하고, 바인딩을 통해 readline 함수를 호출한 다음 , 또 다른 바인딩을 통해 다른 bash 함수를 호출합니다. 이것MetaWaccept-line\C-mbind -x바인딩은 길이가 1 또는 2인 키 시퀀스에만 할당될 수 있습니다.C-x LETTER, 그래서 저는 거의 사용되지 않는 도우미 매크로 조합을 사용합니다.

run_command_during_line_edition () {
  saved_READLINE_LINE=$READLINE_LINE saved_READLINE_POINT=$READLINE_POINT
  READLINE_POINT=0 READLINE_LINE=" $1"
  unset run_command_first
}
restore_saved_command () {
  READLINE_LINE=$saved_READLINE_LINE READLINE_POINT=$saved_READLINE_POINT
  unset saved_READLINE_LINE saved_READLINE_POINT
}
bind -x '"\C-xZ": "restore_saved_command"'
bind -x '"\C-xR": "reset; stty sane -icrnl -icanon -echo; run_command_during_line_edition reset"'
bind '"\e\C-w": "\C-xR\r\C-xZ"'

다시 말하지만, 아마도 이 모든 복잡성이 필요하지 않을 것입니다. reset프롬프트에서 블라인드 타이핑을 하거나 stty sane에 포함시키면 PROMPT_COMMAND도움이 될 것입니다. 아, 아니면 zsh로 전환하면 아주 쉬울 것입니다.

관련 정보