[CSI Sequence] 커서 옮기기

CodeAbbrName
CSI # ACUUCUrsor Up
CSI # BCUDCUrsor Down
CSI # CCUFCUrsor Forward
CSI # DCUBCUrsor Backward
CSI # ECNLCUrsor Next Line
CSI # FCPLCUrsor Previous Line
CSI # ICHTCursor Horizontal forward Tabulation
CSI # ZCBTCursor Backward Tabulation
CSI # GCHACursor Horizontal Absolute
CSI # ; # HCUPCUrsor Position

오늘은 지난 글에 이어 이번 글에서는 CSI sequence를 이용해 커서를 옮기는 방법에 대해 알아보겠다. 커서를 옮기는 CSI sequence의 종류는 위와 같이 정리할 수 있다.

CUU, CUD, CUF, CUB

이들은 각각 CUrsor Up, CUrsor Down, CUrsor Forward, CUrsor Backward의 약자로 이름 그대로 커서를 위, 아래, 앞, 뒤로 이동한다. 인자로는 한 개의 숫자를 받고, 만약 인자가 생략되면 1로 취급된다. 즉, 0x1b[A0x1b[1A와 같은 의미이다.

이때 CUF나 CUB는 같은 줄 내에서만 움직이며 줄의 시작에서 CUB를 받아도 이전 줄로 움직이지 않고, 줄의 마지막에서 CUF를 받아도 다음 줄로 움직이지 않는다. 이런 동작을 원하면 각각 reverse auto-wrap 모드와 auto-wrap 모드를 켜야 하는데, 이 모드를 지원할지는 터미널별로 다르다.

CNL, CPL

이들은 각각 Cursor Next Line, Cursor Previous Line을 의미하며, 커서를 다음 줄 혹은 윗줄로 옮긴다. CUU와 CUD는 커서의 column을 유지한 채 줄을 바꾼다면, CNL과 CPL은 커서를 줄의 시작으로 옮긴다. 즉, CNL은 CR(\r, carriage return)과 CUD의 조합이고, CPL은 CR과 CUU의 조합과 같다. 이들 또한 인자로 하나의 숫자를 받으며, 인자를 넘기지 않은 경우 기본값은 1로 취급된다.

CHT, CBT

CHT는 Cursor Horizontal forward Tabulation의 약자이고, CBT는 Cursor Backward Tabulation의 약자다. 이들은 각각 다음 tab stop과 이전 tab stop으로 커서를 옮긴다.

CHA, CUP

위의 시퀀스들은 커서를 현재 위치에서 상대적인 위치로 움직인다. 하지만 CHA와 CUP는 입력받은 절대 좌표로 움직인다. 둘의 차이는 CHA는 하나의 숫자를 인자로 받아 현재 줄의 지정 된 칼럼으로 커서를 옮기고, CUP는 줄과 칼럼, 두 개의 숫자를 받아 커서를 지정된 좌표로 옮긴다는 것이다. 이때 숫자를 넘기지 않으면 기본값은 1로 처리된다.

프로그래밍에 익숙한 사람들은 어째서 기본값이 0이 아닌 1인지 궁금해할 것이다. 이는 터미널이 (0, 0)에서 시작하는 좌표계가 아닌 (1, 1)에서 시작하는 좌표계를 사용하기 때문이다. 즉, 터미널에서 좌상단의 좌표는 (1, 1)이다.

지금까지 CSI sequence를 이용해 커서를 옮기는 방법에 대해 알아보았다. 커서를 자유롭게 다루는 것은 TUI를 만드는 최소한의 빌딩 블록이다. 이를 응용하여 단순히 아래로 흘러 내려가는 출력 스트림 뿐 아니라, 다양한 화면을 터미널에 구현할 수 있다.

댓글

이 블로그의 인기 게시물

Escape Codes의 역사

RAII는 무엇인가

[C++] enum class - 안전하고 쓰기 쉬운 enum

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

[Python] cache 데코레이터로 최적화하기