Practical Vim 2판 정리 페이지

16 Nov 2016

  1. Use Vim’s Factory Settings
  2. 1. The Vim Way
    1. Tip 1. Dot Command
    2. Tip 2. Don’t Repeat Yourself
    3. Tip 3. Take One Step Back, Then Three Forward
      1. Make the Motion Repeatable
    4. Tip 4. Act, Repeat, Reverse
    5. Tip 5. Find and Replace by Hand
    6. Tip 6. Meet Dot formular
      1. 이상적 해결책: 한 키로 이동, 한 키로 실행
  3. Part 1. Modes
  4. Chapter 2. Normal Mode(일반 모드)
    1. Tip 7. Pause with Your Brush Off the Page
    2. Tip 8. Chunk Your Undos
      1. 입력 모드에서 이동하면 변경이 재설정된다.
    3. Tip 9. Compose Repeatable Changes
    4. Tip 10. Use Counts to Do Simple Arithmetic
      1. 숫자 포맷
    5. Tip 11. Don’t Count If You Can Repeat
    6. Tip 12. Combine and Conquer
      1. Extending Vim’s Combinatorial Powers
        1. Custom Operators Work with Existing Motions
        2. Custom Motions Work with Existing Operators
        3. Meet Operator-Pending Mode
  5. Chapter 3. Insert Mode(입력 모드)
    1. Tip 13. Make Corrections Instantly from Insert Mode
    2. Tip 14. Get Back to Normal Mode
      1. Meet Insert Normal Mode
    3. Tip 15. Paste from a Register Without Leaving Insert Mode
      1. Remap the Caps Lock Key
      2. Use {register} for Character-wise Registers
    4. Tip 16. Do Back-of-the-Envelope Calculations in Place
    5. Tip 17. Insert Unusual Characters by Character Code
    6. Tip 18. Insert Unusual Characters by Digraph
    7. Tip 19. Overwrite Existing Text with Replace Mode
      1. Overwrite Tab Characters with Virtual Replace Mode
  6. Chapter 4. Visual Mode
    1. Tip 20. Grok Visual Mode
      1. Meet Select Mode
    2. Tip 21. Define a Visual Selection
      1. Enabling Visual Modes
      2. Switching Between Visual Modes
      3. Toggling the Free End of a Selection
        1. Preparation
        2. Indent Once, Then Repeat
    3. Tip 23. Prefer Operators to Visual Commands Where Possible
      1. Using a Visual Operator
      2. Using a Normal Operator
      3. Discussion
    4. Tip 24. Edit Tabular Data with Visual-Block Mode
    5. Tip 25. Change Columns of Text
    6. Tip 26. Append After a Ragged Visual Block
      1. “i”와 “a” 사용법
  7. Chapter 5. Command-Line Mode
    1. Tip 27. Meet Vim’s Command Line
      1. On the Etymology of Vim (and Family)
      2. Special Keys in Vim’s Command-Line Mode
      3. Ex Commands Strike Far and Wide
    2. Tip 28. Execute a Command on One or More Consecutive Lines
      1. Use Line Numbers as an Address
      2. Specify a Range of Lines by Address
      3. Specify a Range of Lines by Visual Selection
      4. Specify a Range of Lines by Patterns
      5. Modify an Address Using an Offset
  8. Part II. Files
  9. Chapter 6. Manage Multiple Files
    1. Tip 37. Track Open Files with the Buffer List
      1. Understand the Distinction Between Files and Buffers
      2. Meet the Buffer List
      3. Use the Buffer List
      4. Deleting Buffers
      5. Group Buffers into a Collection with the Argument List
      6. Populate the Argument List
      7. Use the Argument List
  10. Part III. Getting Around Faster
  11. CHAPTER 8. Navigae Inside Files with Motions
    1. Tip 47. Keep Your Fingers on the Home Row
      1. Leave Your Right Hand Where It Belongs
    2. Tip 48. Distinguish Between Real Lines and Display Lines
      1. Remap Line Motion Commands
    3. Tip 49. Move Word-Wise
      1. Know Your Words from Your WORDS
    4. Tip 50. Find by Character
      1. Don’t Throw Away the Reverse Character Search Command
      2. Character Searches Can Include or Exclude the Target
      3. Think Like a Scrabble® Player
  12. CHAPTER 9.Navigate Between Files with Jumps
    1. Tip 56. Traverse the Jump List
      1. Beware of Mapping the Tab Key
    2. Tip 57. Traverse the Change List
      1. Marks for the Last Change
  13. CHAPTER 18. Search Project-Wide with grep, vimgrep, and Others
    1. Tip 109. Call grep Without Leaving Vim
      1. Using grep from the Command Line
      2. Calling grep from Inside Vim
    2. Tip 110. Customize the grep Program
      1. Vim’s Default grep Settings
      2. Make :grep Call ack
      3. Alternative grep Plugins
      4. Make ack Jump to Line and Column
    3. Tip 111. Grep with Vim’s Internal Search Engine
      1. Specifying Which Files to Look Inside
      2. Search in File, Then Search in Project
      3. Search History and :vimgrep
  14. APPENDIX 1. Customize Vim to Suit Your Preferences
    1. Change Vim’s Settings on the Fly
      1. Save Your Configuration in a vimrc File
      2. Apply Customizations to Certain Types of Files
  • iBooks로 읽는 프랙티컬 Vim 2판을 정리하는 페이지이며 내편한대로 발췌하고 보충하기 때문에 원본을 반드시 참조하세요.
  • Vim은 다른 텍스트 에디터와 다르게 여러 모드를 가진다. Normal/Insert/Visual Mode의 세 가지가 주요 모드인데, 번역이 일관성이 없다. 대체로 Normal Mode는 일반/명령 모드, Insert Mode는 입력/편집 모드, Visual Mode는 비주얼/선택 모드, 일반 모드에서 :로 진입하는 모드는 명령행/ex/명령어 모드 등으로 번역되는데, 이 글에서는 앞의 굵은 글씨의 모드로 사용한다.

Use Vim’s Factory Settings

-u NONE로 환경설정 없이 실행하면 vi 호환 모드로 실행되니, -Nnocompatible 모드로 실행.

$ vim -u NONE -N

Vim 빌트인 플러그인을 요구할 때는

set nocompatible
filetype plugin on

essential.vim에 입력한 후:

$ vim -u essential.vim

로 실행한다. netrw, 옴니 완성 등을 실행할 수 있다.

:version으로 설치된 Vim의 버전과 컴파일 설정을 볼 수 있다.

  • [ ] :version 으로 보니 -hangul_input이 포함되지 않고 컴파일되었네??

1. The Vim Way

우리 일은 본래 반복적이다. Vim은 반복 작업에 최적이다. Vim의 효율성은 가장 최근 작업을 추적하는 방법에서 유래한다. 작업 단위를 잘 고려하면 하나의 키로 반복할 수 있다. 이 개념에 숙달하는 것이 Vim을 효과적으로 사용하는 비결이다.

. 명령은 시작이다.

Tip 1. Dot Command

. 명령은 가장 최근의 변경을 반복한다.(+) Vim에서 가장 강력하고 만능인 명령어이다. Vim의 모달 편집 모드의 핵심을 알 수 있다.

Why, oh WHY, do those #?@! nutheads use vi?

Vim을 올바르게 쓰려면 모달하게 쓰지 말고, 항상 일반 모드에 있어야 한다. 입력 모드에서는 텍스트만 입력하고, 입력하고 난 후에는 Esc로 일반 모드로 돌아와야한다. 그래서, 모드를 기억해야 하는 문제는 없다: 텍스트를 입력하는 중 전화가 온다면 입력 모드를 나가고 전화를 받아야 한다. 그렇지 않으면 Vim으로 돌아올 때 Esc를 누르도록 한다.

좋은 장점은 . 명령이 가장 최근의 완료된, 이어진 편집 명령(커서 이동은 제외)을 반복한다는 것이다. 일반 모드에서 iHello<Esc>를 입력한 후 Dot 명령은 커서의 위치에 ‘Hello’를 입력한다.

  • x.으로 반복하고 u로 undo한다.
  • dd로 현재 줄을 지우고, x로 반복한다.
  • >G로 현재 줄을 들여쓰고, j로 이동한 후 .j(=>Gj)로 반복한다.

Dot 명령은 마이크로 매크로이다.

Tip 2. Don’t Repeat Yourself

  • 소스 코드는 여기에서 내려받을 수 있다.

the_vim_way/2_foo_bar.js의 줄 끝에 ;를 추가할 때, $로 첫줄의 끝으로 이동한 후 a;;을 추가한다. j$로 다음 줄의 끝으로 이동한 후 .(=a;), 다시 j$로 다음 줄로 이동, .을 입력한다.

A$a와 같다. Vim에는 여러 복합 명령(둘 또는 그 이상의 명령을 하나로 압축한 명령)이 있다. 아래 표에 몇 개의 보기를 모았다.

복합 명령 동일 명령
C c$
s cl
S ^C
I ^i
A $a
o A
O ko

ko(더 나쁘게는 k$a<CR>)보다는 O 명령을 대신 사용한다.

위의 명령은 모두 일반 모드에서 입력 모드로 전환한다. dot 명령에 어떻게 영향을 미칠지 생각하라.

이제 이전 보기를 세련되게 해본다. A;<Esc>로 첫줄 끝에 ;를 추가한다. 두번의 j.로 끝낸다.

Tip 3. Take One Step Back, Then Three Forward

the_vim_way/3_concat.js

var foo = "method("+argument1+","+argument2+")";

var foo = "method(" + argument1 + "," + argument2 + ")";

처럼 만들어 본다. 줄의 처음에서 f+로 이동하여 s로 커서 밑의 글자를 지우고 입력 모드로 들어간다. ` + 를 입력하고 `로 일반 모드로. 한 보 뒤로 세 보 앞으로. 직관적이진 않지만 `.` 명령으로 반복할 수 있다. `;`로 다음 `+`로 이동하고 `.`로 계속 반복하여 끝낸다.

; Repeat latest f, t, F or T [count] times :browse old 최근 편집한 파일 목록을 보고, 선택하여 연다.

Make the Motion Repeatable

다른 트릭이 있다. f{char} 명령은 다음 특정 문자로 커서를 이동한다. f+는 다음 +로 이동한다. ; 명령은 f 명령이 수행한 마지막 검색을 반복한다. f+를 네번 반복하지 않고 한번만 실행하고;를 세번 사용했다.

;이 다음 대상으로 이동하고, .로 최근 변경을 반복한다. 세 번의 ;.로 완료한다.

Vim의 모달 입력 모델과 싸우지말고, 같이 작업하면서 일을 더 쉽게 만드는 법을 보라.

Tip 4. Act, Repeat, Reverse

반복적인 일을 마주하면 이동과 변경을 반복적으로 만들어 최적의 편집 전략을 수행할 수 있다. Vim은 비결을 갖고 있다.

Table 1. Repeatable Actions and How to Reverse Them

Intent Act Repeat Reverse
Make a change {edit} . u
Scan line for next character f{char}/t{char} ; ,
Scan line for previous character F{char}/T{char} ; ,
Scan document for next match /pattern n N
Scan document for previous match ?pattern n N
Perform substitution :s/target/replacement & u
Execute a sequence of changes qx{changes}q @x u

. 명령이 마지막 변경을 반복한다는 것을 알았다. 몇 명령은 다른 방법으로 반복할 수 있다. 예로, @:는 Ex 명령을 반복하고, &는 마지막 :substitute를 반복할 수 있다.

한번 실행하고 반복한다.

. 명령의 경우 u 키로 마지막 변경을 되돌릴 수 있다. F{char} 명령을 사용한 후 ; 키를 너무 많이 누른 경우엔 ,로 되돌릴 수 있다. ,은 반대 방향으로 f{char} 검색을 반복한다.

Tip 5. Find and Replace by Hand

the_vim_way/1_copy_content.txt의 내용에 “content”란 단어가 줄마다 있다. “content” 대신 “copy”를 사용하기 원하면 substitut 명령을 사용할 수 있다:

:%s/content/copy/g

이것은 세 개의 “content”를 “copy”로 모두 변경한다. 그러나 두 번째 “content”는 만족하는 이라는 동철 이음 이의어heteronym이다.

* 명령은 커서 밑의 단어를 찾는다. /content로 “content”를 검색할 수도 있다.

두 번째 “content” 단어에 커서를 놓고 *로 세 번째 “content”로 이동한 후 cwcopy를 실행하여 "content"를 "copy"로 변경한다. `*`로 첫 번째 "content"로 이동한 후에 `.` 명령을 실행한다.

:set hls로 검색 하일라이트를 해보라.

“content”를 한번 검색한 후에는 n 키로 다음 검색을 진행할 수 있다. 이 경우에는 *nn으로 모든 경우를 순환한다.

cw 명령은 단어를 지우고 입력 모드로 바꾼다. “copy”를 입력하면 Vim은 입력 모드를 벗어나기 전까지를 기록한다. cwcopy가 하나의 변경이다. `.` 명령을 누르면 커서 밑의 단어를 지우고 "copy"를 입력하게 된다.

n.n.n.:%s/content/copy/g와 같다. 그래서 원하는 경우에만 .을 사용한다.

Tip 6. Meet Dot formular

이상적 해결책: 한 키로 이동, 한 키로 실행

이런 이상적 패턴을 편의상 Dot Fomular라고 말하겠다.

Part 1. Modes

Vim은 모달 유저 인터페이스를 제공한다. 키보드의 키를 누른 결과가 현재 어떤 모드인지에 따라 다르다는 것을 뜻한다. 어떤 모드인지와 Vim 모드 사이를 전환하는 방법을 아는 것이 필수다.

Chapter 2. Normal Mode(일반 모드)

일반 모드는 Vim의 휴식 상태다. 이 책의 대부분이 일반 모드를 사용하는 법에 대한 것이기 때문에 이 장은 아주 짧고, 핵심 개념과 일반 팁만 다룬다.

다른 텍스트 에디터는 입력 모드 비슷한 것에서 대부분의 시간을 보낸다. 그래서 Vim 입문자는 일반 모드가 기본인 것이 낯설다. 팁 7에서 화사의 작업 공간과의 유사한지를 설명한다.

많은 일반 모드 명령은 여러 번 실행하라는 횟수와 함께 사용된다. 팁 10에서 증가/감소 숫자값 명령과 이 명령들이 횟수와 결합할 수 있다는 것을 알게 된다.

일반 모드의 강력함은 동작 명령이 motion과 결합할 수 있다는 것에서 온다.

Tip 7. Pause with Your Brush Off the Page

화가가 페인트 붓을 캔버스와 얼마나 많이 접촉하는 생각해 본 적이 있나? 작업에 쓰는 시간의 반을 사용한다.

화가가 그리기 외에 하는 모든 것을 생각해보라. 주제를 연구하고, 빛을 조절하고, 새로운 색조의 물감을 섞는다. 물감을 캔버스에 적용할 때 붓을 사용해야 한다고 누가 그러는가? 화가는 다른 질감을 위해 팔레트 칼을 바꾸고, 이미 걱용된 물감을 덧붙이기 위해 면 안감을 사용할 수도 있다.

화가는 캔버스에 대어놓고 붓을 쉬지 않는다.

Vim에서도 그렇다. 일반 모드는 자연적인 휴식 상태다. 단서는 그 이름에 있다, 정말로.

화가가 그리기에 시간의 일부를 쓰듯이 프로그래머도 코드 작성에 시간의 일부를 쓴다. 생각하고, 일고, 코드베이스 한 부분에서 다른 부분으로 옮기는 것에 시간을 더 쓴다. 누가 입력 모드로 바꿔야 한다고 하는가? 우리는 기존 코드를 재포맷하고 복사하고 이동하거나 지운다. 일반 모드에서 마음대로 사용할 수 있는 도구가 많이 있다.

Tip 8. Chunk Your Undos

다른 텍스트 에디터에서는 몇 단어를 입력한 후 undo 명령으로 마지막 입력한 단어 혹은 문자를 되돌린다. 그러나, Vim에서는 undo 명령의 덩어리를 조절할 수 있다.

u 키는 가장 최근 변경을 되돌린다. 단일 변경은 문서에 문자를 변경한 것이다. 일반, 비주얼, 명령행 모드에서 실행한 명령을 포함한다. 그러나, 입력 모드에서 입력하거나 지운 텍스트도 포함할 수 있다. i{문자 입력}<Esc>는 단일 변경이 될 수 있다.

Vim에서는 undo 명령의 덩어리를 조절할 수 있습니다. 입력 모드로 들어가는 순간부터 일반 모드로 돌아갈 때까지 입력 (또는 삭제)한 모든 것이 단일 변경이다. 따라서 <Esc> 키 사용을 조절하여 undo 명령을 단어, 문장 또는 단락에 적용할 수 있다.

얼마나 자주 입력 모드를 떠나는가? 선호의 문제이지만, 나는 각각의 “되돌릴 덩어리”를 생각과 일치시키려고 한다. 이 텍스트를 쓰면서 (물론 Vim에서!), 나는 문장의 끝에 잠시 멈추고 다음에 쓸 내용을 생각한다. 시간이 아무리 짧아도 각 멈춤은 자연스러운 중단점을 만들고 입력 모드를 떠나는 단서를 준다. 글 쓸 준비가되면, 나는 A를 누르고 내가 중단 한 곳에서 계속한다.

잘못되었다고 생각되면, 일반 모드로 전환하고 u를 누릅니다. undo할 때마다 원본 텍스트를 쓰면서 생각대로 내 텍스트를 일관된 덩어리로 분해한다. 즉, 한 두 문장을 쉽게 쓰고 두개의 키 입력으로 버릴 수 있다.

입력 모드에서 커서가 줄 끝 부분에 있는 경우 새 줄을 여는 가장 빠른 방법은 <CR>을 누르는 것이다. 때로는 undo 명령에서 추가 세분화를 원할 것으로 기대하기 때문에 <Esc>o를 누르기를 선호한다. 어려울 수 있지만 Vim에 익숙해지면 모드 전환이 점점 더 가볍게 느껴진다.

입력 모드에서 이동하면 변경이 재설정된다.

undo 명령이 입력 모드로 들어가고 나오는 동안 입력한 (또는 지운) 모든 문자를 되돌릴 수 있다고 말했다. 입력 모드에서 <Up>, <Down>, <Left>, <Right> 커서 키를 사용하면 새로운 undo 덩어리가 만들어 진다. 입력 모드를 벗어나지 않는다는 것을 제외하고는 h, j, k, l 명령으로 이동하려고 일반 모드로 다시 전환한 것과 같다. 이것은 dot 명령에도 영향을 미친다.

Tip 9. Compose Repeatable Changes

Vim은 반복작업에 최적이다. 이것을 이용하려면 변경을 구성하는 방법을 마음에 새겨야 한다.

Vim에서 어떤 것을 하는 방법이 하나 이상 있다. 어떤 방식이 최고인지를 평가할 때 가장 확실한 척도는 효율성이다: 가장 적은 키 작업(VimGolf)이 필요하다.

“nigh”라는 단어의 “h”에 커서가 있다면:

db는 단어의 시작까지 지운다. x는 커서 밑의 한 글자를 지운다.

b 모션은 커서를 단어의 처음으로 움직인다. dw는 단어를 지운다.

모션 대신 aw 텍스트 개체를 사용할 수 있다. daw는 _delete a word_로 쉽게 기억할 수 있다. 단어만 지우는 것이 아닌 여백 문자까지 지운다. dot 명령을 사용하여 (. == daw) 유용하게 반복할 수 있다. 그래서 이 방법이 승자다.

Tip 10. Use Counts to Do Simple Arithmetic

여기서부터는 인사이트에서 Practical Vim 번역본의 리뷰를 부탁받았습니다. 그래서 며칠 동안 독서를 멈추었지만 12일까지 완료해야 하므로, 앞으로의 진행은 더 빨라지게 되었습니다. 원본과 3차 리뷰 번역본을 동시에 읽으면서 요약합니다

대부분의 일반 모드 명령는 횟수를 앞에 붙일 수 있다. 그 횟수만큼 반복실행한다.

커서 밑에 있는 숫자를 명령으로 증가시키거나 명령으로 감소시킬 수 있다. 숫자를 앞에 붙이면 그 수만큼 증감한다. 5 문자에 커서를 놓고 10를 실행하면 15로 증가한다.

커서 밑이 숫자가 아닐 때는 이후에 있는 숫자로 이동해 앞에 입력한 [숫자]만큼 증감한다.

normal_mode/sprite.css의 마지막 줄에서 yyp로 줄을 복사하고, 180<C-x>로 숫자로 이동해 -180px로 번경한다.

숫자 포맷

0이 앞에 있는 숫자는 8진수로 해석하기 때문에 007+001 = 010이다. :set nrformats=하면 십진수로 해석한다.

Tip 11. Don’t Count If You Can Repeat

횟수를 지정하여 키를 최소로 할 수 있지만, 반드시 해야 하는 것은 아니다.

두 단어를 지울 때 d2w2dw가 유용하다. d2w는 삭제한 후 모션으로 2w를 주었다. “delete two words.”로 읽을 수 있다. 2dw는 삭제 명령에 횟수가 적용되었으며, 모션은 한 단어에서 실행된다. “delete a word two times.”로 읽을 수 있다. 의미를 다르지만, 결과는 같다.

dw.는 “Delete a word and then repeat.”로 읽을 수 있다.

7 단어를 지울 때 d7wdw......(dw.로 6회 반복)은 키 입력 수로 보면 확실한 승자를 알 수 있다. 숫자를 세는 것은 지루하다. 눌러야 하는 키의 숫자를 줄이기 위해 미리 헤아리기보다 . 명령을 6번 입력하는 것을 선호한다.

Tip 12. Combine and Conquer

Vim의 강력함은 오퍼레이터와 모션을 조합하는 방법에서 나온다.

Operator + Motion = Action

d{motion}에서 지우는 범위는 모션이 정한다. dl는 한 문자, daw는 한 단어, dap는 한 문단을 지운다. c{motion}, y{motion}도 같다. 이런 명령을 오퍼레이터라 한다. :h operator로 전체 목록을 찾아볼 수 있다.

g~, gu, gU는 두 번의 키 입력으로 실행한다. g는 다음 키의 행동을 수정하는 접두어로 생각할 수 있다.

오퍼레이터와 모션의 조합은 일종의 문법이다. 첫 규칙은 간단하다: 행동action은 오퍼레이터와 뒤따르는 모션의 조합이다.

Trigger Effect
c Change
d Delete
y Yank into register
g~ Swap case
gu Make lowercase
gU Make uppercase
> Shift right
< Shift left
= Autoindent
! Filter {motion} lines through an external program

Table 2. Vim Operator Commands

gUaw는 현재 단어를 대문자로 만든다. gUap는 문단을 대문자로 만든다.

Vim 문법은 하나의 규칙이 더 있다: 오퍼레이터 명령을 반복하면 현재 줄에 동작한다. dd는 현재 줄을 지우고, >>는 줄을 들여쓴다. gUgUgU, 줄여서 gUU로 할 수 있다.

Extending Vim’s Combinatorial Powers

자신의 모션과 오퍼레이터로 더 확장할 수 있다.

Custom Operators Work with Existing Motions

표준 오퍼레이터를 새롭게 정의할 수 있다. commentary.vim이 좋은 예이다. 모든 언어에서 코드를 주석으로 만들거나 주석을 해제하는 명령을 더한다.

gc{motion} 명령으로 주석을 토글한다. 오퍼레이터이므로, 모든 일반 모션과 조합할 수 있다. gcap로 현재 문단을 주석을 토글한다. gcG는 현재 줄부터 파일 끝까지 주석을 토글한다. gcc는 현재 줄을 주석처리한다. 커스텀 오퍼레이터는 :h :map-operrator를 참조한다.

Custom Motions Work with Existing Operators

Kana Natsuno의 textobj-entire 플러그인이 좋은 예이다. 두 개의 새로운 텍스개체를 더한다: 전체 파일에 동작하는 ieae

= 명령으로 전체 파일을 들여쓰기하려면 gg=G(gg로 파일 처음으로 이동하고 =G로 파일 끝까지를 들여쓴다). 이 플러그인을 설치하면 =ae로 간단히 동작한다.

두 플러그인을 모두 설치하면 gcae로 파일 전체를 주석처리하거나 토글할 수 있다.

커스텀 모션을 만들고 싶다면 :h omap-info를 읽어라.

Meet Operator-Pending Mode

Operator-Pending 모드는 간과하기 쉬운 모드 중 하나이다. 하루에 여러 번 사용하지만, 짧게 지속되기 때문이다. 예로 dw에서 dw 키를 누르는 사이의 짧은 순간이다. Operator-Pending 모드는 모션 명령만 받은 상태이다. 를 눌러 취소할 수 있다.

:h g, :h z, :h ctrl-w, :h [에서 처음 입력은 두 번째 입력의 접두어와 같이 행동한다. 이 명령은 Operator-Pending 모드를 초기화하지 않는다. 여러 명령을 모은 namespace라고 생각할 수 있다. 오퍼레이터 명령만 Operator-Pending 모드를 초기화한다.

이렇게 짧은 모드를 둔 이유가 궁금할 수 있다. Operator-Pending 모드를 초기화하거나 전환하는 커스텀 매핑을 만들 수 있기 때문이다. 이로써 커스텀 오퍼레이터와 모션을 만들어 Vim의 어휘를 확장할 수 있다.

Chapter 3. Insert Mode(입력 모드)

입력 모드에서 레지스터 내용을 붙여넣을 수 있는 단축키, 특수 기호를 입력하는 방법, 바꾸기 모드, 입력-일반 모드라는 서브 모드를 배운다.

Tip 13. Make Corrections Instantly from Insert Mode

입력 모드에서 백스페이스 키는 예상대로 커서 앞에 있는 한 문자를 제거한다. 아래 명령을 사용할 수도 있다.

Keystrokes Effect
Delete back one character (backspace)
Delete back one word
Delete back to start of line

이 명령은 입력 모드나 Vim에만 힌정된 것이 아니다. Vim의 명령행은 물론 bash 셸에서도 사용할 수 있다.

Tip 14. Get Back to Normal Mode

일반 모드로 돌아가는 표준 방법은 <Esc> 키다. 많은 키보드에서 멀리 있어서, 정확히 같은 기능인 C-[를 누를 수 있다.

Keystrokes Effect
Switch to Normal mode
<C-[> Switch to Normal mode
Switch to Insert Normal mode

Meet Insert Normal Mode

입력-일반 모드는 일반 모드의 특별판이며, 총알 하나만 주는 것이다. 즉, 명령 하나만 발사하고 바로 입력 모드로 돌아온다.

입력 중인 행이 창의 상단 또는 하단에 있을 때 추가 맥락을 보기위해 화면을 스크롤하고 싶을 때 <C-o>zz를 자주 사용한다. 입력 모드로 바로 돌아와 끊김없이 타이핑을 계속할 수 있다.

Tip 15. Paste from a Register Without Leaving Insert Mode

insert_mode/practical-vim.txt에서 마지막 줄에 첫 줄의 내용을 복사한 후 붙여넣는다. yt,로 첫 줄의 “,”전까지를 복사하고, jA 로 이동하고, <C-r>0로 레지스터 0의 내용을 붙여넣는다. .<Esc>로 마미표를 찍고 일반 모드로 돌아온다.

Remap the Caps Lock Key

Vim 사용자에게 Caps Lock은 골치거리다. Caps Lock이 켜져 있으면 k, j로 이동하려면 K, J 명령으로 동작한다. K는 커서 밑의 단어를 매뉴얼에서 찾아주고(:h K), J는 현재 행과 다음 행을 하나로 합친다(:h J). Caps Lock 키를 실수로 키면 버퍼에 있는 문서가 순식간에 엉망이 된다.

많은 사용자들이 Caps Lock 키를 <Esc><Ctrl>로 재설정한다.

Use {register} for Character-wise Registers

C-r>{register} 명령은 입력 모드에서 몇 단어를 붙여넣을 때 편리하다. 레지스터 내용이 많으면, 화면 갱신 전 약간 지연이 있을 수 있다. Vim이 레지스터로부터 한 번에 한 글자씩 삽입하기 때문이다. ‘textwidth’나 ‘autoindent’가 켜져있으면, 원하지않는 개행이나 불필요한 들여쓰기가 추가될 수 있다.

<C-r><C-p>{register} 명령이 더 똑똑하다(:h i_CTRL-R_CTRL-P 참고). 여러 줄의 내용이 있는 레지스터를 붙여넣는다면 일반 모드로 전환하고 put 명령을 사용한다.

Tip 16. Do Back-of-the-Envelope Calculations in Place

표현식exporession 레지스터로 계산을 하고 그 결과를 문서에 바로 입력할 수 있다.

대부분의 Vim 레지스터는 문자열이나 행 전체 내용을 포함한다. 삭제나 복사를 하면 레지스터에 저장된다. 붙여넣기는 레지스터 내요을 가져와 본문에 입력한다.

표현식 레지스터는 다르다. Vim 스크립트 코드를 실행하고 그 결과를 돌려준다. 계산기처럼 사용할 수 있다. 1+1과 같은 간단한 산술 표현식을 전달하면 2라는 결과가 나온다. 표현식 레지스터에서 받은 값을 일반 레지스터에 저장된 내용처럼 사용할 수 있다.

표현식 레지스터는 = 기호로 참조한다. 입력 모드에서 <C-r>=로 접근할 수 있다. 계산하길 원하는 표현식을 입력할 수 있는 프롬프트가 화면 하단에 열린다. 입력을 끝내고 <CR>을 누르면 Vim이 현재 위치에 결과를 입력한다.

insert_mode/back-of-envelope.txt에서 A로 줄의 끝에서 입력 모드로 전환하고, <C-r>=6*35<CR>로 결과값을 입력한다.

Tip 17. Insert Unusual Characters by Character Code

숫자 코드로 어떤 문자라도 입력할 수 있다. 입력 모드에서 <C-v>{code}만 입력하면 된다. 숫자 코드는 3개의 숫자이다. “A”의 문자 코드는 65이며, <C-v>065를 입력하면 된다.

유니코드 기본 다국어 목록은 65,535 문자까지 사용할 수 있는데, 세 자리보다 큰 문자는 4자리의 16진수인 <C-v>u{1234}로 입력한다(숫자 앞에 u 를 붙여야 한다). 뒤집어진 물음표 (“¿”)는 <C-v>u00bf를 입력한다. :h i_CTRL-V_digit 참조.

커서를 문자 위에 놓고 ga 명령을 실행하면 화면 하단에 십진수와 16진수, 8진수 코드를 출력한다(:h ga 참조).

<C-v> 명령 뒤에 숫자가 아닌 키를 입력하는 방법도 있다. ‘expandtab’ 옵션이 활성된 상태에서 <Tab 키를 누르면 탭문자 대신 공백 문자를 추가한다. 그러나, `은 탭 문자를 그대로 입력한다.

Keystrokes Effect
{123} Insert character by decimal code
u{1234} Insert character by hexadecimal code
{nondigit} Insert nondigit literally
{char1}{char2} Insert Unusual Characters by Digraph {char1}{char2} digraph

Table 3—Inserting Unusual Characters

Tip 18. Insert Unusual Characters by Digraph

이중자digraph로 입력할 수도 있다: 이중자는 기억하기 쉬운 문자쌍이다.

입력 모드에서 <C-k>{char1}{char2}를 입력하면 된다. ¿ 를 입력하고 싶다면, <C-v>?I를 입력한다.

이중자에서 사용하는 문자 쌍은 문자를 묘사하게 선택하였으므로 기억하거나 추측하기 쉽다. 예를 들어 겹화살 괄호인 «와 »는 이중자 «, »으로 입력할 수 있다; 분수 ½, ¼, ¾는 이중자 12, 14, 34로 입력할 수 있다. Vim 이중자의 기본 목록은 :h digraphs-default에 요약되어 있다. :digraphs에서 가능한 목록을 볼 수도 있지만 살펴보기 어렵다. :h digraph-table로 더 많은 가능한 목록을 볼 수 있다.

Tip 19. Overwrite Existing Text with Replace Mode

바꾸기 모드Replace Mode는 입력 모드와 같지만, 문서의 기존 내용을 덮어쓴다.

insert_mode/replace.txt의 문서 처음에서 f.으로 다음 “.”으로 이동한다. R, b<Esc>로 “. B”를 “, b”로 바꾸어 하나의 문장으로 변경한다.

`로 입력 모드와 바꾸기 모드를 전환할 수도 있다.

Overwrite Tab Characters with Virtual Replace Mode

탭 문자는 ‘tabstop` 설정(:h ‘tabstop’ 참고)에 정의된 만큼 열을 차지한다. 태 영역에서 바꾸기 모드를 시작하면 입력한 문자가 탭 문자를 덮어쓴다. 현재 줄의 길이가 급격히 줄어들게 된다.

gR 명령으로 시작하는 Virtual 바꾸기 모드에서는 탭 문자를 일반 공백 문자처럼 처리한다.

Virtual 바꾸기 모드에서는 실제 파일에 있는 문자를 처리하지 않고 화면에 표시된 문자를 덮어쓴다. 가능하면 Virtual 바꾸기 모드를 사용하길 권한다.

바꾸기 모드와 Virtual 바꾸기 모드의 일발성 버전도 있다. r{char}gr{char}는 한 문자만 덮어쓴 후 다시 일반 모드로 돌아온다(:h r 참고).

Chapter 4. Visual Mode

비주얼 모드Visual Mode는 선택 영역을 지정하고 조작할 수 있다. 매우 직관적이어서 이후 많은 편집 소프트웨어의 모델이 되고 있다.

Vim은 문자, 행, 사각형 영역과 동작하는 세 가지 비주얼 모드가 있다.

비주얼 모드 명령을 반복할 때 . 명령을 사용할 수 있다.

비주얼-블록 모드는 사각형으로 열을 선택할 수 있다.

Tip 20. Grok Visual Mode

비주얼 모드에서 내용의 범위를 선택하고 조작할 수 있으나, Vim의 관점은 다른 에디터와 다르다. 비주얼 모드는 또 다른 모드이다: 이는 각 키는 하나의 다른 기능을 수행한다는 것이다.

일반 모드에서 익숙해진 많은 명령은 비주얼 모드에서 똑같이 동작한다. h, j, k, l도 커서 키로 사용할 수 있고, f{char}으로 이동하고, ;, ,의 이동 반복도 가능하다. 패턴 일치하는 곳으로 이동하는 검색 명령(과 n/N)로 사용할 수있다. 비주얼 모드에서 커서가 이동할 때마다 선택 영역은 변경된다.

몇 가지 비주얼 모드 명령은 일반 모드와 같지만 약간 다르게 동작한다. 예로, 일반 모드에서 c 명령은 c를 먼저 입력한 다음 모션으로 범위를 지정해야 한다. 비주얼 모드에서는 영역을 먼저 선택한 후 c 명령을 실행한다. 대부분 비주얼 모드의 접근 방식을 더 직관적으로 느낀다.

viw로 단어를 선택한다. c 명령을 입력하면 선택된 단어가 지워지고 입력 모드로 전환된다.

Meet Select Mode

선택 모드Select Mode는 내장 문서에서 “마이크로소프트 윈도우에서의 고르기 모드와 닮았다”고 한다(:h Select-mode 참고).

비주얼 모드와 선택 모드는 <C-g>로 전환할 수 있다. 화면 하단에 -- VISUAL ---- SELECT --로 구분할 수 있다. 선택 모드에서 문자를 입력하면 선택된 영역이 지워진 후 입력 모드로 들어가서 문자를 입력할 수 있다. 물론 비주얼 모드에서 c 키로 선택 영역을 변경할 수도 있다.

Vim의 모달 본성을 좋아한다면 선택 모드는 되도록 사용하지 말아야 한다. 선택 모드를 계속 사용하게되는 시간은 한 가지이다. TextMate의 스니핏 기능을 에뮬레이트하는 플러그인 사용할 때, 선택 모드가 활성화된다.

Tip 21. Define a Visual Selection

Vim은 세 가지 비주얼 모드가 있다. 문자 단위 비주얼 모드에서는 단일 문자에서 여러 줄에 걸친 문자까지 선택할 수 있다. 줄 전체를 선택하고 싶다면 행 단위 비주얼 모드를 사용할 수 있다. 마지막으로 블록 단위 비주얼 모드는 문서의 열 영역을 선택할 수 있다.

Enabling Visual Modes

v 키는 비주얼 모드로의 통로이다. 일반 모드에서 v를 누르면 문자 단위 비주얼 모드, V로 행 단위 비주얼 모드, 로 블록 단위 비주얼 모드를 활성한다.

Command Effect
v Enable character-wise Visual mode
V Enable line-wise Visual mode
Enable block-wise Visual mode
gv Reselect the last visual selection

gv 명령은 비주얼 모드에서 마지막으로 선택했던 범위를 다시 선택해주는 단축키다. 문자 단위, 행 단위, 블럭 단위인지는 상관없지만, 선택 영역이 지워진 상황에서 사용하면 혼란스러울 수 있다.

Switching Between Visual Modes

Command Effect
/ <C-[> Switch to Normal mode
v / V / Switch to Normal mode (when used from character-, line- or
block-wise Visual mode, respectively
v Switch to character-wise Visual mode
V Switch to line-wise Visual mode
Switch to block-wise Visual mode
o Go to other end of highlighted text

Toggling the Free End of a Selection

비주얼 모드에서 명령을 실행하면 일반 모드로 돌아가고 선택 영역은 해제된다. 비주얼 모드 명령을 범위는 같지만 위치는 다른 선택 영역에서 똑같이 동작하게 하려면 어떻게 해야할까?

visual_mode/fibonacci-malformed.py는 4칸 들여쓰기를 한다. Vim이 이 들여쓰기와 맞추도록 설정하려고 한다.

Preparation

<>이 제대로 동작하도록 ‘shiftwidth’와 ‘softtabstop’의 설정을 4로 지정하고 ‘expandtab’을 활성한다. 이 한 줄이면 된다:

:set shiftwidth=4 softtabstop=4 expandtab
Indent Once, Then Repeat

들여쓰기할 행의 처음에서 Vj로 두 줄을 선택한 후 >.으로 두 번 들여쓴다. 한번의 2>를 입력해도 같은 결과를 만들 수 있지만 . 명령은 실행 결과를 화면에서 확인할 수 있다. 들여쓰기를 한번 더 하려면 .을 다시 입력하면 된다.신나서 누르다가 지나쳤다면 u로 되돌릴 수 있다.

비주얼 모드에서 . 명령은 사용하면 가장 마지막에 선택한 영역에 대해 동작한다. 행 단위 선택을 가정하고 동작하는 경향이 있어 문자 단위 선택에서는 예기치 않은 결과가 나올 수도 있다.

Tip 23. Prefer Operators to Visual Commands Where Possible

비주얼 모드는 일반 모드보다 직관적이지만 약점도 있다: 점 명령이 항상 올바르게 동작하는 것은 아니다. 일반 모드 오퍼레이터가 적합할 때도 있다.

visual_mode/list-of-links.html에서 vit로 태그 안의 내용을 선택한다: visually select inside the tag.

Using a Visual Operator

U 명령으로 대문자로 전환한다. j.으로 다음 행에서 같은 명령을 반복한다. 다시 j.을 실행하면 같은 길이인 세 글자만 동작한다(:h visual-repeat 참고).

Using a Normal Operator

비주얼 모드 U 명령은 일반 모드 gU{motion}와 같다(:h gU 참고). 이 명령으로 변경하면 점 공식을 사용해서 나머지 편집을 끝낼 수 있다.

파일에 시작에서 gUit하여 첫 태그 안의 문자를 대문자로 변경하고 j.으로 두 번째 줄을, j.으로 세 번째 줄을 변경한다.

Discussion

vitUgUit는 모두 네 번의 키 입력이지만, 내재된 의미는 매우 다르다. 두 개의 명령으로 구부하면: vit는 선택이고, U로 바꾼다. 반면, gU는 오퍼레이터이고, it는 모션이다.

. 명령은 비주얼 모드보다 일반 모드에서 오퍼레이터를 사용하는 것이 더 낫다. 일회성 변경에는 비주얼 모드가 더 낫다.

Tip 24. Edit Tabular Data with Visual-Block Mode

visual_mode/chapter-table.txt에서 <C-v>로 비주얼 블록 모드로 전환. 3j로 아래 3열을 추가한 후 x를 눌러서 선택한 열을 제거하고 . 명령을 여러 번 눌러서 같은 범위를 여러 번 지운다. 두 열의 간격이 적당해질 때까지 반복한다. 넓은 범위를 선택해서 한번에 지워도 되지만 한 열씩 지우면 시각적으로 바로 확인할 수 있으므로 한 열씩 제거하는 방법이 낫다. 마지막으로 선택했던 범위를 gv 명령으로 다시 선택하여 r|로 선택한 범위를 모두 파이프 문자로 바꾼다. 행 단위 복사, 붙여넣기로 최상단 행을 복제한 후에(yyp) 복제한 행에서 모든 문자를 대시(-) 문자로 치환한다(Vr-).

표만들기

Tip 25. Change Columns of Text

비주얼 블록 모드를 사용하면 동시에 여러 행에 내용을 추가하는 것도 가능 하다. 비주얼 블록 모드는 표 형식의 자료를 작업할 때만 유용한 것이 아니다. 코드 작업을 할 때도 종종 요긴하게 활용할 수 있다.

visual_mode/sprite.css에서 파일의 디렉토리를 여러 줄에 걸쳐 변경해야 할 때 변경하려는 범위를 비주얼 블록을 사용해서 지정한다. c를 누르면 선택 영역의 내용이 지워지고 입력 모드로 전환된다. “components”를 입력하면 가장 상단의 행에서만 입력한 내용이 나타날 것이다. 나머지 두 행에서는 아무런 반응이 없지만 <Esc>를 눌러 일반 모드로 돌아가는 순간 입력했던 내용이 나머지 두 행에 추가되는 것을 확인할 수 있다.

Tip 26. Append After a Ragged Visual Block

the_vim_way/2_foo_bar.js는 세 줄이고 행의 길이가 다르다. 세 행의 끝에 세미콜론을 붙이려고 한다. 비주얼 블록 모드로 진입한 다음에 선택 영역을 행의 마지막까지 늘리기 위해 $ 명령을 사용한다. 사각형으로만 제한에서 벗어나서 각 행의 선택 영역을 오른쪽 끝까지, 행의 길이에 맞춰 확장한다.

A 명령을 누르면 입력 모드로 전환되며 가장 상단 행의 끝에 커서가 놓이게 된다. 입력 모드에 있는 동안에 입력한 내용은 가장 상단의 행에서만 나타나지만 입력 모드를 벗어나면 선택한 모든 행에 반영된다.

“i”와 “a” 사용법

ia 명령은 일반 모드에서 입력 모드로 전환하는 명령이고, 각각 현재 문자 앞에, 뒤에 커서를 갖다놓는다. IA는 비슷하지만, 각각 커서를 현재 줄의 처음과 마지막으로 이동한다.

비주얼 블록 모드에서도 비슷하다. IA 명령은 선택한 영역의 시작 또는 끝으로 커서를 이동한 후 입력 모드로 전환한다.

비주얼 모드와 동작 대시 모드에서 ia 명령은 텍스트 개체를 선택할 때 사용하는 명령이므로 전혀 다르게 동작한다. 비주얼 모드에서 i로 입력 모드로 전환하지 않는다면 I를 입력해보라.

Chapter 5. Command-Line Mode

Tip 27. Meet Vim’s Command Line

명령행 모드는 Ex 명령, 검색 패턴, 표현식을 입력했을 때 활성된다. :을 누르면 명령행 모드로 바뀐다. 이 모드는 쉘 명령행과 비슷하다. 명령을 입력한 후 <CR>을 눌러 실행한다. 명령행 모드에서 다시 일반 모드로 돌아가려면 <Esc>를 누른다. /를 눌러 검색 프롬프트(search prompt)를 불러오거나 <C-r>=로 표현식 레지스터에 접근할 때에도 활성된다.

Command Effect
:[range]delete [x] Delete specified lines [into register x]
:[range]yank [x] Yank specified lines [into register x]
:[line]put [x] Put the text from register x after the specified line
:[range]copy {address} Copy the specified lines to below the line specified by {address}
:[range]move {address} Move the specified lines to below the line specified by {address}
:[range]join Join the specified lines
:[range]normal {commands} Execute Normal mode {commands} on each speci- fied line
:[range]substitute/{pat- tern}/{string}/[flags] Replace occurrences of {pattern} with {string} on each specified line
:[range]global/{pattern}/[cmd] Execute the Ex command [cmd] on all specified lines where the {pattern} matches

Table 7—Ex Commands That Operate on the Text in a Buffer

파일을 읽거나 쓸 때도 Ex 명령을 사용할 수 있으며(:edit:write), 탭을 만들거나(:tabnew), 창을 나누거나(:split), 또는 인자 목록을 이동하거나(:prev/:next) 버퍼 목록을 이동하는 경우(:bprev/:bnext)에도 사용할 수 있다. Vim의 모든 명령은 Ex 명령으로도 있다.(:h ex-cmd-index).

On the Etymology of Vim (and Family)

ed는 원래 유닉스(Unix) 문서 편집기이다. 비디오 디스플레이가 흔지 않던 시절에 쓰여졌다. 소스 코드를 롤 용지에 출력하고 텔레타이프(teletyep) 터미널로 편집했다.Teleprinter 하드웨어의 제약 때문에 ed는 간결한 문법이 필수였다.

ed는 여러 세대에 걸친 진보를 통해서 만들어졌다.참고 비디오 디스플레이가 흔해져서 ex는 터미널 스크린으로 파일 내용을 보여주는 기능을 추가했다. 이제 편집 내용을 실시간으로 확인할 수 있었다. 스크린 편집 모드는 :visual 또는 짧게 :vi 명령으로 활성할 수 있었다. vi라는 이름은 이 명령에서 온 것이다.

Vim은 향상된 vi(vi improved)라는 뜻이다. 과소평가된 것이다! vi는 고통스럽다. Vim의 기능 목록 중 vi에서 사용할 수 없는 부분을 :h vi-differences에서 확인할 수 있다. Vim의 기능 향상은 필수였지만 여전히 유산도 많이 가지고 있다. Vim이 선조에게 물려받은 디자인적 제한은 매우 효율적인 명령 세트를 우리에게 주었고, 오늘날 여전히 가치 있다.

Special Keys in Vim’s Command-Line Mode

입력 모드는 입력 내용이 버퍼에 작성되지만 명령행 모드는 프롬프트에 나타난다. 두 모드에서는 <Ctrl> 조합 키로 명령을 호출할 수 있다. 두 모드는 몇 가지 명령을 공유한다. 예를 들어 <C-w><C-u>는 각각 이전 단어까지, 또는 행의 시작까지 역방향으로 지운다. <C-v><C-k>는 키보드에 없는 문자를 입력할 수 있다. <C-r>{register} 명령으로 명령행에 어떤 레지스터의 내용을 입력할 수 있다.

명령행 프롬프트에서는 이동이 제한적이다. <left><right> 방향키를 사용하여 한 글자씩 이동할 수 있지만 일반 모드보다 많이 제한된다. 그러나 프롬프트에서 복잡한 명령들을 작성하길 원한다면 명령행 창으로 모든 편집 기능을 사용할 수 있다.

Ex Commands Strike Far and Wide

같은 일도 Vim의 일반 명령보다 Ex 명령을 사용하여 더 빨리 처리할 수도 있다. 일반 명령은 현재 문자나 현재 행에 동작하는 경향이 있지만, Ex 명령은 어디서든 실행할 수 있다. 커서를 움직이지 않고도 변경할 수도 있다. 특히 여러 행에 걸쳐 동시에 실행하는 능력이 Ex 명령의 가장 훌륭한 특징이다.

일반적으로 말해서, Ex 명령은 넓은 범위와 한 번의 동작으로 많은 행을 변경하는 능력을 가지고 있다. 훨씬 더 응축해서 말하면, Ex 명령은 멀리 그리고 넓게 동작한다.

Tip 28. Execute a Command on One or More Consecutive Lines

대부분의 Ex 명령은 [range]를 지정해서 명령이 실행될 영역을 지정할 수 있다. 범위의 시작과 끝을 지정할 때는 행 번호, 마크(mark), 패턴을 이용할 수 있다.

cmdline_mode/practical-vim.html

<!DOCTYPE html>
<html>
  <head><title>Practical Vim</title></head>
  <body><h1>Practical Vim</h1></body>
</html>

Use Line Numbers as an Address

숫자만 Ex명령으로 입력하면 행번호로 해석하여 지정한 행으로 커서가 이동한다.

파일의 끝으로 이동하고 싶다면 $를 입력한다.

:3p

위의 명령은 3번 행으로 이동하여 행의 내용을 출력한다.

:3d를 입력하면, 3번 행으로 이동하여 행을 삭제한다. 일반 모드에서 3G를 입력한 다음에 dd를 입력하는 것과 같다. Ex 명령이 일반 모드 명령보다 더 빠르게 사용하는 예이다.

Specify a Range of Lines by Address

:2,5p
2 <html>
3   <head><title>Practical Vim</title></head>
4   <body><h1>Practical Vim</h1></body>
5 </html>

이 명령은 2번 행부터 5번 행까지의 내용을 출력한다. 실행한 후 커서는 5번 행으로 이동한다. 범위는 일반적으로 다음 형태로 지정한다.

:{start},{end}

{start}과 {end}는 모두 주소이다. 패턴이나 마크를 주소로 사용할 수도 있다.

현재 행을 말하는 주소로 . 기호를 사용할 수 있다. 현재부터 파일의 끝이라는 범위를 쉽게 만들 수 있다.

:2
:.,$p
2 <html>
3   <head><title>Practical Vim</title></head>
4   <body><h1>Practical Vim</h1></body>
5 </html>

% 기호도 특별한 의미를 갖고 있다. 이 기호는 현재 파일의 모든 행을 뜻한다. :%p 명령은 :1,$p 와 결과가 동일하다. 보통 :substitute 명령과 같이 사용한다.

Specify a Range of Lines by Visual Selection

숫자로 행의 범위를 지정하는 대신 비주얼 선택(visual selection)을 할 수 있다. 2GVG 명령으로 2행부터 파일의 끝까지 선택한다. 영역을 선택한 상태에서 :을 누르면 명령행 프롬프트에 :'<,'>라는 범위가 미리 입력된다. 암호처럼 보일지도 모르겠지만 비주얼 선택의 범위이다. 이제 Ex 명령을 입력하면 선택한 모든 행에서 실행될 것이다.

:'<,'>p

'<는 비주얼 선택의 첫 행이고, '>는 마지막 행이다. 이 마크는 비주얼 모드(visual mode)를 벗어나도 사용할 수 있다. 일반 모드에서 :'<,'>p를 사용하면, 가장 최근에 비주얼 모드의 선택 영역을 기준으로 동작한다.

Specify a Range of Lines by Patterns

:/<html>/,/<\/html>/p

복잡하게 보이지만, 일반적인 범위 형식인 :{start},{end}이다. {start} 주소가 /<html>/ 패턴이고, {end} 주소는 /<\/html>/이다. 달리 말해 <html> 태그가 열린 행부터 닫힌 행까지이다.

:/<html>/+1,/<\/html>/-1p

Modify an Address Using an Offset

오프셋의 형태는 다음과 같다.

:{address}+n

n이 생략되면 기본값으로 1이 적용된다. {address}는 행 번호, 마크, 패턴을 사용할 수 있다.

:2
:.,.+3p

. 기호는 현재 행이다. 그러므로, 이 경우에는 :.,.+3:2,5와 같은 역할을 한다.

범위 문법은 매우 유연하여 행 번호, 마크, 패턴을 섞을 수 있고, 오프셋을 어떤 곳에도 적용할 수 있다.

Symbol Address
1 First line of the file
$ Last line of the file
0 Virtual line above first line of the file . Line where the cursor is placed
. line where the cursor is placed
‘m Line containing mark m
’< Start of visual selection
’> End of visual selection
% The entire file (shorthand for :1,$)

0번 행은 실제로 존재하지 않지만, 맥락에 따라 주소로 사용할 수 있다. 특히 :copy {adress}:move {adress} 명령의 마지막 인자로 사용하여, 하나의 범위를 파일의 최상단으로 복사하거나 이동할 수 있다.

[range]는 항상 연속하는 행이지만, :global 명령을 사용하여 연속하지 않는 행에서 Ex 명령을 실행할 수도 있다.

Part II. Files

Chapter 6. Manage Multiple Files

Tip 37. Track Open Files with the Buffer List

편집 세션에서 여러 파일을 열 수 있다. 버퍼 목록으로 파일을 관리할 수 있다.

Understand the Distinction Between Files and Buffers

Vim에서 실제로 파일을 편집하는 것이 아니다. 사실은 메모리 공간에 파일을 복사해서 편집하는 것이다. 메모리에 존재하는 파일의 사본을 Vim에서는 버퍼(buffer)라고 한다.

파일은 디스크에 보관하고 버퍼는 메모리에 보관한다. 파일을 열면 같은 이름으로 내용을 버퍼에 불러온다. 처음에는 버퍼와 파일의 내용이 일치하지만 버퍼의 내용을 수정하는 순간부터 달라진다. 만약 버퍼에서 변경한 사항을 유지하고 싶다면 버퍼의 내용을 다시 파일로 저장하면 된다. Vim 명령은 대부분 버퍼에서 동작하지만 :write, :update, :saveas 명령처럼 파일을 위한 명령도 있다.

Meet the Buffer List

Vim이 실행되면서 파일을 불러오면 첫 번째 파일을 창에 출력한다. 두 번째 파일은 버퍼로 불러온 후 백그라운드에 놓이기 때문에 보이지 않는다. :ls 명령으로 현재 메모리에 존재하는 모든 버퍼 목록을 확인할 수 있다 (:h :ls 참고).

다음 버퍼를 현재 창으로 불러오고 싶다면 :bnext 명령을 사용한다. 버퍼목록에서 % 기호는 현재 창에서 볼 수 있는 버퍼를 표시한다. # 기호는 현재 활성된 버퍼와 교대한 버퍼를 나타낸다. <C-^>로 현재 버퍼와 이전 버퍼를 전환할 수 있다.

Use the Buffer List

버퍼 목록에서 :bprev, :bnext로 전후 이동을 할 수 있으며, :bfirst:blast 명령으로 목록의 처음과 끝으로 이동할 수 있다. 팀 포프의 unimpaired.vim1 플러그인에서는 다음과 같은 맵핑을 사용하고 있다.

nnoremap <silent> [b :bprevious<CR>
nnoremap <silent> ]b :bnext<CR>
nnoremap <silent> [B :bfirst<CR>
nnoremap <silent> ]B :blast<CR>
  • :h [도 참고

unimpaired.vim 플러그인은 인자 목록([a와 ]a), 퀵 픽스 목록([q, ]q), 위치 목록([l, ]l), 태그 목록([t, ]t)에서 사용할 수 있다.

:ls 버퍼 목록 앞의 숫자를 사용해서 :buffer N으로 숫자에 해당하는 버퍼로 이동할 수 있다(:h :b 참고). :buffer {bufname}이 좀 더 직관적이다. {bufname}은 파일 경로를 기준으로 각각의 버퍼를 구분할 수 있는 명칭을 사용해야 한다. 입력한 버퍼명이 둘 이상인 경우에는 탭 완성을 사용할 수 있다.

:bufdo 명령으로 버퍼 목록에 있는 모든 버퍼를 대상으로 Ex 명령을 사동할 수 있다(:h :bufdo 참고). 실제로는 :argdo 명령을 더 자주 사용한다.

Deleting Buffers

버퍼를 제거하고 싶다면 :bdelete 명령을 사용할 수 있다.

:bdelete N1 N2 N3
:N,M bdelete

5번 버퍼부터 10번 버퍼까지 연속된 버퍼를 제거하려면 :5,10bd 명령을 사용한다. 8번 버퍼는 유지하고 싶다면 :bd 5 6 7 9 10으로 입력해서 8번을 제외하고 제거할 수 있다.

버퍼 목록을 다시 조정할 수 있는 기능이 없다. 대신에 작업 환경을 창이나 탭, 인자목록으로 나눠서 관리할 수 있다.

Group Buffers into a Collection with the Argument List

:args으로 인자 목록을 확인할 수 있다.

실행할 때 *.txt라는 인자로 실행했어도 셸은 * 와일드 카드를 확장해서 패턴이 일치하는 파일 다섯 개를 인자로 집어넣는다. 출력된 인자 목록에서 볼 수 있는 [] 문자는 현재 열려 있는 파일을 표시한다.

버퍼 목록은 Vim에서 개선된 기능이지만, 인자 목록은 vi에서도 제공했던 기능이다.

인자 목록의 내용은 언제든 수정할 수 있다. 다시 말해 :args의 목록은 Vim을 실행할 당시의 인자를 항상 반영하는 것은 아니란 뜻이다. 다른 명령도 마찬가지다. :compiler:make는 컴파일 언어만을 위한 것이 아니다.

Populate the Argument List

:args {arglist} 명령으로 인자 목록을 갱신할 수 있다(:h :args_f 참고). {arglist}은 파일명이나 와일드카드, 셸 명령의 출력을 포함할 수 있다.

인자 목록에 파일명을 입력하는 가장 간단한 방법은 하나씩 직접 입력 하는 것이다.

와일드카드를 이용해서 인자 목록에 등록할 수 있다.(:h wildcard 참고). ** 와일드카드도 파일명에 문자가 없거나 하나 이상 존재하는 경우를 뜻한다. 차이가 있다면 특정 디렉터리 안에 존재하는 부 디렉터리까지 모두 재귀적으로 검색해서 파일을 찾는다는 점이다(:h starstar-wildcard 참고). 이렇게 요청한 경로와 일치하는 파일 목록을 불러오기 위해 와일드카드 조합을 사용할 수 있는데 이 방법을 글롭(glob)이라 한다.

파일 목록을 일반 문서 파일로 작성해서 관리할 수 있다. files/.chapters로 작성하면 :args `cat .chapters`과 같이 사용할 수 았다.

cat 명령을 사용했지만 셸에서 구동할 수 있는 명령은 어떤 것이든 인자 목록 명령과 함께 사용할 수 있다. 모든시스템에서 동작하지는 않는다(:h backtick-expansion 참고).

Use the Argument List

인자 목록은 버퍼 목록보다 간단하다. 파일을 필요에 따라 마음대로 묶어서 관리할 수도 있다. :args {arglist} 명령으로 인자 목록을 비우고 다시 입력할 수 있다. :next:prev으로 인자 목록에 있는 다음 또는 이전 파일을 버퍼로 불러낼 수 있다. :argdo로 인자 목록의 각각 버퍼에 동일한 명령을 실행할 수 있다.

버퍼 목록은 바탕 화면처럼 언제나 난장판이 된다. 인자 목록은 분리된 작업 공간처럼 작업 환경을 단정하게 유지할 수 있고 필요에 따라 작업 공간을 확장하는 것도 가능하다.

Part III. Getting Around Faster

모션(Motion)은 커서 이동에 더해 동작-대기 모드에서 문서 범위를 조작할 수도 있다.

CHAPTER 8. Navigae Inside Files with Motions

텍스트 개체(text object)는 동작-대기 모드의 꽃이다.(:h motion.txt)

Tip 47. Keep Your Fingers on the Home Row

빔은 터치 타이피스트(touch typist)에 최적이다. 키보드 중앙(home row)에서 손을 띠지 않고 그 주위를 움직이는 것을 배우면 빔을 더 빨리 작동할 수 있다. 쿼티(qwerty) 키보드에서 왼손은 a, s, d, f에 오른손은 j, k, l, ;에 놓는 것을 말하고, 이 위치에서 다른 키 대부분을 손을 움직이지 않고도 닿는다. 가장 이상적인 키보드 입력 자세이다.참고 j가 아래 방향을 가리키는 화살표처럼 생겼다고 기억한다.

Leave Your Right Hand Where It Belongs

커서를 왼쪽으 로 이동하는 데 h를 두 번 이상 누르는 것보다 대신에 문자 검색 명령을 사용한다. ;를 새끼 손가락으로 누를 수 있는 기본 위치가 더 편하다. 수평으로 움직일 때는 단어 단위 모션, 문자 검색 모션을 활용한다.

Tip 48. Distinguish Between Real Lines and Display Lines

Vim에는 실제 행과 표시 행이 있다. 줄바꿈(wrap) 설정을 기본으로 사용하기 때문에,창의 너비보다 내용은 줄을 바꿔 모든 내용을 화면에 보여준다. 하나의 행이 여러 줄로 표시된다.

실제 행과 표시 행의 차이를 가장 간단히 알아볼 수 있는 방법은 행 번호(number) 설정을 켜는 것이다. jk는 실제 행을 기준으로 이동한다. gjgk은 표시 행을 기준으로 이동한다.

Command Move Cursor
j Down one real line
gj Down one display line
k Up one real line
gk Up one display line
0 To first character of real line
g0 To first character of display line
^ To first nonblank character of real line
g^ To first nonblank character of display line $ To end of real line
g$ To end of display line

j, k, O, $는 실제 행을 대상으로 사용하는 명령이다. 이 명령 앞에 g를 붙이면 표시 행을 대상으로 사용하는 명령이 된다.

Remap Line Motion Commands

motions/cursor-maps.vim nnoremap k gk nnoremap gk k nnoremap j gj nnoremap gj j

이 설정은 j, k가 표시 행을 이동하고, gj, gk가 실제 행을 이동하도록 변경한다. 기본 동작과 반대로 설정한 것이다. 그러나 Vim을 여러 환경에서 자주 사용하고 있다면 설정을 바꾸는 것보다는 기본 동작과 친숙해지는 편이 낫다.

Tip 49. Move Word-Wise

Vim은 단어 단위로 빠르게 이동할 수 있는 모션을 제공한다(:h word-motions).

Command Move Cursor
w Forward to start of next word
b Backward to start of current/previous word e Forward to end of current/next word
ge Backward to end of previous word

w, b는 단어의 처음으로, ege는 단어의 마지막으로 이동한다. we는 커서를 앞으로 이동하고 b, ge는 뒤로 이동한다. 전진을 뜻하는 (for-)word와 후진을 뜻하는 backword를 생각하면 도움이 된다.

ea는 현재 단어의 끝에 덧붙인다. 하나의 명령처럼 사용되곤 한다. gea는 이전 단어 끝에 덧붙인다.

Know Your Words from Your WORDS

Vim에는 단어에 대한 두 가지 정의가 있다. word와 WORD이다. 앞서 살펴 본 word 단위 모션은 WORD 단위 모션에도 호환된다. W, B, E, gE가 해당한다. 다만 word와 WORD는 정의가 조금 다르다. word는 문자, 숫자, 밑줄(_) 또는 다른 블럭 아닌(nonblock) 문자의 연속으로 이뤄지고 공백으로 분리된 단위이다.(:h word). 반면에 WORD는 단순하다. 블럭아닌 문자의 연속이며 공백으로 분리된 경우를 WORD로 정의한다(:h WORD). WORD는 단어보다 크다. 빠르게 이동하고 싶다면 WORD 단위로, 섬세하게 이동하고 싶다면 word 단위로 이동한다.

Tip 50. Find by Character

문자 검색 명령으로 행 안에서 빠르게 이동할 수 있다. 이 문자 검색 명령은 동작-대기 모드에서 작동한다. f{char} 명령은 특정 문자를 검색하는 명령으로 현재 커서 위치에서 현재 행의 끝까지 검색한다. 일치하는 문자를 찾으면 커서는 그 문자로 이동한다. 일치하는 문자를 찾지 못하면 커서가 움직이지 않는다(:h f).

Vim은 가장 최근의 f{char} 검색을 기억하기 때문에 ; 명령을 사용해서 마지막 검색을 반복하면 된다(:h ;). ;를 입력하다가 원하는 위치를 지나쳤다. 위치를 다시 되돌리기 위해 , 명령을 사용할 수 있다. 이 명령은 마지막 f{char} 검색을 똑같이 수행하지만 반대 방향으로 진행한다(:h , 참고).

Don’t Throw Away the Reverse Character Search Command

Vim에서 키보드에 있는 키 대부분에 기능이 배정되어 있다. 만약 자신만의 특별한 기능을 추가하고 싶다면 사용자 정의 명령의 네임스페이스로 사용할 수 있는 리더 키(<Leader>)를 제공한다. 아래 설정을 추가하면 <Leader>를 사용하여 자신만의 커스텀 설정을 만들 수 있다:

noremap n nzz noremap N Nzz

기본 리더 키는 \다. 따라서 위에서 만든 커스텀 설정은 \n, \N으로 사용할 수 있다. 여기에 사용된 zz가 무슨 역할을 하는지 궁금하면 :h zz를 확인하자. 키보드 종류에 따라 \ 명령을 사용하기 불편할 수도 있다. 이런 경우 리더 키를 다른 키로 변경하여 사용한다(:h mapleader 참고). 일반적으로 쉼표 키를 사용한다. 리더 키를 쉼표 키로 바꾼다면, 이미 쉼표에는 역방향 문서 검색 명령이 배정되어 있기 때문에 이 기능을 다른 키에 배정하기를 권한다.

let mapleader=”,” noremap \ ,

단어 검색 명령인 ;, 명령은 서로 보완하는 관계다. 두 명령 중 하나만 사용한다면 단어 검색의 유용성이 많이 떨어진다.

Character Searches Can Include or Exclude the Target

f{char}, ;, , 명령은 문자 검색 명령 중 일부이다. 다음 표는 모든 문자 검색 명령 목록이다.

Command Effect
f{char} Forward to the next occurrence of {char}
F{char} Backward to the previous occurrence of {char}
t{char} Forward to the character before the next occurrence of {char}
T{char} Backward to the character after the previous occurrence of {char}
; Repeat the last character-search command
, Reverse the last character-search command

t{char}T{char}는 검색하는 문자가 나타날 때까지(till) 검색한다고 생각하자. f{char}, F{char}는 해당 문자가 나타나는 위치로 커서가 이동하지만 t{char}, T{char} 명령은 {char}의 한 글자 앞으로 커서가 이동한다.

,문자에서 문장의 마지막 문자 직전까지 삭제하려면 f,dt.을 사용할 수 있다.

일반 모드에서 f{char}F{char} 명령은 현재 행에서 빠르게 커서를 이동할 때 자주 사용한다. 그리고 d{motion}c{motion}을 사용할 때 t{char}, T{char} 명령과 함께 사용하는 편이다. 이 설명을 다른 방향에서 보면, 일반 모드에서는 f 또는 F를 주로 사용하고, 동작-대기모드에서는 t 또는 T를 주로 사용한다고 말할 수 있다.

Think Like a Scrabble® Player

Improve your writing by deleting excellent adjectives.

excellent로 이동하기 위해서 fe를 사용하면 ;을 세 번이나 더 눌러야 한다. fx를 사용한다면 한 번에 원하는 단어로 이동하여 daw로 단어를 삭제한다.

CHAPTER 9.Navigate Between Files with Jumps

점프(jump)는 모션과 비슷하지만 다른 파일 사이를 이동할 수 있다.

Tip 56. Traverse the Jump List

Vim은 점프할 때 이동 전과 후의 위치를 모두 저장하고, 그 발자취를 알 수 있는 명령을 제공한다.

웹 브라우저에서는 뒤로 버튼으로 이전에 방문했던 페이지로 이동할 수 있다. Vim은 비슷한 기능을 하는 점프 목록(jump list)이 있다. <C-o> 명령이 뒤로 버튼과 같으며 <C-i> 명령은 앞으로 버튼과 같다. 이 명령으로 점프 목록을 오갈수 있다.

모션은 파일 안에서 이동할 때 사용하고, 점프는 파일 사이를 이동할 때 사용한다.(모션 중 점프로 구분되는 일부 모션이 있지만)

점프 목록을 보려면:

:jumps
jump line col file/text
   4   12   2 <recipe id="sec.jump.list">
   3  114   2 <recipe id="sec.change.list">
   2  169   2 <recipe id="sec.gf">
   1  290   2 <recipe id="sec.global.marks">
>
Press Enter or type command to continue

현재 창에서 파일을 변경하는 명령은 모두 점프 명령이라고 말할 수 있다. Vim은 점프 명령을 실행하 기 전과 후의 위치를 점프 목록에 기록한다. :edit 명령으로 새 파일을 열었다면 두 파일을 <C-o><C-i> 명령으로 오갈 수 있다.

[count]G로 특정 행으로 바로 이동하는 것은 점프이지만 한 행씩 이동하는 것은 점프가 아니다. 문장 단위 및 단락 단위의 모션은 점프이지만 문자와 단어의 모션은 점프가 아니다. 일반적으로 장거리 모션은 점프로 분류될 수 있지만 단거리 모션은 그냥 모션이다.

점프로 처리되는 명령을 정리한다:

Command Effect
[count]G Jump to line number
/pattern/?pattern/n/N Jump to next/previous occurrence of pattern
% Jump to matching parenthesis
( / ) Jump to start of previous/next sentence
{ / } Jump to start of previous/next paragraph
H / M / L Jump to top/middle/bottom of screen
gf Jump to file name under the cursor
<C-]> Jump to definition of keyword under the cursor
‘{mark} / `{mark} Jump to a mark

<C-o><C-i> 명령 자체는 모션으로 처리되지 않는다. 비주얼 모드에서 선택 영역을 확장하거나 동작-대기 모드에서 이 명령을 사용할 수 없다는 뜻이다.

Vim은 여러 점프 목록을 동시에 관리 한다. 실은 각 창마다 각 점프 목록이 있다. 창 분할이나 다중 탭 페이지를 사용하고 있다면 <C-o><C-i> 명령은 항상 활성 창의 점프 목록을 따라 이동한다.

Beware of Mapping the Tab Key

입력 모드에서 <C-i><Tab>을 입력하는 것과 같다. Vim이 <C-i><Tab>을 같은 것으로 보기 때문이다.

<Tab> 키의 매핑을 변경하면, <C-i>를 누를 때도 변경된 매핑을 실행한다.(반대도 마찬가지다) 그러므로 <Tab>을 다른 기능으로 변경할 때는 점프 목록을 이동하는 <C-i>를 포기할 만큼 중요한지 고려해야 한다. 한 방향으로만 이동하는 것은 그다지 유용하지 않기 때문이다.

Tip 57. Traverse the Change List

작업을 취소하는 명령과 취소한 작업을 다시 되돌리는 명령을 실행하면 최근에 변경한 위치로 이동하는 부차적인 효과도 생긴다. 실행 취소 명령은 최근 변경 위치로 돌아가고 싶은 경우에도 유용하다. u<C-r>은 일종의 해킹이다.

Vim은 편집 세션 중에 각 버퍼에 대한 수정 목록을 관리한다. 이 것을 변경 목록(change list)이라고 한다.(:h changelist) :changes 명령으로 내용을 볼 수 있다.

g;g, 명령으로 변경 목록에서 앞 뒤로 이동할 수 있다. ;, 명령이 f{char} 명령을 반복하거나 역반복할 수 있다는 것을 생각하면 기억하기 쉬울 것이다.

문서에서 최근 변경으로 되돌아 가려면 g;를 입력한다. u<C-r>을 입력해도 결과는 같지만, 문서에 일시적인 변경을 만든다.

Marks for the Last Change

Vim은 변경 목록을 보완하기 위해서 마크를 자동으로 생성한다. `. 마크는 항상 마지막 변경의 위치를 참조한다.(:h `.) `^ 마크는 입력 모드를 종료한 마지막 위치를 기록한다.

대부분의 시나리오에서 `. 마크로 이동하면 g; 명령과 효과가 같다. 하지만 `. 마크가 마지막 변화의 위치만을 저장하는 것과 달리 변경 목록은 여러 위치를 저장한다. g;를 반복 입력할 때마다 변경 목록에 저장된 위치를 순서대로 이동할 수 있다. 반면 `.는 변경 목록에서 가장 마지막 위치로만 이동한다.

`^ 마크는 마지막 변경_과는 살짝 다른, 마지막 _입력 위치를 참조한다. 입력 모드를 벗어나서 문서를 스크롤한 후 gi를 입력하여 벗어난 곳으로 빠르게 갈 수 있다. `^는 한 번의 움직임으로 커서 위치를 복원하고 입력 모드로 전환한다.

Vim은 변경 목록을 버퍼를 기준으로 관리한다. 대조적으로, 점프 목록은 창을 기준으로 만든다.

CHAPTER 18. Search Project-Wide with grep, vimgrep, and Others

Vim의 검색 명령은 파일 내의 모든 패턴을 찾는 데 탁월하다. 그러나 전체 프로젝트에서 일치하는 항목을 찾으려면 어떻게 해야 할까? 많은 파일을 살펴봐야 한다. 전통적으로 이것은 유닉스 검색 전용 도구 인 grep의 영역이다.

편집기를 떠나지 않고도 외부 프로그램을 호출할 수 있는 :grep 명령을 살펴본다. 이 명령은 기본적으로 grep을 호출하지만, ack와 같은 다른 검색 전용 프로그램을 사용하도록 설정할 수 있다.

외부 프로그램을 사용할 때의 한 가지 단점은 정규식 구문이 대부분의 Vim 검색에 사용되는 구문과 호환되지 않을 수 있다. :vimgrep 명령을 사용하면 Vim의 기본 검색 엔진을 사용하여 여러 파일의 패턴을 찾을 수 있다. vimgrep은 전용 프로그램만큼 빠르지 않다.

Tip 109. Call grep Without Leaving Vim

:grep 명령은 외부의 grep (또는 grep 같은) 프로그램을 사용할 수 있는 래퍼(wrapper)처럼 동작한다. 이 래퍼를 사용하여 Vim을 벗어나지 않고 여러 파일에 걸쳐 grep 패턴 검색을 할 수 있고, 퀵픽스 목록을 사용하여 검색 결과를 오갈 수 있다.

Using grep from the Command Line

$ grep -n {text} *

기본적으로 grep은 일치하는 행의 내용과 파일명을 한 줄로 보여준다. -n 플래그는 grep에게 출력에 행 번호를 표시한다.

검색 결과 항목을 표처럼 다룰 수 있다. 결과 목록의 각 항목에서 파일을 열 수 있고, 행 번호를 지정할 수 있다. goldrush.txt의 9행을 열고 싶다면:

$ vim contain-result.txt +9

Calling grep from Inside Vim

:grep 명령은 외부 grep 프로그램의 레퍼(wrapper)이다(:h :grep). 셸에서 grep을 실행하는 대신에 Vim에서 직접 실행할 수 있다.

:grep {text} *

Vim이 grep -n {text} *을 셸에서 실행한다. Vim은 grep 검색 결과를 해석해서 퀵픽스 목록으로 만든다. :cnext, :cprev 명령으로 결과를 탐색할 수 있으며 모든 기능을 사용할 수 있다.

Vim은 자동으로 -n 플래그를 추가해서 grep 결과에 행 번호도 출력한다. 퀵픽스 목록을 탐색할 때, 일치하는 각 행으로 바로 이동할 수 있는 이유이다.

대소문자를 구분하지 않으려면 -i 플래그를 사용한다.

Tip 110. Customize the grep Program

:grep 명령은 외부 grep 프로그램을 실행하기 위한 래퍼이다. Vim이 이 명령을 처리하는 방법을 ‘grepprg’와 ‘grepformat’ 설정을 수정하여 변경할 수 있다.

Vim’s Default grep Settings

‘grepprg’ 설정은 :grep 명령을 실행할 때 셸에서 실행하는 명령을 지정한다(:h ‘grepprg’). ‘grepformat’ 설정은 Vim이 :grep 명령의 출력 결과를 해석하는 방법을 지장한다(:h ‘grepformat’). Unix 시스템에서는 기본 값이 다음과 같다:

grepprg="grep -n $* /dev/null"
grepformat="%f:%l:%m,%f:%l%m,%f %l%m"

‘grepprg’ 설정에서는 $* 기호를 플레이스홀더로 사용하는데 :grep 명령의 인자가 위치하는 곳을 뜻한다. ‘grepformat’ 설정은 :grep이 반환하는 결과 메시지의 구조를 토큰으로 작성한 문자열이다. ‘grepformat’ 문자열에서 사용되는 특수 토큰은 ‘errorformat’에 사용 된 것과 같다.

이제 %f:%l %m 기본 형식을 사용한 grep 결과를 확인한다.

department-store.txt:1:Waldo is beside the boot counter.
goldrush.txt:6:Waldo is studying his clipboard.
goldrush.txt:9:The penny farthing is 10 paces ahead of Waldo.

각 레코드에서, %f가 파일명(department-store.txt나 goldrush.txt)에 해당하고, %l은 행 번호, %m은 행의 일치하는 문자열이다.

‘grepformat’ 문자열은 쉼표로 구분된 여러 형식을 포함할 수 있다. 기본 일치는 %f:%l %m 또는 %f %l%m이다. Vim은 :grep 출력과 일치하는 첫 번째 형식을 사용한다.

Make :grep Call ack

ack는 grep 대용이고 특히 개발자를 대상으로 한다.(http://betterthangrep.com)

먼저 ack를 설치해야 한다. 우분투에서:

$ sudo apt-get install ack-grep
$ sudo ln -s /usr/bin/ack-grep /usr/local/bin/ack

첫 명령은 프로그램을 설치하고 ack-grep 명령을 사용할 수 있게 한다. 두 번째 명령은 ack로 호출할 수 있도록 심볼릭링크를 생성한다.

OS X에서는 Homebrew로 설치할 수 있다:

$ brew install ack

이제 ‘grepprg’와 ‘grepformat’ 설정을 변경해서 :grepack를 사용하도록 설정 한다. ack에서는 파일명을 한 줄로 출력하고, 행 번호와 일치하는 행의 내용이 뒤따른다:

$ ack Waldo *
department-store.txt
1:Waldo is beside the boot counter.

goldrush.txt
6:Waldo is studying his clipboard.
9:The penny farthing is 10 paces ahead of Waldo.

--nogroup 스위치와 함께 ack를 실행하면 grep -n의 결과처럼 출력을 쉽게 변경할 수 있다.

$ ack --nogroup Waldo *
department-store.txt:1:Waldo is beside the boot counter.
goldrush.txt:6:Waldo is studying his clipboard.
goldrush.txt:9:The penny farthing is 10 paces ahead of Waldo.

이 출력은 grep -n의 형식과 일치한다. Vim의 기본 ‘grepformat’ 설정은 변경할 필요 없다. ‘grepprg’만 다음처럼 변경한다:

:set grepprg=ack\ --nogroup\ $*

Alternative grep Plugins

Vim에서는 외부 프로그램을 사용해서 여러 파일의 본문을 쉽게 검색할 수 있다. 단순히 ‘grepprg’와 ‘grepfotmat’ 설정을 변경한 다음에 :grep 명령을 사용하면 끝이다. 그 결과는 퀵픽스 목록에서 확인할 수 있다. 어떤 프로그램을 호출하는지에 상관없이 사용할 수 있기 때문에 거의 이상적인 인터페이스이다.

그러나 중요한 차이가 있다. grep은 POSIX 정규표현식을 사용하나 ack는 펄의 정규표현식을 사용한다. :grep 명령을 사용하여 ack를 호출하면 이 차이 때문에 제대로 호출되지 않는다. :Ack라는 명령을 직접 만들어서 이름처럼 ack를 호출하는 것은 어떨까?

이런 접근 방법으로 개발된 Ack.vim 플러그인이 있다.mileszs/ack.vim: Vim plugin for the Perl module / CLI script ‘ack’ 또한, git-grep을 사용할 수 있도록 :Ggrep 명령을 제공하는 fugitive.vim 플러그인도 있다.tpope/vim-fugitive: fugitive.vim: a Git wrapper so awesome, it should be illegal

이렇게 여러 플러그인을 설치할 수 있고, :grep 명령을 대체하는 방식보다 각 플러그인의 커스텀 명령을 만들어 서로 충돌없이 공존할 수 있다.

Make ack Jump to Line and Column

그러나 ack는 또 다른 기법을 소매 속에 숨기고 있다. --column 옵션과 함께 실행하면 ack는 일치하는 행과 열 번호 를 출력한 다.

$ ack --nogroup --column Waldo *
department-store.txt:1:1:Waldo is beside the boot counter.
goldrush.txt:6:1:Waldo is studying his clipboard.
goldrush.txt:9:41:The penny farthing is 10 paces ahead of Waldo.

‘grepformat’이 추가 정보를 추출할 수 있도록 설정하면 일치하는 행으로 이동하는 것뿐만 아니라 일치하는 정확한 위치로 이동할 수 있다. 다음 설정으로 쉽게 된다:

:set grepprg=ack\ --nogroup\ --column\ $*
:set grepformat=%f:%l:%c:%m

%c 항목이 일치하는 열 번호이다.

Tip 111. Grep with Vim’s Internal Search Engine

:vimgrep 명령으로 Vim의 내장 정규표현식 엔진을 사용해서 여러 파일을 검색할 수 있다.

grep/quotes 폴더에서 각 파일은 단어 “going”을 하나 이상 포함하고 있다. :vimgrep 명령을 사용하여 이 단어를 어떤 파일이 포함하고 있는지 찾으려면:

:vimgrep /going/ clock.txt tough.txt where.txt
(1 of 3): Don't watch the clock; do what it does. Keep going.
:cnext
(2 of 3): When the going gets tough, the tough get going.
:cnext
(3 of 3): If you don't know where you are going,

:vimgrep 명령은 일치한 항목을 각각 한 줄씩 퀵픽스 목록을 만든다. :cnext, :cprev와 같은 명령을 사용해서 결과를 탐색한다.

tough.txt 파일은 “going”이 두 번 나타난다. 하지만 :vimgrep 명령은 첫 일치하는 것만 고려한다. 모든 항목을 찾으려면 g 플래그를 패턴 뒤에 추가한다.

:vim /going/g clock.txt tough.txt where.txt
(1 of 4): Don't watch the clock; do what it does. Keep going.

이번에는 “going” 단어가 나타나는 모든 항목이 퀵픽스 목록에 포함한다. :substitute 명령이 동작하는 방식이 기억날 것이다: 기본적으로는 행에서 첫 번째 일치하는 항목에 대해서만 치환을 수행한다. g 플래그를 제공했을 때 주어진 행에서 일치하는 모든 것에 대해 수행한다. 필자는 :substitute:vimgrep 명령을 사용 할 때 거의 항상 g 플래그를 넣어서 사용한다.

Specifying Which Files to Look Inside

다음은 :vimgrep 명령 형식이다(:h :vimgrep).

:vim[grep][!] /{pattern}/[g][j] {file} ...

{file} 인자는 빈칸으로 남겨둘 수 없다. 이 인자에는 파일명이나 와일드카드, 역따옴표 표현식, 그리고 이 모든 것을 조합할 수도 있다. 인자 목록을 불러올 때 사용할 수 있던 그 기법을 여기에서도 사용할 수 있다.

와일드카드를 사용해서 동일한 검색을 수행할 수 있다:

:vim /going/g *.txt

*** 와일드카드를 사용한 것처럼 인자 목록에 있는 파일을 모두 열기 위해서 ## 기호를 사용할 수 있다(:h cmdline-special). 이 기호를 사용하면 조금 다른 방식으로도 작업을 진행할 수 있다. 먼저 인자 목록에 검사할 파일을 불러온다. 그런 다음 인수 목록의 각 파일에 대해 :vimgrep을 실행한다.

:args *.txt
:vim /going/g ##
(1 of 4): Don't watch the clock; do what it does. Keep going.

Ex 명령 두 개로 분리해서 실행하기 때문에 더 일하는 것 같지만 :vimgrep을 사용할 때는 이 방식을 종종 선호한다. 어느 파일을 검색하고 싶은가, 그리고 어떤 패턴을 검색하고 싶은가로 분리해서 생각할 수 있기 때문이다. 인자 목록으로 파일을 불러 온 후에 :vimgrep 명령을 사용하고 싶은 만큼 반복할 수도 있다.

Search in File, Then Search in Project

:vimgrep에 패턴 필드를 비워두면 현재 검색 패턴을 다시 사용할 수 있다. :substitute 명령과 :global 명령에서도 같은 트릭을 사용할 수 있다. 이 방법은 여러 파일에 걸쳐 정규표현식을 사용할 때 유용하다. 현재 파일에서 정규표현식을 조합하고 적합한 정규표현식을 작성할 때까지 반복한다. 패턴 결과가 마음에 들 때 :vimgrep 명령을 사용한다. 다음은 “don’t”와 “Don’t” 모두 일치하는 정규표현식을 현재 파일 내에서 검색한 후 :vimgrep을 사용한다:

/[Dd]on't
:vim //g *.txt
(1 of 2): Don't watch the clock; do what it does. Keep going.

:vimgrep의 가장 큰 장점은 Vim의 검색 명령과 같은 패턴을 사용할 수 있다는 것이다. 검색 패턴을 사용한 후에 같은 검색 패턴으로 :grep으로 프로젝트 기준 검색을 수행하려면 먼저 POSIX 정규표현식으로 번역해야 한다. 간단한 정규표현식은 오래 걸리지 않겠지만, 복잡한 정규표현식은 하고 싶지 않을 것이다.

Search History and :vimgrep

인자 목록에서 현재 검색 패턴과 일치하는 파일이 얼마나 있는지 확인하기 위해 다음 명령을 사용할 수 있다:

:vim //g ##

주의 깊게 봐야 하는 부분은 항상 인자 목록(##)과 검색 히스토리의 현재 정보를 사용한다는 것이다. 만약 이 명령을 나중에 반복하면 인자 목록과 검색 히스토리에 따라서 다르게 동작할 것이다.

그 대신에 <C-r>/로 검색 필드를 현재 패턴의 값으로 채울 수 있다. 검색 결과는 어느 쪽이든 같지만 명령 히스토리는 다르다.

:vim /<C-r>//g ##

:vimgrep 명령을 다시 사용하더라도 패턴이 명령 히스토리에 포함되어 있기 때문에 더 유용할 것이다.

APPENDIX 1. Customize Vim to Suit Your Preferences

Vim의 설정은 유연하다.

Change Vim’s Settings on the Fly

Vim의 기능과 동작 방식을 변경할 수 있는 수백 가지 설정이 있다(:h option-list). 이 설정은 :set 명령을 사용한다.

‘ignorecase’는 불린(boolean) 값이고, 켜고 끌 수 있다. 기능을 활성하려면:

:set ignorecase

비활성하려면 “no”를 앞에 붙인다:

:set noignorecase

뒤에 느낌표(!)를 붙이면 설정을 토글할 수 있다:

:set ignorecase!

뒤에 물음표(?)를 붙이면 현재 설정 값을 확인할 수 있다:

:set ignorecase?
ignorecase

기본 설정으로 재설정하려면 끝에 &를 붙인다:

:set ignorecase&
:set ignorecase?
noignorecase

Vim 설정 중에는 문자열이나 숫자를 값으로 사용하기도 한다. 예를 들어 ‘tabstop’ 설정은 탭 문자가 나타내는 열 수를 설정한다(:h 'tabstop'):

:set tabstop=2

set 구문 하나로 여러 설정을 지정할 수도 있다:

:set ts=2 sts=2 sw=2 et

‘softtabpstop’, ‘shiftwidth’, ‘expandtab’ 설정은 들여쓰기에도 영향을 준다. 더 많은 것을 알려면 Vimcasts의 에피소드인 탭과 공백을 보라.

설정은 대부분 축약어도 있다. ‘ignorecase’ 설정은 ic로 줄일 수 있어 :se ic!로 토글하거나 :se noic로 비활성할 수 있다. 즉석에서 설정을 변경하는 경우는 축약어로 변경하지만, vimrc 파일에 입력할 때는 가독성을 위해 긴 이름을 사용한다.

Vim 설정은 대부분 전역으로 동작하지만, 일부 설정은 창이나 버퍼로만 제한해서 사용할 수 있다. :setlocal tabstop=4는 활성 버퍼에만 적용된다. 동시에 여러 파일을 열고 있다면 서로 다른 ‘tabstop’ 설정을 각각 지정할 수도 있다. 같은 설정을 모든 버퍼에 적용하려면 다음과 같이 실행한다:

:bufdo setlocal tabstop=4

‘number’설정은 창 단위로 설정할 수 있다. :setlocal number를 입력하면 활성 창에서 행 번호를 표시한다. 모든 창에서 행 번호를 표시하려면 다음 명령을 사용한다:

:windo setlocal number

:setlocal 명령은 현재 창이나 현재 버퍼에서만 설정을 변경할 때 사용할 수 있다(전역으로 사용할 수 있는 설정도 해당한다). :set number를 실행하면 현재 창에서 행 번호를 활성할 뿐만 아니라 전역 기본값도 설정한다. 현재 열려 있는 창은 지역 설정을 유지하지만 새로 열리는 창은 새 전역 설정에 따라 행 번호가 활성된다.

Save Your Configuration in a vimrc File

즉석에서 변경한 Vim 설정이 모두 잘 동작한다. 변경한 설정 중에서 특히 마음에 드는 기능이 있다면 파일로 저장할 수 있다. :source {file} 특정 {file}로부터 설정을 현재 편집 세션으로 불러올 수 있다(:h :source). 파일을 불러오면 파일의 각 행을 Ex 명령으로 여기고 실행한다.

들여쓰기를 두 칸 공백으로 사용하려면 다음과 같이 파일을 생성해서 저장해놓고 필요할 때마다 사용할 수 있다:

customizations/two-space-indent.vim

" Use two spaces for indentation
set tabstop=2
set softtabstop=2
set shiftwidth=2
set expandtab

이 설정을 현재 버퍼에 적용하고 싶다면:

:source two-space-indent.vim

명령행 가장 앞에 붙이는 콜론은 파일로 저장할 때는 필요 없다. :source 명령은 실행 파일의 각 행을 이미 Ex 명령으로 가정한다.

Vim을 시작하면 vimrc 파일이 존재하는지 먼저 확인한다. 파일이 있으면 존재하면 파일의 내용을 자동으로 실행한다.

Vim은 여러 위치에서 vimrc를 찾는다(:h vimrc). 유닉스 시스템에서는 ~/.vimrc 파일을 찾는다. 윈도에서는 $HOME/_vimrc 파일을 찾는다. 시스템과 상관없이 vimrc 파일을 다음 명령으로 열 수 있다:

:edit $MYVIMRC

$MYVIMRC는 Vim에서 사용하는 환경변수로 vimrc 파일의 경로로 확장한다. vimrc 파일을 변경한 후 새로운 설정을 Vim 세션에 반영하려면 다음 명령을 실행한다:

:source $MYVIMRC

vimrc 파일이 활성 버퍼에 열려 있다면 :so %로 줄일 수 있다.

Apply Customizations to Certain Types of Files

설정을 파일 타입에 따라 적용할 수 있다. 예를 들어 루비(Ruby)는 2칸 들여쓰기를 사용하고 자바스크립트(JavaScript)는 4칸 들여쓰기를 사용하는 사내 규정이 있을 수 있다. 다음 설정을 vimrc에 추가할 수 있다:

customizations/filetype-indentation.vim

if has("autocmd")
  filetype on
  autocmd FileType ruby setlocal ts=2 sts=2 sw=2 et
  autocmd FileType javascript setlocal ts=4 sts=4 sw=4 noet
endif

autocmd 문은 이벤트가 발생하면, 특정 명령을 실행하는 선언문이다(:h :autocmd). 이 경우에는 FileType 이벤트를 기다리고 있다가 Vim이 현재 파일의 타입을 감지하면 지정한 명령을 실행한다.

같은 이벤트를 감지하는 하나 이상의 자동 명령(autocommand)을 사용할 수 있다. nodelint를 자바스크립트 파일의 컴파일러로 사용하려면 다음 예제처럼 이벤트를 하나 더 추가할 수 있다:

autocmd FileType javascript compiler nodelint

자바스크립트 파일을 열어서 FileType 이벤트를 호출할 때마다 두 가지 자동 명령을 모두 실행할 것이다.

한두 개 정도의 파일 타입을 설정할 때는 자동 명령을 vimrc에 추가하면 잘 동작한다. 특정 타입의 파일에 설정을 많이 하면 혼란스러워질 것이다. ftplugin은 파일 타입에 따라 설정을 적용할 수 있는 대안 구조이다. 이 플러그인을 사용하면 자바스크립트 설정을 vimrc에 선언하는 대신 ~/.vim/after/ftplugin/javascript.vim 파일 안에 설정을 넣을 수 있다:

customizations/ftplugin/javascript.vim

setlocal ts=4 sts=4 sw=4 noet
compiler nodelint

이 파일은 일반 vimrc 파일과 같지만, 자바스크립트 파일에만 적용한다. 루비 설정을 위해 ftplugin/ruby.vim 파일을 만들 수도 있고 다른 파일 타입에도 적용할 수 있다(:h ftplugin-name).

ftplugin 구조를 사용하기 위해서는 파일 타입 감지와 플러그인을 모두 활성해야 한다. 다음 내용이 vimrc 파일에 있는지 확인한다:

filetype plugin on

Practical Vim cover

Share this:

comments powered by Disqus