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 플래그가 없으면 기존에 길었던 라인 위에서 입력모드로 전환될 때 자동으로 행을 나누는 동작을 안하는 정도로만 작동하는 것 같네요.

Read more

워드프레스에서 고스트로 이전

워드프레스에서 고스트로 이전

이 글을 쓰면서도 믿기 힘든 사실인데, 블로그라는 걸 처음 시작한지가 20년이 되었습니다. 이글루스에서 처음 시작했다가, SK컴즈가 인수한다고 발표함과 동시에 워드프레스로 플랫폼을 옮겼죠. 워드프레스오 옮긴 이후에는 호스팅 환경을 이리 저리 옮기긴 했지만 거의 18년 가까이 워드프레스를 사용해온 것 같습니다. 그 동안 워드프레스는 블로깅 툴에서 명실상부한 범용CMS로 발전했습니다. 사실 웬만한 홈페이지들은 이제

By sooop
띄어쓰기에 대한 생각

띄어쓰기에 대한 생각

업무 메일을 쓸 때 가장 많이 쓰는 말 중에 하나가 메일 말미에 ‘업무에 참고 부탁 드립니다.‘인데요, 어느 날부터 아웃룩에서 이 ‘부탁 드립니다’가 틀렸다고 맞춤법 지적을 하기 시작했습니다. 맞는 말은 ‘부탁드립니다’라고 붙여 쓰는 거라고. 사실 아래아한글 시절부터 이전의 MS워드까지, 워드프로세서들의 한국어 맞춤법 검사 실력은 거의 있으나 마나 한

By sooop

구글 포토에서 아이클라우드로 탈출한 후기

한 때 구글 포토가 백업 용량을 무제한으로 제공해 주겠다고해서, 구글 포토를 사용해서 사진을 백업해왔습니다. 물론 이 이야기의 결말은 저나 이 글을 읽고 있는 여러분이나 모두 알고 있습니다. 사실 AI에게 학습 시킬 이미지 데이터를 모으기 위한 것일 뿐이라거나 하는 이야기는 그 당시에도 있었습니다만, 에이 그래도 구글인데 용량은 넉넉하게 주겠지…하는 순진한

By sooop

Julia의 함수 사용팁

연산자의 함수적 표기 Julia의 연산자는 기본적으로 함수이며, 함수 호출 표기와 같은 방식으로 호출하는 것이 가능합니다. 또한 그 자체로 함수이기 때문에 filter(), map() 과 같이 함수를 인자로 받는 함수에도 연산자를 그대로 적용하는 것이 가능합니다. 특히 + 연산자는 sum() 함수와 같이 여러 인자를 받아 인자들의 합을 구할 수 있습니다. 2 + 3 # = 5 +(2,

By sooop