터미널 에뮬레이터는 Shift+F 키를 어떻게 처리합니까?

터미널 에뮬레이터는 Shift+F 키를 어떻게 처리합니까?

이 질문은 다음에서 영감을 얻었습니다.vi.SE에 대한 또 다른 질문. OP에는 런타임 시 Shift+ F8키 조합에 문제가 있습니다. 터미널 에뮬레이터가 이를 올바르게 전달하지 않기 때문에(적어도 제가 디버깅한 것에서는) 키 조합이 작동하지 않습니다.vimurxvtvim

F터미널 에뮬레이터가 키를 어떻게 처리하는지 잘 모르겠습니다 .

존재하다urxvt

  • Shift+를 누르면 F8 ~에코가 울립니다 .
  • F7(또는 다른 F 키)를 누를 때도 ~에코됩니다 .

vim내부urxvt

  • Shift+를 누르면 F8효과가 나타납니다 ~~.
  • Shift+를 누르면 F7효과가 나타납니다 ~.
  • Shift+를 누르면 F6효과가 나타납니다 ~~~.

반면에 xterm:

  • Shift+를 누르면 F8 ;2~에코가 울립니다 .
  • F8(또는 다른 F 키)를 누를 때만 ~에코 됩니다.

왜 이런 결과가 나오는지 이해가 되지 않습니다.

추가 디버깅을 위해 실행하여 xev다음과 같은 결과를 얻었습니다.

~을 위한F8

KeyPress event, serial 29, synthetic NO, window 0x2000001,
    root 0x7e, subw 0x0, time 17730758, (431,256), root:(432,275),
    state 0x0, keycode 74 (keysym 0xffc5, F8), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

왼쪽Shift

KeyPress event, serial 32, synthetic NO, window 0x2000001,
    root 0x7e, subw 0x0, time 17733031, (431,256), root:(432,275),
    state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

그리고 오른쪽에는Shift

KeyPress event, serial 32, synthetic NO, window 0x2000001,
    root 0x7e, subw 0x0, time 17733372, (431,256), root:(432,275),
    state 0x0, keycode 62 (keysym 0xffe2, Shift_R), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

그러나 나는 거기에서 전혀 이상한 것을 보지 못했습니다.

터미널 에뮬레이터는 이러한 키(F 키)를 어떻게 처리합니까? 터미널 에뮬레이터는 무엇으로부터 정보를 받나요 x11? 내부적으로 실행되는 프로그램에 어떻게 전달합니까?

나는 항상 F 키가 단지 Esc숫자를 추가하는 조합이라고 생각했습니다. 이제 나는 내가 틀렸다는 것을 알았습니다.


부록

거기에서는 F 키가 제대로 작동하지 않습니다 Shift. 만약 내가한다면:vimurxvt

:map <f8> :echo "yay"<CR>

를 누르면 "아아"가 올바르게 에코됩니다 F8.

답변1

터미널과 애플리케이션 간의 인터페이스는 키가 아닌 바이트를 보냅니다. 인쇄 가능한 문자는 터미널의 문자 인코딩에 해당하는 바이트 시퀀스로 해석됩니다. 기능 키는 이스케이프 시퀀스로 인코딩됩니다. 이러한 이스케이프 시퀀스에 대한 일반적인 규칙이 있지만 완전히 표준화되지는 않았습니다.

보다 일반적인 배경을 보려면 다음을 참조하세요.키보드 입력과 텍스트 출력은 어떻게 작동합니까?. 자세한 내용은 다음을 참조하세요.콘솔 로그인 화면에서 위쪽 화살표를 누를 때 ^[[A가 표시되는 이유가 있나요?그리고키 바인딩 테이블?

모든 기능 키 이스케이프 시퀀스는 다음으로 시작합니다.이스케이프 문자그리고 대부분은 ~. Vim은 컴파일 시간 설정과 터미널 정보를 기반으로 여러 이스케이프 시퀀스를 인식합니다. Vim이 이스케이프 문자열을 인식하지 못하면 이를 무시하지만 Vim은 이스케이프 문자열의 길이를 알지 못합니다(마지막 문자가 a라고 가정하지 않으며 ~항상 그런 것은 아닙니다). ~Vim이 인식하는 부분 이후에는 종종 혼란이 발생하며 때로는 더욱 혼란스럽습니다.

쉘이나 Vim의 삽입 모드에서 먼저 +를 누르면 Ctrl터미널이 보내는 내용을 정확하게 볼 수 있습니다.V

Vim에게 이스케이프 시퀀스에 해당하는 기능 키를 알릴 수 있습니다.:set,예를 들어

:set <S-F8>=^[[19;2~

(뒷부분을 ^[터미널이 실제로 보내는 내용으로 바꾸세요).

답변2

일부 키는 다음과 같이 사용됩니다.수정자( shift, control가 가장 일반적으로 사용됩니다.) 터미널 에뮬레이터는 일련의X 이벤트, 를 사용하여 볼 수 있습니다 xev. 터미널 에뮬레이터는 shiftaX 라이브러리를 사용하여 A기능 키 및 커서 키(라고 함)와 같은 일부 이벤트를 통합합니다 ."특수 키") X 라이브러리에는 미리 정의된 변환이 없습니다. 터미널 에뮬레이터는 이러한 수정자를 사용하여 특수 키로 전송된 다양한 이스케이프 시퀀스를 생성할지 여부와 시기를 결정합니다.

다양한 터미널 에뮬레이터는 이에 대해 서로 다른 규칙을 사용할 수 있습니다. 없음기준전송할 수 있는 시퀀스입니다. 오직협약예를 들어, 특정 터미널을 에뮬레이트하거나 다른 터미널에는 없는 새로운 시퀀스를 만들어 확장하기로 결정합니다.

rxvt와 xterm은 모두 이러한 수정자를 사용하여 서로 다른 기능 키 시퀀스를 제공하므로 마치 터미널에 수십 개의 기능 키가 있는 것처럼 터미널에서 프로그램을 실행할 수 있습니다.

그러나 터미널에는 다음이 있을 수도 있습니다.모델, 애플리케이션에서 터미널까지의 제어 시퀀스에 의해 설정됨변화기능 키에 대해 전송된 이스케이프 시퀀스입니다. vim과 같은 전체 화면 프로그램에서는 이러한 모드 전환 제어 시퀀스를 사용하는 것이 일반적입니다. 그래서 당신은 차이점을 볼 수 있습니다.

왜냐하면 아무것도 없으니까기준, 하나 있어요터미널 설명각 터미널에 대해 해당 동작을 설명합니다( TERM환경 변수 사용). 대부분의 터미널의 경우 초기화 시 사용할 터미널을 설명합니다.신청방법(키보드 및 커서 키용) 전체 화면 응용 프로그램은 이러한 초기화 시퀀스를 사용하고 이러한 설명에 나열된 기능 키와 커서 키를 사용하여 일관된 동작을 얻습니다.

모든 터미널이 기능 키에 대한 이스케이프 시퀀스를 보내는 것은 아닙니다. 예를 들어,알토스워크스테이션은 캐럿을 사용합니다.와이즈-858비트 모드( \233CSI \033[) 사용을 지원합니다.qnx사용된 \377. 하지만 대부분의시작ASCII 이스케이프 문자를 사용합니다. 최종 캐릭터는 다른 이야기입니다. 절반 정도rxvt의 수정 기능 키ASCII 물결표 이외의 문자로 끝납니다 ~(이를 설명하는 ncurses FAQ에 표가 있습니다). 이러한 차이점 때문에 터미널 설명이 실제 터미널과 일치하는 것이 중요합니다.

현재 버전의 vim(7.3)에서는 문제가 없다고 생각합니다. 교대를 인식합니다 F8. 몇 년 전에 문제가 생겼습니다. vim의 기능 키 확인에는 xterm이 보내는 것처럼 세미콜론이 필요하지 않습니다. 세미콜론을 만나면 기능 키 인식이 중지됩니다. 이전 버전의 vim을 사용하고 있거나 일부 키 매핑으로 인해 키 누름을 인식하는 데 방해가 될 수 있습니다. vim은 이제 가능하지만 (사용하는 버전에 관계없이)아니요확장 키의 터미널 설명을 보지만 자체 테이블에 의존합니다. 문제를 복잡하게 만들기 위해 vim가능한xterm 기능(이라고 함)을 사용하십시오.tcap 쿼리)는 xterm이 보낸 실제 키 시퀀스를 가져옵니다.

반면 vim에는 rxvt 키 시퀀스에 대해 다른 결과를 제공하는 맵이 있을 수 있습니다. 시프트 F6( \E[29~), 시프트 F7( \E[31~), 시프트 F8( ) 사이에는 \E[32~특별한 차이가 없습니다 .

추가 자료:

관련 정보