http://www.vim.org
아아... 몇 년 동안 사용해 오면서 꽤 숙달되었다고 생각했었고, 텍스트 에디터 사용법을 알기 위해 비싼 책을 살 필요가 있나 싶었는데... 정말 쥐뿔도 모르고 사용해 왔었다는 것을 깨닫게 되었다... 팁이 보이는 대로 여기에 적어 두기로 함.
HKEY_LOCAL_MACHINE
|- Software
|- Microsoft
|- Internet Explorer
|- View Source Editor
|- Editor Name (Default) = D:\Local\vim\vim62\gvim.exe (gvim.exe 의 경로)
이 때 소스 보기를 하면 임시로 생성되는 파일의 확장자가 html이 아니라서 vi가 html임을 인식하지 못한다. 다음과 같이 하면 더 낫다.
위 레지스트리에서 gvim.exe 대신에 gvimweb.bat 으로 바꾸고
gvimweb.bat 의 내용은
start D:\Local\vim\vim62\gvim.exe -c "set ft=html" %1
settabstop=8 "진짜 탭은 8칸으로setsofttabstop=4 "탭 키를 누르면 스페이스 4개 삽입setshiftwidth=4 "<, >키로 줄을 밀거나 당길때setbackspace=2 "백스페이스를 누르면 sts값만큼 움직임setexpandtab"탭을 항상 스페이스로 변환 noexpandtab 은 스페이스가 tabstop 값만큼 되면 탭으로 변환
[vim 다운로드 페이지]에서 "iconv library", "newer intl library"에 있는 링크를 찾아가서 파일을 받은 후에, 다음 두 파일을 gvim.exe가 있는 곳에 복사
libiconv 쪽에서 iconv.dll
gettext-runtime 쪽에서 intl.dll (libintl.dll 로 이름을 바꿔서 옮겨줄 것)
이제는 gvim의 메시지가 제대로 변환이 되면서 출력된다.
그 다음은 5번 문제, "MS Mincho"글꼴은 일본어와 한글이 다 잘 나오지만 너무 보기 안 좋다는 건데...
일본어와 한글의 글꼴을 각각 지정할 수 있으면 좋겠지만 그 방법을 찾기 어려워서, 한글 글꼴을 포기하고 영문만 나눔고딕코딩을 계속 쓰는 정도로 타협
set guifont=NanumGothicCoding:h10:cHANGEUL - 나눔고딕을 적용하고
set guifontwide=MS\ Mincho:h10 - 폭이 두 배인 글자에 대한 글꼴은 MS Mincho로 지정
아래 스크린샷은 글자 높이를 h10으로 지정했을 때. 더 크면 좀 더 봐줄만하긴 하다.
윈도우에서는 fontlink란 걸 써서3, 어떤 베이스 폰트에서 표시할 수 없는 글자는 그 베이스 폰트에 링크된 대체 폰트에서 찾아서 표시를 해 준다고 한다4 따라서, '나눔고딕코딩'글꼴에 'MS Mincho'글꼴을 링크하면 나눔고딕코딩으로 표시할 수 없는 문자만 MS Mincho를 사용하여 표시하게 할 수 있다.
링크하는 방법5:
regedit로 레지스트리 에디터를 연다
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink로 이동
나눔고딕코딩 글꼴 항목이 이미 있다면 수정, 없으면 새로 만들기 - 다중 문자열 값
이름
NanumGothicCoding
값 데이터: (아래 둘 중 하나만 써도 될 것 같은데 재부팅해가면서 확인하기 귀찮아서 둘 다 넣었음)
MSMINCHO.TTF,MS Mincho
MSMINCHO.TTC,MS Mincho
재부팅
다음과 같이 한글까지도 나눔고딕코딩으로 잘 나온다.
(그런데 첫번째 방법과 비교하면 일본어와 한자 글꼴이 다르다. 왜 다른지는 모르겠다)
split 이나 new 등으로 vim 창 안에서 윈도우를 둘 이상으로 분할할 경우 각 윈도우 하단에 파일명이 적힌 상태표시줄이 나타나는데, 이걸 자신의 입맛에 맞게 설정할 수 있다.
" 상태표시줄에 출력할 내용들setstatusline=%F\ %m%h%r%<%=\ [%{&ff},%{&fenc}]\ [%Y]\ [%l,%v]\ [%L]\ [%p%%]
" 윈도우가 하나 뿐일 때도 상태표시줄이 나타나도록setlaststatus=2
상태표시줄에 출력할 수 있는 내용들의 종류에 대해서는 :help statusline
여러 윈도우들 중에 현재 편집 중인 윈도우의 상태표시줄에 대해 특별히 더 꾸며주고 싶다면, highlight 명령으로 StatusLine 항목에 정의해주면 된다.
hi StatusLine term=bold,reversecterm=bold,reversegui=bold,reversectermfg=Blue guifg=Blue
foreground 색상을 Blue 로 했는데, 이게 reverse가 되니까 결과적으로 상태표시줄의 배경색이 파란색이 된다.
bold,reverse는 기본값이라서 사실 생략해도 무방할 듯
입력 모드일 때와 명령 모드일 때 상태표시줄의 색상을 또 다르게 바꿔줄 수 있다.
" 입력 모드로 들어갈 때는 녹색으로, 입력 모드를 빠져나올 때는 파란색으로au InsertEnter * hi StatusLine ctermfg=DarkGreen guifg=DarkGreen
au InsertLeave * hi StatusLine ctermfg=Blue guifg=Blue
(파일명, 읽기전용여부, 수정여부, 파일줄바꿈포맷, 파일인코딩(이게 아주 요긴함), 파일타입, 행번호 등등을 출력시켰음. 파란색 상태표시줄이 현재 편집중인 창)
창을 여러 번 분할해서 상태표시줄 길이가 짧아질 경우 내용이 잘리는데, 상태표시줄을 두 줄 이상 나오게 할 설정법은 없는 듯
저 색상이 맘에 들어서 적용해봤다. 다운받아서 vimfiles 폴더 아래에 colors, autoload, doc 디렉토리 안에 각각 파일을 복사해주고.
윈도우 gvim 설정:
" solarizedsetbackground=light
call togglebg#map("") " 이 라인을 넣어줘야, 이후에 <F5>를 눌러 배경색 토글을 할 수 있다.let g:solarized_italic=0" 이건 주석 라인이 이탤릭체로 나오는게 싫어서colorscheme solarized
그런데 PuTTY로 리눅스 서버에 접속해서도 마찬가지로 적용하고 싶어서 시도했다가 좀 헤맸다.
putty에 설정하는 내용은 PuTTY#solarized 참고
그러면 일단 putty 로 접속하는 것 자체에 저 색상이 적용되긴 하는데... 막상 vim(vim 은 아직 컬러스킴을 적용하지 않은 상태)을 띄워보면,
(왼쪽 위가 putty+vim, 오른쪽 아래가 gvim)
배경은 똑같은데 키워드들의 하일라이트 색상이 다르다. 뭐 큰 지장이 있는 건 아닌데 그래도 맘에 안 든다.
그래서 이 상태에서 다시 vim 설정에도 위와 같이 solarized 를 설치하고 .vimrc 에 똑같이 적어줬더만 이번엔 배경색이 미묘하게 달라져버리고, 글자들도 일부 키워드에만 따로 배경색이 적용되어서 정말 흉하게 나왔다.
(반대로, putty에는 적용하지 않고 vim에만 적용하면... 역시 흉하게 나온다. colors/solarized.vim 파일을 열어보니, gvim에서는 일일이 색상값을 할당하지만, GUI모드가 아닌 vim에서는 터미널의 디폴트 색상을 사용하여 적용하고, 실제 색이 바뀌는 건 터미널 에뮬레이터의 팔레트를 조절하는 식으로 되어 있는 듯 하다)
뒤져보니 http://stackoverflow.com/a/5561823/1150133 에 이 컬러스킴 제작자가 친히 리플을 달았더라.
sett_Co=16 " 이 값이 원래는 8이었는데, 16으로 바꿔줌...colorscheme solarized
위와 같이 t_Co 값을 16으로 해주니, 이젠 완전히 동일하게 나온다. (딱 한가지, 배경이 light일 때, 커서의 색상이 너무 옅어서 잘 안 보인다. 해결법은 모르겠음)
두 줄을 추가하여 해결함.
저 링크 글에 보면 smartindent 옵션이 적용될 때 문제 같은데, 저 글에 다른 답변글에서도 언급하고 있지만 :help smartindent해 보면
When typing '#' as the first character in a new line, the indent for
that line is removed, the '#' is put in the first column. The indent
is restored for the next line. If you don't want this, use this
mapping: ":inoremap # X^H#", where ^H is entered with CTRL-V CTRL-H.
이렇게 정확히 해당 문제와(애초에 이게 문제가 아니라 의도된 기능인 듯?) 그 해결법도 나와 있긴 한데, 막상 해봐도 제대로 안 되더라.
1.21. 따옴표(괄호, 부등호 등) 안의 내용을 통채로 지우기 - Text object selection
출처: https://twitter.com/vimtips/statuses/270934644202041344[motion.txt] 도움말을 보면 커서를 이동시키는 수많은(정말 수많은) 명령어들이 있다. 그 중 [6장]에 보면 "Text object selection" 항목이 있는데, 비주얼 모드에 들어가 있거나 c(change), d(delete), y(yank) 등의 명령어 뒤에서 쓰일 수 있는 이동 명령어들이다. 초반에는 단어 단위, 문장 단위, 단락 단위로 커서를 움직일 수 있는 방법이 나오고, 그 다음 나오는 것들이 쏠쏠하다.
a 뒤에
] 또는 [ - [ ] 블럭
) 또는 ( - ( ) 블럭
> 또는 < - < > 블럭
} 또는 { - { } 블럭
" - " " 블럭
' - ' ' 블럭
` - ` ` 블럭
t - <aaa>...</aaa> 태그 블럭
i 뒤에
위와 마찬가지인데, 블럭 경계기호는 제외한 그 안의 것
즉, 현재 커서가 있는 위치를 둘러싸고 있는 블럭을 찾아서 그 블럭의 내용을 통채로 삭제하거나 복사하거나 할 수 있다. 특히나 블럭이 중첩되어 있을 때, 블럭의 좌우 괄호의 갯수를 손으로 세어가며 찾을 필요가 없음
예를 들어보면, 먼저 a를 쓰는 경우
y = (1+(2+(3+(4+func()))));
^ 커서가 여기 있을 때 da( 순, 또는 da) 순으로 누르면 "delete a () block"
y = (1+(2+(3+ )));
이렇게 괄호까지 포함하여 지워지고
y = (1+(2+(3+)));
^ 커서 위치
이번에는 d(delete) 대신에 c(change)를, a 대신에 i 를 썼을 때:
y = (1+(2+(3+(4+func()))));
^ 커서가 여기 있을 때 ci( 순으로 누르면 "change inner () block"
y = (1+( ));
이렇게 괄호는 남아 있고 그 안의 내용만 지워지고
y = (1+());
^ 커서 위치는 이 )괄호 앞에서 입력 모드로 깜박거림
앞에 카운트를 넣어서 단계도 조절할 수 있다.
y = (1+(2+(3+(4+func()))));
^ 커서가 여기 있을 때 c2i( 순으로 누르면
y = (1+(2+( )));
2단계 중첩된 괄호 안의 내용이 지워지고,
(커서 위치에서 좌측으로 2번째 만나는 여는괄호를 찾고, 거기에 대응되는 닫는괄호까지 매치됨)
y = (1+(2+()));
^ 커서 위치는 이 괄호 앞에서 입력 모드
() 블락 뿐 아니라 암튼 좌우에 기호를 넣어 표시하는 웬만한 블럭은 다 된다. 심지어 html,xml 태그도 가능:
<b><i>long long long <s>long</s> long text</i></b>
^ 커서가 여기 있을 때 cit 순으로 누르면
<b><i></i></b>
^ <i>..</i>태그 안의 텍스트는 다 지워지고 여기서 입력 모드
사용하다보니 c뿐 아니라 yank와 같이 쓰는 것도 아주 쏠쏠하다. 어떤 태그로 둘러쌓인 부분(예를 들어 "<b>bold text</b>") 안에 커서를 놓고 yat하면 시작태그부터 끝태그까지의 내용이 복사되고 paste로 붙여넣을 수 있다. 마우스로 긁거나 SHIFT+커서키 조합으로 블락을 지정해서 복사하는 것보다 훨씬 편함.
gvim 으로 link.txt 를 열어서 수정하고 저장하는 순간, link.txt가 심볼릭 링크가 아니라 일반 파일로 바뀌어버린다.
이것은 기존 파일을 저장할 때 백업파일을 만드는 방식이, 기존 파일의 이름을 바꾸고 그 자리에 새 파일을 만드는 형태를 택했을 때 발생하는데, backupcopy 옵션값을 가지고 바꿀 수 있다.
set backupcopy=yes - 원본 파일의 사본을 만들어 백업본으로 저장하고, 원본 파일을 덮어씀
=no - 원본 파일의 이름을 바꾸어 백업본으로 저장하고, 새 파일을 생성함
=auto - 디폴트. 두 방식 중 적절한 것을 사용
f{문자} 커서 위치에서 오른쪽 방향에 있는 {문자}까지 이동
F{문자} 커서 위치에서 왼쪽 방향에 있는 {문자}까지 이동
t{문자} 커서 위치에서 오른쪽 방향에 있는 {문자}의 바로 직전까지 이동
T{문자} 커서 위치에서 왼쪽 방향에 있는 {문자}의 바로 직후까지 이동
앞에 숫자를 넣어서, 예를 들어 3fa라고 하면 커서 위치에서 오른쪽 방향으로 가다가 세 번째로 a가 나타나는 곳까지 이동한다.
단지 커서만 이동할 거면 그냥 /를 써서 검색을 해도 되겠는데, 이게 삭제 등 다른 명령과 같이 쓰면 요긴하다.
$str = "very long long long long long";
^ 커서가 여기 있을 때 dt" 를 입력하면
$str = "very long long";
^ 따옴표 직전까지의 내용이 삭제된다.
예를 들어 textwidth 값을 바꿔서 한 행에 들어갈 글자 수를 바꿨을 때, 현재 작성되어 있는 텍스트에 적용하려면 gq를 사용한다. gq 뒤에 커서 이동을 하면 그 위치 방향에 있는 텍스트를 변경한다. 처음부터 끝까지 바꾸고 싶으면 gggqG 같은 식으로.
또는 비주얼 블락을 잡은 후에 gq해서 선택 영역만 변경.
그리고 템플릿을 만들다보면 불가피하게 계속 div 안에 div 안에 div 안에... 이런 식으로 만들게 되는데, (서툴러서 그런가...) 태그들이 제대로 열고 닫는 매치가 되고 있는지도 걱정되고, 여는 태그에 대응되는 닫는 태그 찾는 것도 일이라서 불편하다.
일단 vim의 기본 기능 중에 visual block을 응용하는 법이 있다.
" Convert slashes to backslashes for Windows.ifhas('win32')nmap ,cs :let @*=substitute(expand("%"), "/", "\\", "g")<CR>nmap ,cl :let @*=substitute(expand("%:p"), "/", "\\", "g")<CR> " This will copy the path in 8.3 short format, for DOS and Windows 9xnmap ,c8 :let @*=substitute(expand("%:p:8"), "/", "\\", "g")<CR>elsenmap ,cs :let @*=expand("%")<CR>nmap ,cl :let @*=expand("%:p")<CR>endif
위의 키매핑 설정을 .vimrc 파일에 저장한다.
,cs : 파일명을 클립보드에 저장. 이 파일명은 현재 vim에서 열고 있는 기준이라서, 하위 디렉토리에 있는 경우는 dir/filename 형태로 복사되더라. (맥에서만 테스트한 상태)
:%s/pattern//gn" Omit g to display the number of lines where the pattern matches:
:%s/pattern//n" To restrict the count to a region of the text, specify a range instead of % (% means all lines)." For example, the following counts the number of occurrences in lines 10 to 50 inclusive:
:10,50s/pattern//gn
" The following counts the number of occurrences in the lines in the most recent visual selection.
:'<,'>s/pattern//gn" Word under cursorEdit" To count the number of occurrences of the last used search pattern, you can leave out the pattern entirely:
:%s///gn" To access this quickly, define a shortcut command likemap ,* *<C-O>:%s///gn<CR>
검색 패턴 중에 어떤 문자는 문자 그 자체를 의미하고, 앞에 백슬래쉬를 붙이면 특수한 의미가 된다. 반면 어떤 문자는 백슬래쉬 없이 쓸 때 특수한 의미가 있고, 백슬래쉬를 붙이면 그제서야 문자 그 자체를 의미한다:
+는 "+"문자 자체, \+는 1개 이상의 반복
*는 0개 이상의 반복, \*는 "*"문자 자체
잘은 모르겠지만, 오리지널 vi에서와 최대한 호환성을 유지하기 위해 메타캐릭터를 기본적으로는 최소한의 것만 제공하고, 그 외에는 백슬래쉬를 붙여서 쓰도록 하는 느낌이다. Perl/정규표현식에서는 *, +, (), {} 등이 전부 특수한 의미를 가지고 있다. 그러다보니 vim을 쓸 때와 혼동되곤 한다.
어떤 문자가 문자 자체로 해석될지 특수한 의미로 해석될지 여부를 조절하는 데 magic 옵션을 쓸 수 있다. 또한, 검색 패턴 내에 \m, \M, \v, \V를 삽입하여 일시적으로 지정할 수도 있다.
\m 이후에 오는 패턴은, magic 옵션이 켜져 있을 때처럼 해석된다.
\M 이후에 오는 패턴은, nomagic 옵션을 썼을 때처럼 해석된다.
\v 이후에 오는 패턴은, '0'-'9', 'a'-'z', 'A'-'Z', '_'를 제외하곤 전부 특수한 의미로 해석된다. "very magic"
\V 이후에 오는 패턴은, 오직 백슬래쉬만이 특수한 의미로 해석된다. "very nomagic"
예:
지정: \v \m \M \V 매치되는 것
'magic' 'nomagic'
$ $ $ \$ 라인의 끝
. . \. \. 임의의 문자
* * \* \* 직전 원소의 0번 이상의 반복
() \(\) \(\) \(\) 그룹
| \| \| \| 얼터너티브
\a \a \a \a 알파벳 문자
\\ \\ \\ \\ 백슬래쉬 자체
\. \. . . 마침표 자체
\{ { { { '{' 자체
a a a a 'a' 자체
따로 지정하지 않을 경우 set magic 상태가 기본이며7, 문서에서는 호환성 문제를 없애기 위해 이 상태로 사용하는 것을 권장하고 있다.
Perl 정규표현식과 그나마 최대한 비슷하게 사용하려면 \v를 사용한다:
레퍼런스 문서의 [2장 패턴의 정의] 부분을 보다 발견한 것.
"or"에 해당하는 \|에 대응되어서, "and"에 해당하는 \&도 있다. 하나 이상의 concat8을 \&로 연결할 경우, 이 패턴은 문자열의 한 위치에서 모든 concat이 다 매치할 때에 한해서, 마지막 concat에 매치된다. 이건 Perl에는 없고 vim에만 있는 기능이다.
"foobeep\&..."는 "foobeep"의 "foo"에 매치된다.
String : ....... foobeep .......
current position : ^
concat 1 : foobeep
concat 2 : ...
".*Peter\&.*Bob"은 "Peter"와 "Bob"이 둘 다 들어있는 라인 전체에 매치된다.
이건 결국 lookahead 검색과 동일하나, 아래 얘기할 lookahead에 비해 쓰기 간편하다.
Perl/정규표현식에 있는 lookahead와 lookbehind를 vim에서도 쓸 수 있는데 형태가 좀 다르다. 먼저 검색할 원소를 적은 후에 뒤에 다음 기호를 붙인다.
\@=, \@! : lookahead.
\@<=, \@<! : lookbehind.
예제를 보면:
Example matches ~
foo\(bar\)\@= "foobar"의 "foo"
foo\(bar\)\@=foo 이건 절대 매치되지 않는다
foo\(bar\)\@! 바로 뒤에 "bar"가 오지 않는 "foo"
a.\{-}p\@! "a", "ap", "app", 등. 더 이상 p가 오지 않을 때까지.
if \(\(then\)\@!.\)*$ 뒤쪽에 "then"이 오지 않는 "if "
\(an\_s\+\)\@<=file "an" 뒤에 공백 또는 라인의 끝 뒤에 오는 "file"
\(foo\)\@<!bar "foobar"의 경우만 제외한 "bar"
\(\/\/.*\)\@<!in 앞쪽에 "//"가 나오지 않는 경우의 "in"
[Perl compatible regular expressions - Vim Tips Wiki] 참고
vim을 컴파일할 때 perl을 지원하게 했다면, (:ver 했을 때 +perl 또는 +perl/dyn이 있으면 됨)
:perldo s/searchme/replaceme/g 이런 식으로 쓸 수 있음.
윈도우 gvim 의 경우는 perldo 명령을 실행했을 때 perl**.dll 이 없다고 에러가 날 수 있는데, [strawberry perl]의 해당 버전의 압축파일을 받아서 dll 만 vim이 있는 곳에 넣어 주면 된다. 그런데 perl58.dll이 필요하다고 할 때 perl-5.8.*.* 여러 버전 중에 어떤 건 vim이 죽어버리고 어떤 건 괜찮았으니 확인이 필요.
PC에 Perl이 설치되어 있는 경우는 perl 인터프리터를 직접 호출하는 식으로도 쓸 수 있긴 하다:
:%!perl -pi -e 's/<text>/\n/'
그런데 주인장이 해 봤을 때 이 경우 문제는, lookahead 를 위해서 (?!pattern) 등과 같이 쓸 경우 "!"를 vim이 먼저 해석해버리는지 perl이 제대로 수행되지 않고 에러가 반환되었다.
서버에 있는게 7.0인데, 7.3을 써보고 싶어서 직접 컴파일하려니... 도대체 그 수많은 옵션 중 뭐를 켜줘야 무난한지 모르겠다. 일단은
./configure --prefix=/home/gypark/local/
# 이름 겹치지 말라고
--with-vim-name=vim73 --with-ex-name=ex73 --with-view-name=view73
# 이건 아래 features 항목을 big으로 하면 안 해도 되는 것 같긴 한데
--enable-multibyte --enable-hangulinput
--with-features=huge
# 펄 인터프리터를 추가하는 건 실패했다
--enable-perlinterp=yes
펄 인터프리터를 추가하려고 했더니 make할 때 Undefined subroutine &ExtUtils::ParseXS::errors called at /home/gypark/perl5/perlbrew/perls/perl-5.14.2/lib/5.14.2/ExtUtils/xsubpp에러가 난다. 포기.
각주: 1. [commentstrnig], [fold-create-marker] 참조 2. 이 문제는 다른 문서를 읽을 때도 종종 겪던 문제. 텍스트 문서가 UTF-8로 인코딩되어 있어도 보통은 gvim이 iconv를 써서 변환을 하면서 제대로 보여주는데, 상황에 따라 그 변환이 제대로 되지 않아 한글이 깨져나오는 경우가 있다. 이 경우 강제로 set encoding=utf-8 해 주면 텍스트는 잘 보이는데 그 다음부터는 gvim의 메시지가 다 깨져보여서 불편 3. rashper님께서 알려주셨음. 감사합니다 4. font link를 통해 찾지 못할 경우는 font fallback을 사용하여 시스템에 있는 폰트를 검색하여 쓴다고도 하는데, 그래서 메모장에서는 제대로 보였는데 gvim은 안 되는 이유는 모르겠음 5. [하늘빛 공방 » 맑은 고딕 쓸 때 한자도 클리어 타입으로 보기], [Globalization Step-by-Step: Fonts]를 참고 6. encoding을 utf-8로 놓고, termencoding을 cp949로 해봤는데, 출력은 상관 없는데 한글을 입력할 때 문제가 생김 7. :set 했을때 아예 나오지도 않더라. 윈도우용 gvim 7.2에서 확인 8. 뭐라 번역해야 할지...