Practical Vim 정리

Kim Jin Hyeok·2021년 3월 4일
0

서문

Vim의 방식

Vim은 반복 작업에 최적화되어 있다.

점 명령어

점(.) 명령어는 마지막 변경을 반복한다.

* 명령어

*은 현재 커서 밑 단어를 검색한다.

점 공식

키 입력 한 번으로 이동, 키 입력 한 번으로 실행하기

모드

일반 모드

붓을 놓고 잠시 멈추기

언제 삽입 모드에서 일반 모드로 변경하냐면, 취향 문제이긴 하나 글을 작성하다가 멈춰서 생각이 필요할 때마다 삽입 모드를 벗어난다.

단어 삭제

단어를 삭제할 때 커서의 위치에 상관 없이 사용할 수 있는 daw가 좋다. 반복하기 좋기 때문이다.

간단한 가감 연산

커서 아래, 혹은 커서 아래가 숫자가 아닐 경우 커서 이후 숫자로 이동한 후 가감 연산을 하는 방법이다.

  • <C-a> : 증가
  • <C-x> : 감소

오퍼레이터 + 모션 = 행동

d{모션} 명령은 모션 범위에 따라 문자 하나(dl), 단어 하나(daw)를 제거한다. 동일한 규칙은 c{모션}, y{모션} 등에도 적용되며 이러한 명령을 오퍼레이터 operator 라고 한다.

  • c : 변경 change
  • d : 삭제 delete
  • y : 레지스터로 복사 yaked
  • g~ : 대소문자 변환
  • gu : 소문자로 변환
  • gU : 대문자로 변환(gUaw=단어를 대문자로 변환)
  • <, > : 탭 이동
  • = : 자동 들여쓰기
  • ! : {모션}에 해당되는 행을 외부 프로그램을 사용해 필터

커스텀 오퍼레이터, 커스텀 모션

기본 제공 외에 유저들이 만든 플러그인으로 여러 커스텀 오퍼레이터, 커스텀 모션을 사용할 수 있다.

삽입 모드

Vim의 명령은 대부분 삽입 모드 외에서 사용 가능하지만, 삽입 모드에서 사용할 수 있는 명령도 있다.

삽입 모드에서 바로 교정하기

사실 타자 속도가 빠르면 지우고 다시 쓰는게 더 빠를 수 있다.

다른 방법은 아래와 같다.

  • <C-h> : 앞 글자 하나 제거(==Backspace)
  • <C-w> : 앞 단어 하나 제거
  • <C-u> : 행의 시작 부반까지 제거

삽입-일반 모드

  • <C-o> : 삽입-일반 모드
    삽입-일반 모드 insert normal mode 를 사용하면 삽입 모드에서 일반 모드로 가서 명령 하나를 실행하고 다시 삽입 모드로 돌아올 수 있다.

예를 들어 삽입 모드에서 편집 중, 현재 행을 화면 중간으로 이동시키는 zz왜 조합해서<C-o>zz 같이 사용할 수 있다.

삽입 모드에서 레지스터 붙여넣기

  • <C-r>0 : 레지스터 붙여넣기 (0은 레지스터 번호)

삽입 모드에서 산술 계산

표현식 레지스터를 이용해 삽입 모드에서 산술 계산을 할 수 있다.

  • <C-r> = {계산식} Enter

문자 코드를 이용한 특수 문자 입력

  • <C-v>{123} : 8진수 코드
  • <C-v>u{123} : 16진수 코드
  • <C-k>{문자1}{문자2} : 이중자(digraph) 문자
    이중자 예시 : ½ == <C-k>12

치환 모드, 선택 치환 모드

  • R : 치환 모드 replace mode
  • gR : 선택 치환 모드 virtual replace mode, 탭 문자를 공백으로 처리
  • r, gr : 문자 하나 치환

비주얼 모드

비주얼 모드 활성화

  • v : 문자 단위 character-wise 비주얼 모드
  • V : 행 단위 line-wise
  • <C-v> : 블록 단위 block-wise
  • gv : 가장 최근 비주얼 모드 영역

비주얼 모드 간 전환

  • Esc : 일반모드로 전환
  • o : 선택 영역 반대쪽 끝으로 이동

명령행 모드

명령행 모드는 Ex 명령(:), 검색 패턴(/), 표현식(<C-r>=)을 입력 시 활성화된다.

버퍼 문서 작업 시 사용할 수 있는 Ex 명령

  • :[범위]delete [x] : 행 삭제(레지스터 x에 저장),d
  • :[범위]yank [x] : 행 복사(레지스터 x에 저장)
  • :[행]put [x] : 행 붙여넣기(레지스터 x로부터)
  • :[범위]copy {주소} : 행 복사 후 주소 행 아래에 붙여넣기,t
  • :[범위]move {주소} : 행을 주소 행 아래로 이동하기,m
  • :[범위]join : 지정한 행을 한 줄로 연결하기
  • :[범위]normal {명령} : 일반 모드 명령을 범위 각각 행에서 실행
  • :[범위]substitute/패턴/문자열/플래그 : 치환
  • :[범위]global/패턴/명령 : 전역 명령

어디에서나 광범위하게 활용할 수 있다는 장점이 있다. 즉 직접 커서를 옮기지 않아도 된다.

또 y,p와 다르게 copy, move는 레지스터를 사용하지 않는다.

명령행 모드에서 특수키

삽입 모드에서 사용하는 것 대부분 사용할 수 있다.
<C-w> <C-u> <C-v> <C-k> 등

범위

  • 숫자 : 행 번호
  • 시작,끝 : 범위이며 기호도 쓸 수 있다.
  • $ : 마지막 행
  • . : 현재 커서 행
  • % : 파일 전체(==1,$)

비주얼 모드로 범위 지정 후 명령

비주얼 모드로 영역 지정 후 :를 누르면 '<,'> 로 범위 지정되서 명령을 쓸 수 있다. 저 기호는 각각 비주얼 영역의 첫 행과 마지막 행을 의미한다.

패턴으로 범위 지정

:/<html>/,/</html>/d 처럼 패턴도 쓸 수 있다.

오프셋으로 주소 수정

오프셋으로 디테일한 범위 지정이 가능하다.
예를 들어 html 태그 자체는 제외하고 내부를 삭제하고 싶다면
:/<html>/+1/</html>/-1d
처럼 사용할 수 있다.

탭으로 Ex 명령 자동완성

  • <Tab> : 추천 목록 순회
  • <S-Tab> : 역순
  • <C-d> : 추천 목록 출력

zsh 처럼 세팅할 경우,

set wildmenu
set wildmode=full

이러면 탭만으로 선택된 것이 하이라이트된 상태로 목록 출력

현재 커서의 단어를 명령행으로 올리기

  • <C-r><C-w> : (명령행모드에서) 현재 단어(word)를 명령행으로 복사
  • <C-r><C-a> : 현재 단어(WORD)를 복사

:로 진입해서 사용하면 현재 커서의 단어가 복사되서 올라간다.

이를 치환 등의 명령과 응용하면 좋다. 또는 vimrc 설정을 알고 싶을 때 해당 설정으로 커서 옮기고 :help CrCw 하면 바로 확인할 수 있다.

히스토리에서 명령 재호출

명령행 모드에서의 활동은 히스토리로 기록된다. Vim을 종료해도 지워지지 않는다.

  • @: : 가장 최근 Ex 명령 재실행
  • q/ : 검색 히스토리 창 열기
  • q: : Ex 명령 히스토리 창 열기
  • <Up>, <Down> : 히스토리 탐색
  • <C-f> : 명령행 모드에서 히스토리 창 열기

기본값은 20개인데 제한을 더 늘릴 것을 권장한다.

set history=200

셸 명령 실행하기

Vim을 벗어나지 않고 간단하게 외부 셸을 사용할 수 있다.

  • :!명령 : 간단한 명령
  • :shell : 셸로 전환
  • exit : 셸에서 vim으로 전환

셸 명령의 결과를 표준 입출력으로 버퍼로 불러와 쓸 수도 있는데 별로인 것 같다.

배치를 사용한 여러 Ex 명령 구동

  • :source 파일명 : 배치 스크립트 실행

파일

여러 파일 관리하기

Vim은 여러 파일을 관리할 수 있도록 버퍼 목록을 제공한다.

버퍼 목록

파일과 버퍼의 차이점

Vim은 파일에 실제로 접근해서 편집하는 것이 아닌 메모리 공간에 파일을 복사해서 편집을 하는데, 이 메모리에 존재하는 파일의 사본을 Vim에서 사용하는 용어로 버퍼 buffer 라고 한다.

버퍼 목록 사용하기

  • :ls : 현재 버퍼 목록 출력
  • :bp : 목록에서 이전 버퍼를 현재 창에 띄우기
  • :bn : 목록에서 다음 버퍼를 현재 창에 띄우기
  • :bf : 첫 번째 버퍼
  • :bl : 마지막 버퍼
  • :b번호 : 해당 번호의 버퍼로 이동
  • :bd n1 n2 : 버퍼 제거
  • :n,m bd : n~m 까지 버퍼 제거
  • <C-^> : 이전 버퍼와 현재 버퍼 전환

아래처럼 매핑해서 쓰면 편하다.

nnoremap <silent> [b :bprevious<CR>
nnoremap <silent> ]b :bnext<CR>
nnoremap <silent> [B :bfirst<CR>
nnoremap <silent> ]B :blast<CR>

인자 목록

인자 목록 arguments list 은 파일들을 쉽게 관리하기 위해 그룹으로 묶는 기능을 제공한다.

  • :args : 인자 목록 출력
  • :args목록 : 파일명, 글롭, 셸 명령의 출력으로 인자 목록 갱신

글롭

와일드카드를 조합해 파일들을 인자 목록으로 가져오는 방법을 글롭 glob 라고 한다.

  • ** : *와 다르게 재귀적으로 탐색
  • args **/*.js

백틱(`)으로 파일 지정하기

백택 안의 문자를 셸 명령으로 처리한다.

예를 들어 파일 목록들이 적힌 파일이 있다면,
:args `cat fileList.txt`
로 내부 내용을 읽어 인자 목록을 갱신할 수 있다.

인자 목록 사용하기

  • :next, :prev : 인자 목록의 이전, 다음 파일을 버퍼로 불러오기
  • :argdo : 인자 목록의 각각 버퍼의 동일한 명령 실행

숨김 파일 관리

여기서 숨김 파일은 수정된 버퍼가 저장하지 않고 숨겨진 경우를 의미한다.

버퍼를 수정한 상태(+)에서 버퍼를 전환하려고 하면 저장하든가 !로 강제 전환하라고 하는데 강제 전환 할 경우 기존 버퍼는 숨김 상태(h)가 된다.

종료 시 숨김 버퍼 처리하기

vim 종료 시 숨김 됬던 버퍼를 어떻게 처리할지 묻는다.

  • w : 변경된 버퍼 내용을 반영
  • e! : 디스크 내용을 다시 읽어 버퍼에 반영(즉, 변경을 취소)
  • qa! : 모든 창을 닫고, 모든 변경을 취소
  • wa : 변경한 모든 버퍼를 저장

*.do 명령 사용 전 hidden 설정 활성화

*.do 명령은 순차적으로 목록에 실행되는데 만약 버퍼를 수정하는 내용이 있다면, 작업 후 넘어갈 때 오류가 발생한다.

:argdo명령 은 아래 처럼 작동한다.

:first
{command}
:next
{command}
...반복

여기서 next때 오류가 발생한다. 이를 해결하기 위해 hidden 설정(set hidden)을 사용하면 느낌표를 붙이지 않고 n, bn, cn 등을 사용할 수 있다.

작업 후에는 :argdo w (또는 :wa)로 일괄 저장할 수 있다.

작업 환경 창 분리하기

  • <C-w>s, :sp : 수평 분리
  • <C-w>v, :vs : 수직 분리

활성화 창 변경하기

  • <C-w>w : 열린 창 순회
  • <C-w>h,j,k,l : 각 방향의 창으로 활성화

창 닫기

  • <C-w>c, :clo[se] : 활성화 창 닫기
  • <C-w>o, :on[ly] : 활성화 창 빼고 다 닫기

창 크기 조절 및 재정렬

  • <C-w>= : 모든 창 높이, 폭 균등화
  • <C-w>_ : 활성창 높이 최대화
  • <C-w>| : 활성창 폭 최대화
  • {숫자}<C-w>_ : 활성창 높이 조절
  • {숫자}<C-w>| : 활성창 폭 조절

탭으로 창 레이아웃 관리


터미널 탭, tmux, vim-airline 버퍼 리스트로 대체 가능


파일 열기와 저장하기

파일 경로와 :edit 명령으로 파일 열기

절대 경로는 물론 현재 작업 디렉터리 기준으로 상대 경로도 사용할 수 있다.

  • :edit {file}
  • :pwd : print working directory

파일 명과 :find 명령으로 파일 열기

:find 를 이용하면 경로를 입력하지 않고도 파일을 열 수 있다.

하지만 먼저 path 를 설정해야 한다.

:set path+=./**

예시로, 위 명령은 현재 디렉터리 아래 모든 디렉토리를 path 로 설정한다.

  • :find {file} : path를 근거로 파일을 찾는다.

만약 동일한 이름의 파일이 있다면 탭으로 고를 수 있다.

netrw로 파일 시스템 탐색


NERDTree로 대체 가능


존재하지 않는 디렉터리에 파일 저장하기

Vim 은 디렉터리 존재 여부와 상관 없이 새로운 버퍼를 생성하지만, 존재하지 않는 디렉터리에 버퍼를 저장(:write)하려고 하면 에러가 발생한다.

이 문제는 외부 mkdir 호출로 해결할 수 있다.

:!mkdir -p %:h
:write

-p 는 mkdir 에서 존재하지 않는 디렉터리가 있다면 생성하라는 플래그이다.
% 는 현재 활성 버퍼의 경로, :h 는 파일 경로에서 파일명을 제거한다는 의미이다.

관리자 권한으로 파일 저장하기

읽기 전용 파일 등을 편집하고 저장이 안될 경우, sudo vim 이나 sudoedit vim 으로 관리자 권한으로 다시 vim을 실행하면 된다.

하지만 vim을 껐다 켜지 않고 외부 명령어로 바로 저장하는 방법도 있다.

:w !sudo tee % > {dir/file}

빠르게 이동하기

모션 motion 은 Vim을 조작하는데 중요한 명령 중 하나이다. 단순히 커서 이동 뿐만 아니라 오퍼레이터-대기 모드 사용 중 문서의 범위를 조작할 때도 사용한다.

어떤 모션이 어떤 상왕에 유용한지, 또 파일 간 이동을 더 빠르게 하는 뛰어넘기에 관한 내용이다.

모션으로 파일 내부 탐색하기

키보드 중앙에서 벗어나지 않고 타자 입력하기

방향키 대신 hjkl 사용 권장

실제 행과 표시 행 구분하기


줄바꿈 처리될 만큼의 긴 문자열을 편집할 경우가 거의 없다. 또 행 번호 설정해놓으면 햇갈릴 일이 없다.


단어 단위로 이동하기

h, l로 열을 하나 하나 이동하는 것보다 훨씬 빠르다.

  • w : 다음 단어의 시작 위치
  • b : 현재 단어의 시작 위치 또는 이전 단어의 시작 위치
  • e : 현재 단어의 마지막 위치 또는 다음 단어의 마지막 위치
  • ge : 이전 단어의 마지막 위치

'단어의 끝에 덧붙이기'라는 뜻으로, ea, gea를 하나의 명령으로 쓸 때가 많다.

word인지 WORD인지 파악하기

word는 문자, 숫자, 밑줄 또는 다른 논블럭 문자의 연속으로 이뤄지고 공백으로 분리된 단위를 의미한다.

WORD는 단순하게 문자의 연속이며 공백으로 분리된 경우이다.

위 명령들의 WORD 단위 모션 명령은 W, B, E, gE 이다.

문자로 찾기

행 안에서 빠르게 이동해야 할 경우 유용하다.

  • f{문자} : 현재 커서 위치에서 현재 행 끝까지의 범위에서 문자 검색 후 찾으면 커서 이동
  • F{문자} : 현재 커서에서 이전 위치로 이동
  • t{문자} : 검색 후 다음 위치로 커서 이동
  • T{문자} : 검색 후 이전 위치 앞으로 이동
  • ; : 최근 수행했던 문자 검색 재수행
  • , : 역방향으로 최근 검색 수행

find, till로 외우자.

빈도가 적은 문자로 찾기

예를 들어 excellent 라는 단어를 지우려고 검색할 때 e보다 x로 접근하는 것이 더 빠르다.

이동을 위해 검색하기

문자 검색(f, t)는 가볍지만 한 문자, 현재 행이라는 제한을 가진다.

문자를 하나 이상 검색하고 싶거나, 현재 행을 넘는 범위에서 찾고 싶다면 검색 명령을 이용한다.

  • /{단어}<CR> : 검색 명령
  • n : 다음 결과(순방향)
  • N : 이전 결과(역방향)

이를 이용하여 행을 넘어 원하는 위치로 즉시 이동할 수 있다.

검색 모션으로 조작하기

검색 명령은 일반 모드 뿐만 아니라 동작 대기 모드(오퍼레이터), 비주얼 모드에서도 사용할 수 있다.



예제를 따라하되 고런갑다 하고 빠르게 넘어갈 것

출처: Drew Nail, Practical Vim(2015)

0개의 댓글