Wireframe

vim에서 긴 행을 자동 줄바꿈하는 올바른 설정

세상에는 메모장을 위시로 하여 수 없이 많은 GUI 기반 텍스트 편집기가 있습니다. 그 중 가장 간단한 텍스트 편집기인 윈도 메모장에서도 “자동 줄 바꿈”이라는 옵션은 존재합니다. 메모장에도 있을 정도의 기능이면 줄바꿈 없이 긴 문장을 화면에서 읽으려고 할 때, 가장 필요한 기능이라고도 할 수 있겠습니다. 오늘은 vim에서 긴 행은 어떻게 처리되는지, 그리고 이런 ‘자동줄바꿈’과 관련된 옵션은 어떤 것들이 있고 어떻게 설정하면 좋을지에 대해 생각해 보도록 하겠습니다.

'wraps' 옵션을 켜면 창의 폭보다 긴 라인을 자동으로 창에서 꺾어서(?) 다음 줄로 밀어내어 표시합니다. 이 옵션이 바로 메모장의 ‘자동 줄바꿈’에 가장 근접하는 기능이라 할 수 있습니다. 그러면 모두가 행복해지는 것인가? 뭐 결론부터 말하면 약절반 정도는 해피해질 수 있다….고 하겠습니다. 우선 나머지 절반에 대한 이야기를 하기 전에, “페이지의 폭”과 관련된 내용을 조금 살펴보겠습니다.

왜 굳이 이런 이야기를 꺼내냐하면, 우리는 사람들이 공개해 놓은 자신의 vimrc 파일을 종종 엿볼 기회가 생기기 때문입니다. 당장 그 설정 파일 내 옵션 중에서 어떤 내용인지 정확히 알지는 못해도, 대략의 단어만 보고 ‘아 이건 대충 이런 효과겠군’하고 내 설정 파일에도 그 부분을 쉽게 추가할지도 모르겠습니다. 그리고 그런 일을 반복하다보면, 내 vim이 이상하게 작동하고 있었다는 사실을 알게 되는 날이 올 때도 있습니다. 이번에 소개하는 옵션이 딱 그런 놈입니다.

‘textwidth’, ‘tw’

'textwidth' 옵션은 버퍼에서 텍스트의 최대 폭을 지정합니다. 이를 간단히 생각하면 긴 줄이 자동으로 줄바꿈되어 표시되는 한계값이라 생각하기 쉬운데, 실제로는 이 옵션은 그렇게 작동하지 않습니다. 보통 텍스트 문서를 작성하는 와중에 이런 옵션을 필요로 하는 경우는 잘 없을 것 같습니다. 하지만 “프로그램 소스 코드의 한 줄은 80자를 넘기지 않는 것이 좋다”는 격언에 익숙한 프로그래머라면,창의 크기에 상관없이 80자를 넘는 라인이 자동으로 줄바꿈 되어 보인다면 왠지 깔끔한 느낌일 것 같고 그런 기분이 들지도 모릅니다.

그런데 사실 이 옵션을 설정해놓으면, 편집 모드에서 텍스트를 입력하는 중에 입력하던 내용이 'textwidth'의 값보다 길어지면 자동으로 개행이 되면서 줄이 나눠집니다. (실제로 이 동작은 또다른 vim 옵션인 'formatoptions' 의 설정에 따라서도 달라질 수 있습니다. 그 외에도 영향을 주는 다른 옵션이 있는지 적용되는 양상도 도움말에서 설명하는 것과 살짝 다른 거 같아요)및 소스 코드를 작성하던 중에 라인이 부득이하게 길어지는데 이 설정이 켜져 있다면 재수가 없으면, 의도하지 않는 곳에서 개행이 일어나고, 공교롭게도 그 위치가 올바른 line continuation이 아나라면 문법 오류를 만나게 됩니다. 따라서 정말 특정한 길이보다 행이 길어지지 않아야 하는 특별한 경우를 제외하고 이 옵션의 값은 0이어야 합니다.

실제로 vim은 'wrap' 옵션을 켜면 긴 행을 여러 줄로 wrapping 하여 표시해줍니다. 이 때 몇 글자나 표시하고 다음 줄로 넘어갈지는 순전히 창의 크기가 결정합니다. 이와 관련된 추가적인 옵션으로는 wrapmargin 이 있습니다. 이 값은 디폴트가 0인데, 버퍼를 표시하는 창이 오른쪽 경계로부터 몇 자나 떨어진 지점에서 넘치는 내용을 다음 줄로 밀어서 표시할 것인지를 결정합니다.

그렇다고 textwidth 옵션이 아예 쓸모가 없는 것은 아닙니다. 적어도 이 옵션은 vim 도움말을 작성할 때 유용하게 사용되는 것 같습니다. 아래 스크린샷은 vim의 도움말 내용을 복사하여 일반 버퍼에 붙여넣은 모양입니다. 본문은 앞의 탭을 제외하면 한 라인이 정확하게 70자 길이 제한을 가지고 있습니다. (오른쪽에 빨갛게 표시한 것은 78번째 칸입니다.)

탭, 개행 등의 부호는 ‘set list’ 설정을 사용하여 표시할 수 있고, 각 부호는 ‘listchar’ 옵션에서 설정합니다.

몇 개의 줄을 합쳐서 두 문단으로 정리해보면 아래와 같이 보입니다.

vim에서 textwidth=0 wraps list nu 의 옵션을 설정한 상태입니다. 4번 행의 내용이 매우 길어지면서 자동으로 여러 줄에 걸쳐 표시되고 있습니다. 이는 5번 행도 마찬가지입니다. 이것이 딱 우리가 원했던 바로 그 느낌입니다. 그런데 이렇게 표시될 때, 기본 vim 설정에서는 긴 행을 포함한 문서를 읽기는 편하지만, 커서 이동이 조금 애매해집니다.

wrap 사용시 커서 이동의 문제

만약 현재 커서 위치가 4행의 맨 앞 ‘N’자에 위치하는 상황에서 j 키를 눌러서 아래로 내려간다면 어떻게 될까요? j 키는 ‘다음 행으로’ 이동하는 명령입니다. 따라서 N의 다음 행에서 첫번째 글자인 5행의 ‘T’로 바로 이동하게 됩니다. 즉, 눈으로 볼 때 4개의 줄을 한 번에 건너뛰는 것처럼 보입니다. (물론 실제로는 한 줄만 아래로 내려간 것이 맞습니다.) 만약 화면에서 보이는 ‘T’ 바로 아래에 있는 ‘beyond’의 ‘b’로 커서를 이동하고 싶다면, 사용자는 w 를 열심히 눌러서 “옆으로” 이동해야 합니다.

wrap이 적용된 라인이 화면에 있을 때, 커서를 화면 기준으로 아래로 한 칸씩 이동하는 명령은 따로 존재하며, 노멀모드 명령 gj, gk가 그것입니다. 따라서 긴 행을 자동으로 화면에 표시하되, GUI 앱처럼 커서는 화면 기준으로 이동하고 싶다면, 우리의 j, k 키는 gj, gk 와 같이 작동해야 합니다. 따라서 아래와 같은 세팅을 해두는 것이 필요합니다.

set wrap textwidth=0
nnoremap j gj
nnoremap k gk
nnoremap gj j
nnoremap gk k

formatoptions

개행이나 들여쓰기, 주석 기호 등과 관련된, 입력 및 편집 시 텍스트의 포맷팅과 관련한 설정은 'formatoptions'라는 옵션에 관계되는 것들이 있습니다. 앞에서 설명했던 내용들 중에는 이 옵션이 관련되면서 사실이 아니게 되는 것이 있습니다. 예를 들어, 이 옵션에 들어갈 수 있는 문자 중에 "t" 플래그가 바로 textwidth 보다 큰 라인에 대해 “auto wrap”을 적용하게 하는 옵션입니다. (vim 도움말에도 “auto-wrap” 이라고 표현되어 있지만, 실제로는 “break line” 입니다.) 따라서 이 옵션의 값에서 t 를 제거하면 textwidth 의 값이 0이 아니어도 해당 길이를 초과하는 라인이 강제로 개행되어 새로운 행으로 분리되지 않는다고 합니다. 하지만 제가 시험해본 결과, 이 옵션과 무관하게 textwidth 옵션이 0이 아닌 값으로 설정되어 있으면 무조건 개행은 일어나는 것 같습니다. 최소한 t 플래그가 없으면 기존에 길었던 라인 위에서 입력모드로 전환될 때 자동으로 행을 나누는 동작을 안하는 정도로만 작동하는 것 같네요.

Exit mobile version