Linux 터미널에서 \e[H\e[2J ANSI 이스케이프 시퀀스를 해석하는 방법은 무엇입니까?

Linux 터미널에서 \e[H\e[2J ANSI 이스케이프 시퀀스를 해석하는 방법은 무엇입니까?

StackOverflow에 질문을 다시 올렸는데 답변이 없고 현상금을 추가했지만 효과가 없습니다(그냥 현상금을 삭제했습니다). 내 생각엔 여기 사람들이 무슨 일이 일어나고 있는지 더 잘 알 수 있을 것 같아요.

내 JavaScript 라이브러리에 대한 더 나은 ANSI 이스케이프 코드 해석기를 개발 중이지만 명령을 처리하는 데 문제가 있습니다 top( script터미널 출력을 파일에 덤프하는 명령 사용).

대체 화면을 사용하는 MacOS의 샘플 파일이 있습니다 ESC [ ? 1049 h.l여기에 녹음하세요.

문제는 명령의 Linux 버전이 top대체 화면만 사용하지 않는다는 것입니다. \e[H\e[2J순서는 1,1로 이동하여 화면을 지우는 것입니다. 내 이해로는 실제로 이 명령 이전에 터미널에 인쇄된 모든 내용이 지워져야 합니다. 이것이 내가 파서/인터프리터에서 하는 일이다. 하지만 Linux 터미널은 그렇지 않습니다(저는 XFce 터미널을 사용합니다). 어떻게든 화면의 일부를 지우고 페이지를 아래로 스크롤합니다.

그래서 제 질문은 \e[H\e[2JLinux 터미널처럼 렌더링하기 위해 최상위 명령(시퀀스)을 처리하는 정확한 단계(알고리즘)가 무엇입니까? 내 터미널에 표시되는 세션 출력으로 문자열이 필요합니다.

다음은 스크립트 명령의 샘플 출력입니다.https://jcubic.pl/screen_dump_linux_top.txt

테스트 코드가 있습니다코드 펜:

다음 코드를 사용하세요:

$.terminal.format($.terminal.overtyping($.terminal.from_ansi(text)));

Linux에서 top 명령의 출력을 보면. 이전에는 명령의 출력이 표시되지 않습니다. 모든 것을 인쇄하는 macOS 파일과 비교합니다(실제 터미널은 기본 화면으로 다시 전환할 때 대체 화면을 인쇄하지 않는다는 것을 알고 있지만 해당 출력을 거기에 넣기로 결정했습니다. 어쩌면 토글 옵션을 추가했을 수도 있습니다).

터미널 에뮬레이터 소스 코드를 확인할 수 있다는 것을 알고 있지만 단순히 이것에 대해 묻는 것보다 시간이 더 걸릴 것입니다.

답변1

\e[H커서를 홈페이지(왼쪽 상단)로 이동하여 \e[2J화면을 지웁니다(자주 보는 부분이지만 뒤로 스크롤되는 부분은 아님).

많은 터미널 에뮬레이터에서는 \e[2J화면에서 자주 보는 부분이 단순히 그 자리에서 지워집니다. 결과는 다음과 같습니다. 일부 출력(예: seq 100테스트 목적)을 생성하는 명령을 실행한 다음 실행하면 top이전 프로그램 출력의 시작 부분은 스크롤백 버퍼에 남아 있지만 출력의 끝은 영원히 손실됩니다.

이 비논리적인 동작을 해결하기 위해 일부 터미널 에뮬레이터(Xfce 터미널에서 사용하는 VTE 위젯 포함)는 동작을 수정했습니다 \e[2J. 즉, 화면을 스크롤백 버퍼로 스크롤합니다. "일반 영역"의 결과는 동일합니다. 빈 화면이 표시됩니다. 스크롤백 버퍼의 내용은 틀림없이 더 의미가 있습니다. 이전 명령의 전체 출력이 유지됩니다.

\e[3J이렇게 하려면 이를 사용하여 스크롤백 버퍼를 지울 수 있습니다. 이걸 보내뒤쪽에 \e[2J그렇지 않으면 한 화면의 데이터가 스크롤됩니다. (이것이 바로 이 clear명령이 하는 일입니다.)

그래서 제 질문은 \e[H\e[2JLinux 터미널처럼 렌더링하기 위해 최상위 명령(시퀀스)을 처리하는 정확한 단계(알고리즘)가 무엇입니까?

대답은 다음과 같습니다. 터미널에 따라 다릅니다.

답변2

하지만 Linux 터미널은 그렇지 않습니다(저는 XFce 터미널을 사용합니다). 어떻게든 화면의 일부를 지우고 페이지를 아래로 스크롤합니다.

실제로 echo -e "\033[H\033[2J"이는 여러분이 기대하는 것과 정확히 일치합니다. 왼쪽 상단으로 이동하여 화면 버퍼의 나머지 부분을 지웁니다.

아래로 스크롤하는 것은 화면 버퍼에 터미널보다 더 많은 줄이 있기 때문입니다.

stty size얼마나 많은 행과 열이 있는지 확인하세요 . 그것을 바꾸 십시오 stty rows X cols Y.

답변3

나는이 문제를 스스로 해결했다고 생각합니다. XFce 터미널 소스 코드에서 ANSI 이스케이프 코드에 대한 정보를 찾을 수 없습니다. ANSI 코드가 어디서 처리되는지 잘 모르겠습니다.

그러나 해결책은 다음 알고리즘입니다.

  1. 코드가 있는 경우 [H커서 위치를 저장합니다 .
  2. 코드 가 있고 [2J이전 코드가 H커서 위치로 복원되는 경우.
  3. 한 행 앞으로 이동하고 x를 0으로 이동합니다.
  4. y 위치를 scroll_top으로 저장합니다.
  5. 이제 코드를 작성할 때마다 [x;yHy [H커서 위치의 오프셋으로 scroll_top을 사용하십시오.

이는 많은 줄을 지워서 다음 줄이 화면 상단에 표시되므로 Linux 터미널보다 더 잘 작동합니다. macOS의 iTerm2에는 나와 비슷한 알고리즘이 있지만 1 1 위치가 터미널 창의 왼쪽 상단에 있도록 창만 스크롤합니다.

관련 정보