Code browser, Source Insight

brucekim1, brucekim2에서 같은 내용을 올려둔 적은 있는데, 잘 정리된 것 같지 않아서 다시 여기에 정리하여 적어둔다.

소스파일의 개수와 소스코드의 양이 많고 적음을 떠나서, 소스코드를 효과적이고 빠르게 분석을 하기 위해서는 코드 브라우징 기능을 제공하는 도구를 사용하면 생산성을 높일 수 있다. 메모장으로 분석하려는 소스파일을 하나하나 열고 함수와 변수들이 어떻게 호출되는지 그 연관관계를 파악하기에는 여간 어려운 것이 아니다. 코드 브라우징을 포함한 여러 분석기능을 제공하는 툴인 소스인사이트가 대표적인 도구라고 생각한다.

소스인사이트를 몇년간 사용해온 경험으로는, 수십기가에 이르는 소스파일들 상에서 원하는 파일을 빠르게 찾아 열어볼 수 있고, 몇 번의 클릭만으로 함수와 변수들이 사용된 곳이 어디인지 보여주기 때문에 빠르게 분석할 수 있는 것이 장점이다.

그런데 문제는 수십기가에 이르는 한벌의 소스파일들을 새로 받고, 소스인사이트에서 분석이 가능하게 하려면 선행되어야 하는 작업이 있는데, 여기에 시간이 많이 걸린다는 것이 단점이라고 생각한다. 이 작업은 소스파일들에 대한 심볼을 추출하고 이에 대한 캐쉬파일을 만드는 것인데 꽤 오래 걸린다. 짧게는 한 두시간에서 길게는 반나절이 걸린다. 물론, 작업 필요한 파일들을 선별하여 캐쉬를 만들면 시간이 단축될 수는 있으나, 마우스로 여러번 클릭해야 하는 것이 꽤 번거롭게 느껴졌다.

VIM + code browser like source insight

대부분의 리눅스환경에 설치되어있는 편집기인 VIM에서, 몇 가지 플러그인을 설치해주고 적절히 설정을 해주면 코드 브라우징이 가능해진다. 나는 VIM으로 코드분석을 하기를 선호하는데, 마치 소스인사이트처럼 쓸 수 있을 뿐만 아니라, 캐쉬를 만드는 시간도 소스인사이트와 비교하여 오래 걸리지 않기 때문에 좋아한다. 다만 파일네비게이션이 좀 힘들어지는 단점이 있다. 첫째로, Nerd Tree 로 디렉터리 tree에서 원하는 파일을 눈으로 찾기에는 너무 피곤하다.파일명으로 파일을 찾기보다는 SrcExpl로 함수가 호출된 부분을 따라가다 보면 원하는 파일들이 자동으로 열리니까 크게 문제 없이 쓰고 있다. 두번째로, 소스인사이트에서 Ctrl+o 단축키로 파일이름만 넣어주면 원하는 파일을 찾아주는 유사한 기능을 FuzzFinder라는 플러그인에서 제공을 해주기는 하지만 캐쉬되어있는 소스파일들의 개수와 소스코드가 수 기가(Giga) 단위만 되어도 파일 하나 찾는데 꽤 오랜 시간이 걸려서 답답하다.한글자 타이핑할때마다 입력된 문자에 해당하는 파일들을 정규표현식에 맞추어 새로 검색하는 순서로 동작되어서 그런것 같은데, 파일이름들에 대한 캐쉬를 만들 수 없는지 찾아보았지만 못찾았다.

How to

Prerequisite

  • ctags, cscope : 아래 플러그인들에서 브라우징하기 위해 참조하는 캐쉬파일을 생성하는 도구
  • vim-pathogen : vim plugin을 package 관리자처럼 쉽게 설치해주는 플러그인
  • vimsensible : 기본적으로 사용되는 vimrc 설정을 해주는데, backspace, incsearch, listchars, scrolloff, autoread가 있음
  • SrcExpl : ctags와 csope를 캐쉬로 쓰는 소스코드 브라우저 플러그인, 가장 핵심 플러그인
  • NERDtree : 파일시스템을 트리형태로 네이게이션 해주는 플러그인, 디렉터리/파일 복사, 삭제, 이동등 기본 기능이 제공된다.
  • taglist : 소스파일내의 소스코드의 심벌(함수, 변수등)을 브라우징할 수 있는 플러그인
  • Trinity : SrcExpl, taglish, NERDtree 를 쉽게 사용할 수 있도록 단축키기능을 제공하는 플러그인

Plugin Install

patheogen 설치

mkdir -p ~/.vim/autoload ~/.vim/bundle
cd ~/.vim/autoload/ && wget https://tpo.pe/pathogen.vim

그리고 .vimrc에 아래 내용을 추가한다.

execute pathogen#infect()
syntax on
filetype plugin indent on

이제부터는 patheogen으로 쉽게 vim plugin 설치가 가능해진다.

나머지 plugin 설치

cd ~/.vim/bundle && git clone git://github.com/tpope/vim-sensible.git
cd ~/.vim/bundle/  && git clone https://github.com/wesleyche/SrcExpl
cd ~/.vim/bundle/ && git clone https://github.com/scrooloose/nerdtree
cd ~/.vim/bundle/ && git clone https://github.com/wesleyche/Trinity
cd ~/.vim/bundle/ && wget https://sourceforge.net/projects/vim-taglist/files/vim-taglist/4.6/taglist_46.zip && unzip taglist_46.zip -d taglist

.vimrc 수정

  1 "common option
  2 set number
  3 syntax on
  4 colorscheme desert
  5 set smartindent
  6 set ai
  7 set cindent
  8 set tabstop=4
  9 set softtabstop=4
 10 set shiftwidth=4
 11 set shiftround
 12 set expandtab
 13 set fo=croql
 14 set hlsearch
 15 
 16 
 17 "for vim plugin
 18 execute pathogen#infect()
 19 filetype plugin indent on
 20 
 21 let g:NERDTreeDirArrows = 1
 22 let g:NERDTreeDirArrowExpandable = '▸'
 23 let g:NERDTreeDirArrowCollapsible = '▾'
 24 let g:NERDTreeGlyphReadOnly = "RO"
 25 let g:NERDTreeWinSize = 40
 26 
 27 "Open and close all the three plugins on the same time
 28 nmap <F7>   :TrinityToggleAll<CR>
 29 
 30 "Open and close the taglist.vim separately
 31 nmap <F8>  :TrinityToggleTagList<CR>
 32 
 33 "Open and close the srcexpl.vim separately
 34 nmap <F9>   :TrinityToggleSourceExplorer<CR>
 35 "
 36 "Open and close the NERD_tree.vim separately
 37 nmap <F10>  :TrinityToggleNERDTree<CR>
 38 
 39 set listchars=eol:$,tab:>-,trail:~,extends:>,precedes:<
 40 set list

21~25 line을 넣어주지 않으면 vim을 열 때 에러메시지가 발생한다.

Error detected while processing /home/pi/.vim/bundle/nerdtree/syntax/nerdtree.vim:
line    3:
E121: Undefined variable: g:NERDTreeGlyphReadOnly
E15: Invalid expression: 'syn match NERDTreeIgnore #\['.g:NERDTreeGlyphReadOnly.'\]#'
line   25:
E121: Undefined variable: g:NERDTreeDirArrowCollapsible
E116: Invalid arguments for function escape(g:NERDTreeDirArrowCollapsible, '~').'# containedin=NERDTreeDir,NERDTreeFile'
E15: Invalid expression: 'syn match NERDTreeClosable #'.escape(g:NERDTreeDirArrowCollapsible, '~').'# containedin=NERDTreeDir,NERDTreeFile'
line   26:
E121: Undefined variable: g:NERDTreeDirArrowExpandable
E116: Invalid arguments for function escape(g:NERDTreeDirArrowExpandable, '~').'# containedin=NERDTreeDir,NERDTreeFile'
E15: Invalid expression: 'syn match NERDTreeOpenable #'.escape(g:NERDTreeDirArrowExpandable, '~').'# containedin=NERDTreeDir,NERDTreeFile'
line   28:
E121: Undefined variable: g:NERDTreeDirArrowCollapsible
E116: Invalid arguments for function escape(g:NERDTreeDirArrowCollapsible, '~]\-').escape(g:NERDTreeDirArrowExpandable, '~]\-')
E15: Invalid expression: escape(g:NERDTreeDirArrowCollapsible, '~]\-').escape(g:NERDTreeDirArrowExpandable, '~]\-')
line   29:
E121: Undefined variable: s:dirArrows
E15: Invalid expression: 'syn match NERDTreeDir #[^'.s:dirArrows.' ].*/#'
line   31:
E121: Undefined variable: s:dirArrows
E15: Invalid expression: 'syn match NERDTreeFile  #^[^"\.'.s:dirArrows.'] *[^'.s:dirArrows.']*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecF
ile'
line   34:
E121: Undefined variable: g:NERDTreeGlyphReadOnly
E15: Invalid expression: 'syn match NERDTreeRO # *\zs.*\ze \['.g:NERDTreeGlyphReadOnly.'\]# contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreeFile'

Useful tool&plugins

  • cscope : ctags는 callee로 jump하는 기능은 제공하지만, caller를 찾아주는 기능이 없다. cscope에서 지원해주므로, cscope도 같이 사용
  • vim-bitbake : vim에서 bitbake syntax highlighting 해주는 플러그인 .vimrc추가 옵션
    • Disable Folding: let g:vim_markdown_folding_disabled = 1 - set [no]foldenable
    • Change fold style: let g:vim_markdown_folding_style_pythonic = 1
    • Set header folding level: let g:vim_markdown_folding_level = 6 - between 1 and 6
    • Disable Default Key Mappings: let g:vim_markdown_no_default_key_mappings = 1
    • Enable TOC window auto-fit: let g:vim_markdown_toc_autofit = 1
    • Text emphasis restriction to single-lines: let g:vim_markdown_emphasis_multiline = 0
    • Syntax Concealing: set conceallevel=2
    • Fenced code block languages: let g:vim_markdown_fenced_languages = ['csharp=cs']
    • Syntax extensions: LaTeX math, YAML Front Matter, TOML Front Matter, JSON Front Matter
        let g:vim_markdown_math = 1
        let g:vim_markdown_frontmatter = 1
        let g:vim_markdown_toml_frontmatter = 1
        let g:vim_markdown_json_frontmatter = 1
      
  • vimmarkdown : vim에서 markdown syntax highlighting 해주는 플러그인
  • youcompleteme : code-completion engine, clang기반인 C/C++/Objective-C++ (C-family)의 semantic code completion을 지원해주는 플러그인
    Image
  • vimdirdiff : 두 디렉터리에 있는 파일들의 diff를 편하게 해주는 plugin
    Image