VIM (Vi IMproved) 설정하기

A. 준비사항

Ubuntu 리눅스에 기본으로 포함된 vim-tiny 패키지에서는 다음 설정을 적용할 수 없습니다. 그 대신 vim의 모든 기능을 사용할 수 있는 vim-gnome 패키지가 필요합니다. 또한, 아래 설정에서 사용할 taglist script는 Exuberant Ctags에 의존성을 가지며 Ubuntu 리눅스에서는 exuberant-ctags 패키지로 설치할 수 있습니다. Ubuntu 리눅스 9.04에서는 ctags 패키지가 exuberant-ctags 패키지로 링크가 걸려 있으므로, ctags 패키지를 설치하여도 상관 없습니다. 두 가지 패키지를 설치한 후 다음으로 진행합니다.

aptitude install vim-gnome ctags

B. 스크립트 설치

다음 목록에 있는 VIM Script를 다운로드 받아 설치합니다.

모두 다운로드 받은 후, 압축 파일은 홈 디렉터리 아래의 .vim 디렉터리($HOME/.vim)에 압축을 해제하고, 확장자가 vim인 파일은 plugin 디렉터리($HOME/.vim/plugin)로 이동시킵니다.

압축을 해제한 후, doc 디렉터리($HOME/.vim/doc)에서 vi를 실행한 후 다음 명령을 입력합니다.

:helptags .

C. 설정 파일

홈 디렉터리 아래의 .vimrc 파일($HOME/.vimrc)의 내용을 다음과 같이 만듭니다.

set nocompatible

set fileencoding=utf-8
set fileencodings=utf-8,cp949,unicode
set termencoding=utf-8
"set termencoding=korea                " Cygwin-specific option
set encoding=utf-8

set autoindent
set autowrite
set backspace=indent,eol,start
set cindent
set cinoptions=:0,g0,(0,l1,t0
set history=1000
set hlsearch
set incsearch
"set km=startsel,stopsel
set laststatus=2
set magic
set matchpairs+=<:>
set mouse=a
set nobackup
set noerrorbells
set noexpandtab
set nowrap
set number!
"set pastetoggle=<Ins>
set report=0
set ruler
set scrolloff=5
set selection=exclusive
set shiftwidth=4
set showcmd
set showmatch
set showmode
set sidescrolloff=5
set smartcase
set smartindent
set startofline
"set statusline=%<%F%h%m%r%h%w%y\ %{strftime(\"%Y/%m/%d-%H:%M\")}%=\ col:%c%V\ ascii:%b\ pos:%o\ lin:%l\,%L\ %P
"set statusline=%h%F%m%r%=[%l:%c(%p%%)]
set statusline=%-3.3n\ %f\ %r%#Error#%m%#Statusline#\ (%l/%L,\ %v)\ %P%=%h%w\ %y\ [%{&encoding}:%{&fileformat}]
set softtabstop=0
set tabstop=4
set title
set ttyfast
"set virtualedit=onemore                        " Has to be used with caution!!
set whichwrap=h,l,<,>,[,]
set wildchar=<Tab>
set wildmenu
set wildmode=longest:full,full
"set visualbell
let maplocalleader=','

syntax on
filetype on
filetype plugin on
filetype indent on

" setup for the visual environment
if has('gui_running')
	colorscheme inkpot
else
	if $TERM =~ '^xterm'
		set t_Co=256
	elseif $TERM =~ '^screen-bce'
		set t_Co=256            " just guessing
	elseif $TERM =~ '^screen'
		set t_Co=256            " just guessing, too
	elseif $TERM =~ '^rxvt'
		set t_Co=88
	elseif $TERM =~ '^linux'
		set t_Co=8
	elseif $TERM =~ '^cygwin'
		set t_Co=8
	else
		set t_Co=16
	endif

	if &t_Co > 16
		colorscheme inkpot
	else
		colorscheme ron
	endif
endif

" Uncomment the following to have Vim jump to the last position when
" reopening a file
"if has("autocmd")
"  au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$")
"    \| exe "normal g'\"" | endif
"endif

if 0
	" automatically delete trailing Dos-returns,whitespace
	"autocmd BufRead * silent! %s/[\r \t]\+$//
	"autocmd BufEnter *.php :%s/[ \t\r]\+$//e

	" automatically delete trailing Dos-returns
	autocmd BufRead * silent! %s/\r\+$//
	autocmd BufEnter *.php :%s/\r\+$//e

	" Automatic folding
	autocmd BufWinLeave *.rb mkview
	autocmd BufWinEnter *.rb silent loadview

	autocmd BufWinLeave *.c mkview
	autocmd BufWinEnter *.c silent loadview

	autocmd BufWinLeave *.cc mkview
	autocmd BufWinEnter *.cc silent loadview

	autocmd BufWinLeave *.cpp mkview
	autocmd BufWinEnter *.cpp silent loadview

	autocmd BufWinLeave *.C mkview
	autocmd BufWinEnter *.C silent loadview

	autocmd BufWinLeave *.h mkview
	autocmd BufWinEnter *.h silent loadview

	autocmd BufWinLeave *.H mkview
	autocmd BufWinEnter *.H silent loadview

	autocmd BufWinLeave *.hpp mkview
	autocmd BufWinEnter *.hpp silent loadview
	autocmd BufWinEnter *.hpp set syntax=cpp

	autocmd BufWinLeave *.s mkview
	autocmd BufWinEnter *.s silent loadview

	autocmd BufWinLeave *.S mkview
	autocmd BufWinEnter *.S silent loadview
endif

" VIM man pager related setting
autocmd FileType man set nonumber
autocmd FileType man set mouse=a

" Hotkeys
" Ctrl-s : saves
inoremap <C-s> <Esc>:w<CR>a
nnoremap <C-s> :w<CR>

" F12 : generating ctags
map <F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --verbose=yes .<CR>

" tabs
" (LocalLeader is ",")
" create a new tab
map <LocalLeader>tc :tabnew %<cr>
" close a tab
map <LocalLeader>td :tabclose<cr>
" next tab
map <LocalLeader>tn :tabnext<cr>
" previous tab
map <LocalLeader>tp :tabprev<cr>
" move a tab to a new location
map <LocalLeader>tm :tabmove

" some useful mappings
" Y yanks from cursor to $
map Y y$
" toggle list mode
nmap <LocalLeader>tl :set list!<cr>
" toggle paste mode
nmap <LocalLeader>pp :set paste!<cr>
" change directory to that of current file
nmap <LocalLeader>cd :cd%:p:h<cr>
" change local directory to that of current file
nmap <LocalLeader>lcd :lcd%:p:h<cr>
" save and build
nmap <LocalLeader>wm :w<cr>:make<cr>
" open all folds
nmap <LocalLeader>fo :%foldopen!<cr>
" close all folds
nmap <LocalLeader>fc :%foldclose!<cr>
" ,tt will toggle taglist on and off
nmap <LocalLeader>tt :Tlist<cr>
" When I'm pretty sure that the first suggestion is correct
map <LocalLeader>r 1z=
" togle wordwrap mode
map <LocalLeader>ww :set wrap!<cr>

" WinManager plugin settings
nnoremap <silent> <F4> :WMToggle<CR>
nnoremap <silent> <F5> :FirstExplorerWindow<CR>
nnoremap <silent> <F6> :BottomExplorerWindow<CR>

let winManagerWindowLayout = 'FileExplorer|BufExplorer'
let g:persistentBehaviour = 0

" taglist plugin settings
nnoremap <silent> <F7> :TlistUpdate<CR>
nnoremap <silent> <F8> :Tlist<CR>
nnoremap <silent> <F9> :TlistSync<CR>

let Tlist_Inc_Winwidth = 0
let Tlist_Auto_Open = 1
let Tlist_Process_File_Always = 0
let Tlist_Enable_Fold_Column = 0
let Tlist_Display_Tag_Scope = 0
let Tlist_Sort_Type = "name"
let Tlist_Use_Right_Window = 1
let Tlist_Display_Prototype = 0
let Tlist_Exit_OnlyWindow = 1
let Tlist_File_Fold_Auto_Close = 1

"let Tlist_Ctags_Cmd = '$HOME/bin/ctags.exe'   "Cygwin-specific option

" OmniCppComplete plugin settings
autocmd CursorMovedI * if pumvisible() == 0|pclose|endif
autocmd InsertLeave * if pumvisible() == 0|pclose|endif

let OmniCpp_GlobalScopeSearch = 1
let OmniCpp_NamespaceSearch = 1
let OmniCpp_DisplayMode = 0
let OmniCpp_ShowScopeInAbbr = 0
let OmniCpp_ShowPrototypeInAbbr = 0
let OmniCpp_ShowAccess = 1
let OmniCpp_DefaultNamespaces = []
let OmniCpp_MayCompleteDot = 1
let OmniCpp_MayCompleteArrow = 1
let OmniCpp_MayCompleteScope = 0
let OmniCpp_SelectFirstItem = 0
let OmniCpp_LocalSearchDecl = 0

" // The switch of the Source Explorer
nmap <F11> :SrcExplToggle<CR>

" // Set the height of Source Explorer window
let g:SrcExpl_winHeight = 8

" // Set 100 ms for refreshing the Source Explorer
let g:SrcExpl_refreshTime = 100

" // Set "Enter" key to jump into the exact definition context
let g:SrcExpl_jumpKey = "<ENTER>"

" // Set "Space" key for back from the definition context
let g:SrcExpl_gobackKey = "<SPACE>"

" // In order to Avoid conflicts, the Source Explorer should know what plugins
" // are using buffers. And you need add their bufname into the list below
" // according to the command ":buffers!"
let g:SrcExpl_pluginList = [
        \ "__Tag_List__",
        \ "_NERD_tree_",
        \ "Source_Explorer",
        \ "[File List]",
        \ "[Buf List]"
    \ ]
" // Enable/Disable the local definition searching, and note that this is not
" // guaranteed to work, the Source Explorer doesn't check the syntax for now.
" // It only searches for a match with the keyword according to command 'gd'
let g:SrcExpl_searchLocalDef = 1

" // Let the Source Explorer update the tags file when opening
let g:SrcExpl_isUpdateTags = 1

" // Use program 'ctags' with argument '--sort=foldcase -R' to create or
" // update a tags file
let g:SrcExpl_updateTagsCmd = "ctags --sort=foldcase -R ."

" // Set "<S-F12>" key for updating the tags file artificially
let g:SrcExpl_updateTagsKey = "<S-F12>" 

" bracket autocompletion
inoremap ( ()<ESC>i
inoremap [ []<ESC>i
inoremap { {<CR>}<ESC>O
autocmd Syntax html,vim inoremap < <lt>><ESC>i| inoremap > <c-r>=ClosePair('>')<CR>
inoremap ) <c-r>=ClosePair(')')<CR>
inoremap ] <c-r>=ClosePair(']')<CR>
inoremap } <c-r>=CloseBracket()<CR>
inoremap " <c-r>=QuoteDelim('"')<CR>
inoremap ' <c-r>=QuoteDelim("'")<CR>

function ClosePair(char)
	if getline('.')[col('.') - 1] == a:char
		return "\<Right>"
	else
		return a:char
	endif
endf

function CloseBracket()
	if match(getline(line('.') + 1), '\s*}') < 0
		return "\<CR>}"
	else
		return "\<ESC>j0f}a"
	endif
endf

function QuoteDelim(char)
	let line = getline('.')
	let col = col('.')
	if line[col - 2] == "\\"
		" Inserting a quoted quotation mark into the string
		return a:char
	elseif line[col - 1] == a:char
		" Escaping out of the string
		return "\<Right>"
	else
		" Starting a string
		return a:char.a:char."\<ESC>i"
	endif
endf

D. Cygwin 관련 설정(옵션)

Cygwin 1.5는 taglist 스크립트가 필요로 하는 Exuberant Ctags를 제공하지 않습니다. 만약 Cygwin 1.5 환경이라면 Exuberant Ctags를 별도로 다운로드 받아 설치해주어야 합니다. 소스를 홈페이지에서 다운로드 받아 빌드하거나 미리 빌드해놓은 바이너리를 다운로드 받아 실행 파일만을 홈 디렉터리 아래의 bin 디렉터리($HOME/bin)에 설치합니다.

참고로, 위의 실행파일은 Cygwin version 1.5.25, gcc version 3.4.4에서 빌드되었습니다. 버전이 달라 정상 동작하지 않는다면 직접 빌드하여 사용하십시오.

그리고, 홈 디렉터리 아래의 .vimrc 파일($HOME/.vimrc)의 내용 중 termencoding 항목을 주석처리 또는 삭제하고, 다음 두 행을 적절한 위치에 추가합니다.

set termencoding=korea
let Tlist_Ctags_Cmd = '$HOME/bin/ctags.exe'

E. 적용 스크린 샷

Ubuntu 리눅스의 Gnome terminal에서 이 설정을 사용하여 VIM을 사용하는 스크린 샷입니다.

20090906 - VIM screenshot

* 수정 내역

  1. 2010년 5월 1일 오후 1시 10분: SuperTab, bufexplorer script 업데이트
  2. 2009년 8월 27일 오후 10시 31분: SuperTab script 관련 내용 추가
  3. 2009년 8월 28일 오전 9시 18분: 설정 파일 수정(view, trailing character 관련 항목)
  4. 2009년 8월 28일 오전 10시 43분: 설정 파일 수정(mouse 관련 항목)
  5. 2009년 8월 28일 오후 12시 44분: 설정 파일 수정(trailing character 관련 항목)
  6. 2009년 8월 28일 오후 6시 9분: OmniCppComplete 관련 내용과 설정 항목 추가
  7. 2009년 9월 2일 오후 4시 2분: 설정 파일 수정(VIM pager 관련 항목)
  8. 2009년 9월 3일 오후 3시 47분: 설정 파일 수정(color, key mapping 관련 항목)
  9. 2009년 9월 4일 오후 1시 46분: 설정 파일 수정(color scheme 관련 항목)
  10. 2009년 9월 5일 오전 12시 36분: 설정 파일 수정(terminal color 관련 항목)
  11. 2009년 9월 8일 오후 12시 41분: 설정 파일 수정(key mapping, scrolloff 관련 항목)
  12. 2009년 10월 15일 오후 11시 41분: SuperTab script를 0.60 버전으로 업데이트
  13. 2009년 10월 26일 오후 1시 4분: SuperTab script를 0.61 버전으로 업데이트
  14. 2009년 11월 21일 오후 5시 41분: Source Explorer script 추가, 설정 파일 수정(autocmd 관련 항목, Source Explorer script 관련 항목)
Creative Commons LicenseWonmin Jung에 의해 창작된 Dr. Jung's Blog 은(는) 크리에이티브 커먼즈 저작자표시-비영리-변경금지 2.0 대한민국 라이선스에 따라 이용할 수 있습니다. 이 라이선스의 범위를 넘는 이용허락은 http://­www­.drjung­.net­/wp1­/contact에서 받을 수 있습니다.

    • 김민창
    • 2009년 8월 31일

    Good~~~
    조만간 설치해서 함 사용해 보도록 하지..ㅋㅋ

    • 카켈
    • 2009년 9월 23일

    너무 멋지네요. 다른 프로그램이 되었어요.
    자료 공개 감사합니다.

    • 도움이 되셨다니 저도 기쁘네요.
      잘 사용하시기 바라고 댓글 감사합니다. ^^

    • 김중근
    • 2010년 3월 29일

    cygwin에서 해보려고 하는데, 잘 안되네요.
    일단 위에서 기술한 필요한 script는 다 다운받았으며,
    Exuberant Ctags도 다운받아서 cygwin/bin 아래넣어놨습니다.
    주석도 말씀대로 comment처리 했고요.
    그 다음에 뭘 해봐야 할까요?

    저는 기존에는 .vim dir가 아닌 home에 .vimrc를 넣어놓고 사용했는데, 단순하게만 사용했거든요. 그래서 위에서 보여주신 스샷처럼 사용하고 싶은데..
    잘 안되네요..^^
    좀 부탁좀 드립니다. 저런 환경에서 일해보고 싶은생각이 가득하네요.

    • 안녕하세요 ^^ 방문 감사드립니다.
      어떤 부분이 안되시는지요?
      에러 메시지나 스크린샷을 보여주시면 알아볼 수 있을 것 같네요 ^^

    • 김중근
    • 2010년 3월 31일

    이것저것 해서 되게 만들었습니다. 보니까 제가 제대로 못했더라고요.
    그런데, 제가 VI 초보다 보니까.. full 기능을 몰라서 그런것 같습니다.
    이 script에 숨어있는 기능이 많은것 같은데, 혹시 기능 설명은 없나요?
    사용법을 모르니, 환경은 달라져도 기본만 사용하게 되네요.

    • 제대로 되신다니 다행이네요~
      자세한 기능 설명이 있지는 않은데..
      map, nmap, nnoremap에 해당하는 라인들의 주석을 참고하시면 어느 정도 도움이 될 수 있지 않을까 합니다~
      이해 안되시는 라인은 댓글 남겨주시면 자세히 알려드리겠습니다. ;)

  1. 트랙백이 없습니다.