1
0
Fork 0
mirror of synced 2024-11-26 18:55:34 -05:00

Merge pull request #1 from amix/master

update
This commit is contained in:
Brandon Werner 2015-05-20 18:14:25 -07:00
commit 6d6caec1b1
688 changed files with 53141 additions and 20920 deletions

2
.gitignore vendored
View file

@ -4,3 +4,5 @@ temp_dirs/yankring_history_v2.txt
sources_forked/yankring/doc/tags sources_forked/yankring/doc/tags
sources_non_forked/tlib/doc/tags sources_non_forked/tlib/doc/tags
my_configs.vim my_configs.vim
tags
.DS_Store

View file

@ -9,6 +9,15 @@ There are two versions:
I would of course recommend using the awesome version. I would of course recommend using the awesome version.
## How to install the Awesome version?
The awesome version includes a lot of great plugins, configurations and color schemes that make Vim a lot better. To install it simply do following:
git clone git://github.com/amix/vimrc.git ~/.vim_runtime
sh ~/.vim_runtime/install_awesome_vimrc.sh
The taglist.vim plugin will require ctags (http://ctags.sourceforge.net) (Debian: apt-get install ctags)
I also recommend using [Source Code Pro font from Adobe](http://store1.adobe.com/cfusion/store/html/index.cfm?event=displayFontPackage&code=1960) (it's free and awesome font for writing and programming). The Awesome vimrc is already setup to try to use it
## How to install the Basic version? ## How to install the Basic version?
The basic version is basically just one file and no plugins. You can check out [basic.vim](https://github.com/amix/vimrc/blob/master/vimrcs/basic.vim). The basic version is basically just one file and no plugins. You can check out [basic.vim](https://github.com/amix/vimrc/blob/master/vimrcs/basic.vim).
@ -19,13 +28,6 @@ This is useful to install on remote servers where you don't need many plugins an
sh ~/.vim_runtime/install_basic_vimrc.sh sh ~/.vim_runtime/install_basic_vimrc.sh
## How to install the Awesome version?
The awesome version includes a lot of great plugins, configurations and color schemes that make Vim a lot better. To install it simply do following:
git clone git://github.com/amix/vimrc.git ~/.vim_runtime
sh ~/.vim_runtime/install_awesome_vimrc.sh
## How to install on Windows? ## How to install on Windows?
Use [msysgit](http://msysgit.github.com/) to checkout the repository and run the installation instructions above. No special instructions needed ;-) Use [msysgit](http://msysgit.github.com/) to checkout the repository and run the installation instructions above. No special instructions needed ;-)
@ -53,8 +55,11 @@ Opening recently opened files [mru.vim](https://github.com/vim-scripts/mru.vim):
This vimrc even works on Windows! This vimrc even works on Windows!
![Screenshot 4](http://files1.wedoist.com/4e85163d97b81422240c822c82022f2f/as/screenshot_4.png) ![Screenshot 4](http://files1.wedoist.com/4e85163d97b81422240c822c82022f2f/as/screenshot_4.png)
Distraction free mode using [goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2):
![Screenshot 5](https://d2dq6e731uoz0t.cloudfront.net/a5182977c3d6c2a6cd3f9e97398ca8ca/as/zen_mode.jpg)
## What plugins are included?
## Included Plugins
I recommend reading the docs of these plugins to understand them better. Each of them provide a much better Vim experience! I recommend reading the docs of these plugins to understand them better. Each of them provide a much better Vim experience!
@ -63,19 +68,24 @@ I recommend reading the docs of these plugins to understand them better. Each of
* [snipMate.vim](https://github.com/garbas/vim-snipmate): snipMate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim * [snipMate.vim](https://github.com/garbas/vim-snipmate): snipMate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim
* [bufexplorer.zip](https://github.com/vim-scripts/bufexplorer.zip): Buffer Explorer / Browser. This plugin can be opened with `<leader+o>` * [bufexplorer.zip](https://github.com/vim-scripts/bufexplorer.zip): Buffer Explorer / Browser. This plugin can be opened with `<leader+o>`
* [NERD Tree](https://github.com/scrooloose/nerdtree): A tree explorer plugin for vim * [NERD Tree](https://github.com/scrooloose/nerdtree): A tree explorer plugin for vim
* [ack.vim](github.com/mileszs/ack.vim): Vim plugin for the Perl module / CLI script 'ack' * [ack.vim](https://github.com/mileszs/ack.vim): Vim plugin for the Perl module / CLI script 'ack'
* [vim-powerline](https://github.com/Lokaltog/vim-powerline): The ultimate vim statusline utility
* [ctrlp.vim](https://github.com/kien/ctrlp.vim): Fuzzy file, buffer, mru and tag finder. In my config it's mapped to `<Ctrl+F>`, because `<Ctrl+P>` is used by YankRing * [ctrlp.vim](https://github.com/kien/ctrlp.vim): Fuzzy file, buffer, mru and tag finder. In my config it's mapped to `<Ctrl+F>`, because `<Ctrl+P>` is used by YankRing
* [mru.vim](https://github.com/vim-scripts/mru.vim): Plugin to manage Most Recently Used (MRU) files. Includes my own fork which adds syntax highlighting to MRU. This plugin can be opened with `<leader+f>` * [mru.vim](https://github.com/vim-scripts/mru.vim): Plugin to manage Most Recently Used (MRU) files. Includes my own fork which adds syntax highlighting to MRU. This plugin can be opened with `<leader+f>`
* [open_file_under_cursor.vim](https://github.com/amix/open_file_under_cursor.vim): Open file under cursor when pressing `gf` * [open_file_under_cursor.vim](https://github.com/amix/open_file_under_cursor.vim): Open file under cursor when pressing `gf`
* [zencoding](https://github.com/mattn/zencoding-vim): Expanding abbreviation like zen-coding, very useful for editing XML, HTML. * [zencoding](https://github.com/mattn/emmet-vim): Expanding abbreviation like zen-coding, very useful for editing XML, HTML.
* [vim-indent-object](https://github.com/michaeljsmith/vim-indent-object): Defines a new text object representing lines of code at the same indent level. Useful for python/vim scripts * [vim-indent-object](https://github.com/michaeljsmith/vim-indent-object): Defines a new text object representing lines of code at the same indent level. Useful for python/vim scripts
* [taglist.vim](https://github.com/vim-scripts/taglist.vim): Source code browser (supports C/C++, java, perl, python, tcl, sql, php, etc) * [taglist.vim](https://github.com/vim-scripts/taglist.vim): Source code browser (supports C/C++, java, perl, python, tcl, sql, php, etc)
* [vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors): Sublime Text style multiple selections for Vim, CTRL+N is remapped to CTRL+S (due to YankRing) * [vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors): Sublime Text style multiple selections for Vim, CTRL+N is remapped to CTRL+S (due to YankRing)
* [vim-expand-region](https://github.com/terryma/vim-expand-region): Allows you to visually select increasingly larger regions of text using the same key combination. * [vim-expand-region](https://github.com/terryma/vim-expand-region): Allows you to visually select increasingly larger regions of text using the same key combination.
* [vim-airline](https://github.com/bling/vim-airline): Lean & mean status/tabline for vim that's light as air (replacing powerline)
* [vim-fugitive](https://github.com/tpope/vim-fugitive): A Git wrapper so awesome, it should be illegal
* [goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2):
Remove all clutter and focus only on the essential. Similar to iA Writer or Write Room [Read more here](http://amix.dk/blog/post/19744)
* [vim-commentary](https://github.com/tpope/vim-commentary): Comment stuff out. Use `gcc` to comment out a line (takes a count), `gc` to comment out the target of a motion. `gcu` uncomments a set of adjacent commented lines.
* [syntastic](https://github.com/scrooloose/syntastic): Syntax checking hacks for vim
## What color schemes are included? ## Included color schemes
* [peaksea](https://github.com/vim-scripts/peaksea): My favorite! * [peaksea](https://github.com/vim-scripts/peaksea): My favorite!
* [vim-colors-solarized](https://github.com/altercation/vim-colors-solarized) * [vim-colors-solarized](https://github.com/altercation/vim-colors-solarized)
@ -84,13 +94,14 @@ I recommend reading the docs of these plugins to understand them better. Each of
* [vim-pyte](https://github.com/therubymug/vim-pyte) * [vim-pyte](https://github.com/therubymug/vim-pyte)
## What modes are included? ## Included modes
* [vim-coffee-script](https://github.com/kchmck/vim-coffee-script) * [vim-coffee-script](https://github.com/kchmck/vim-coffee-script)
* [vim-less](https://github.com/groenewege/vim-less) * [vim-less](https://github.com/groenewege/vim-less)
* [vim-bundle-mako](https://github.com/sophacles/vim-bundle-mako) * [vim-bundle-mako](https://github.com/sophacles/vim-bundle-mako)
* [vim-markdown](https://github.com/tpope/vim-markdown) * [vim-markdown](https://github.com/tpope/vim-markdown)
* [nginx.vim](https://github.com/vim-scripts/nginx.vim): Highlights configuration files for nginx * [nginx.vim](https://github.com/vim-scripts/nginx.vim): Highlights configuration files for nginx
* [vim-golang](https://github.com/jnwhiteh/vim-golang)
## How to include your own stuff? ## How to include your own stuff?
@ -135,6 +146,10 @@ Managing the [NERD Tree](https://github.com/scrooloose/nerdtree) plugin:
map <leader>nb :NERDTreeFromBookmark map <leader>nb :NERDTreeFromBookmark
map <leader>nf :NERDTreeFind<cr> map <leader>nf :NERDTreeFind<cr>
[goyo.vim](https://github.com/junegunn/goyo.vim) and [vim-zenroom2](https://github.com/amix/vim-zenroom2) lets you only focus on one thing at a time. It removes all the distractions and centers the content. It has a special look when editing Markdown, reStructuredText and textfiles. It only has one mapping.
map <leader>z :Goyo<cr>
### Normal mode mappings ### Normal mode mappings
Fast saving of a buffer: Fast saving of a buffer:
@ -300,7 +315,6 @@ Vimscript mappings:
map <leader>n :cn<cr> map <leader>n :cn<cr>
map <leader>p :cp<cr> map <leader>p :cp<cr>
## Useful blog tips regarding my Vim setup ## Useful blog tips regarding my Vim setup
* [Vim: Annotate strings with gettext (the macro way)](http://amix.dk/blog/post/19678#Vim-Annotate-strings-with-gettext-the-macro-way) * [Vim: Annotate strings with gettext (the macro way)](http://amix.dk/blog/post/19678#Vim-Annotate-strings-with-gettext-the-macro-way)
@ -310,3 +324,5 @@ Vimscript mappings:
* [Vim 7.3: Persistent undo and encryption!](http://amix.dk/blog/post/19548#Vim-7-3-Persistent-undo-and-encryption) * [Vim 7.3: Persistent undo and encryption!](http://amix.dk/blog/post/19548#Vim-7-3-Persistent-undo-and-encryption)
* [Vim tips: Visual Search](http://amix.dk/blog/post/19334#Vim-tips-Visual-Search) * [Vim tips: Visual Search](http://amix.dk/blog/post/19334#Vim-tips-Visual-Search)
* [Folding in Vim](http://amix.dk/blog/post/19132#Folding-in-Vim) * [Folding in Vim](http://amix.dk/blog/post/19132#Folding-in-Vim)
* [
Zen room for Vim: Focusing only on the essential](http://amix.dk/blog/post/19744#zenroom-for-Vim-Focsuing-only-on-the-essential)

View file

@ -1,99 +0,0 @@
10
dir
24
svn://orangoo.com/vim/autoload
svn://orangoo.com/vim
2010-01-15T19:53:13.037300Z
2
amix
f0bd9f4a-2ac3-40fc-bab3-7711922a5bd5
fuf
dir
fuf.vim
file
2009-12-03T15:37:36.000000Z
cd795290ec0c8e87d61563c8553f6a5a
2010-01-15T19:52:41.083563Z
1
amix
34950
snipMate.vim
file
2010-01-15T16:14:44.000000Z
935ed920e29eeb56885cba09798db5ce
2010-01-15T19:52:41.083563Z
1
amix
14083

File diff suppressed because it is too large Load diff

View file

@ -1,433 +0,0 @@
fun! Filename(...)
let filename = expand('%:t:r')
if filename == '' | return a:0 == 2 ? a:2 : '' | endif
return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g')
endf
fun s:RemoveSnippet()
unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen
\ s:lastBuf s:oldWord
if exists('s:update')
unl s:startCol s:origWordLen s:update
if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif
endif
aug! snipMateAutocmds
endf
fun snipMate#expandSnip(snip, col)
let lnum = line('.') | let col = a:col
let snippet = s:ProcessSnippet(a:snip)
" Avoid error if eval evaluates to nothing
if snippet == '' | return '' | endif
" Expand snippet onto current position with the tab stops removed
let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1)
let line = getline(lnum)
let afterCursor = strpart(line, col - 1)
" Keep text after the cursor
if afterCursor != "\t" && afterCursor != ' '
let line = strpart(line, 0, col - 1)
let snipLines[-1] .= afterCursor
else
let afterCursor = ''
" For some reason the cursor needs to move one right after this
if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore'
let col += 1
endif
endif
call setline(lnum, line.snipLines[0])
" Autoindent snippet according to previous indentation
let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1
call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val"))
" Open any folds snippet expands into
if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif
let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent)
if s:snipLen
aug snipMateAutocmds
au CursorMovedI * call s:UpdateChangedSnip(0)
au InsertEnter * call s:UpdateChangedSnip(1)
aug END
let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer
let s:curPos = 0
let s:endCol = g:snipPos[s:curPos][1]
let s:endLine = g:snipPos[s:curPos][0]
call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
let s:prevLen = [line('$'), col('$')]
if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif
else
unl g:snipPos s:snipLen
" Place cursor at end of snippet if no tab stop is given
let newlines = len(snipLines) - 1
call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor)
\ + (newlines ? 0: col - 1))
endif
return ''
endf
" Prepare snippet to be processed by s:BuildTabStops
fun s:ProcessSnippet(snip)
let snippet = a:snip
" Evaluate eval (`...`) expressions.
" Using a loop here instead of a regex fixes a bug with nested "\=".
if stridx(snippet, '`') != -1
while match(snippet, '`.\{-}`') != -1
let snippet = substitute(snippet, '`.\{-}`',
\ substitute(eval(matchstr(snippet, '`\zs.\{-}\ze`')),
\ "\n\\%$", '', ''), '')
endw
let snippet = substitute(snippet, "\r", "\n", 'g')
endif
" Place all text after a colon in a tab stop after the tab stop
" (e.g. "${#:foo}" becomes "${:foo}foo").
" This helps tell the position of the tab stops later.
let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g')
" Update the a:snip so that all the $# become the text after
" the colon in their associated ${#}.
" (e.g. "${1:foo}" turns all "$1"'s into "foo")
let i = 1
while stridx(snippet, '${'.i) != -1
let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}')
if s != ''
let snippet = substitute(snippet, '$'.i, s.'&', 'g')
endif
let i += 1
endw
if &et " Expand tabs to spaces if 'expandtab' is set.
return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g')
endif
return snippet
endf
" Counts occurences of haystack in needle
fun s:Count(haystack, needle)
let counter = 0
let index = stridx(a:haystack, a:needle)
while index != -1
let index = stridx(a:haystack, a:needle, index+1)
let counter += 1
endw
return counter
endf
" Builds a list of a list of each tab stop in the snippet containing:
" 1.) The tab stop's line number.
" 2.) The tab stop's column number
" (by getting the length of the string between the last "\n" and the
" tab stop).
" 3.) The length of the text after the colon for the current tab stop
" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned.
" 4.) If the "${#:}" construct is given, another list containing all
" the matches of "$#", to be replaced with the placeholder. This list is
" composed the same way as the parent; the first item is the line number,
" and the second is the column.
fun s:BuildTabStops(snip, lnum, col, indent)
let snipPos = []
let i = 1
let withoutVars = substitute(a:snip, '$\d\+', '', 'g')
while stridx(a:snip, '${'.i) != -1
let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D')
let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g')
let j = i - 1
call add(snipPos, [0, 0, -1])
let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n")
let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D'))
if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif
" Get all $# matches in another list, if ${#:name} is given
if stridx(withoutVars, '${'.i.':') != -1
let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}'))
let dots = repeat('.', snipPos[j][2])
call add(snipPos[j], [])
let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g')
while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1
let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)')
call add(snipPos[j][3], [0, 0])
let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n")
let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum
\ ? len(matchstr(beforeMark, '.*\n\zs.*'))
\ : a:col + len(beforeMark))
let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '')
endw
endif
let i += 1
endw
return [snipPos, i - 1]
endf
fun snipMate#jumpTabStop(backwards)
let leftPlaceholder = exists('s:origWordLen')
\ && s:origWordLen != g:snipPos[s:curPos][2]
if leftPlaceholder && exists('s:oldEndCol')
let startPlaceholder = s:oldEndCol + 1
endif
if exists('s:update')
call s:UpdatePlaceholderTabStops()
else
call s:UpdateTabStops()
endif
" Don't reselect placeholder if it has been modified
if leftPlaceholder && g:snipPos[s:curPos][2] != -1
if exists('startPlaceholder')
let g:snipPos[s:curPos][1] = startPlaceholder
else
let g:snipPos[s:curPos][1] = col('.')
let g:snipPos[s:curPos][2] = 0
endif
endif
let s:curPos += a:backwards ? -1 : 1
" Loop over the snippet when going backwards from the beginning
if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif
if s:curPos == s:snipLen
let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2]
call s:RemoveSnippet()
return sMode ? "\<tab>" : TriggerSnippet()
endif
call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1])
let s:endLine = g:snipPos[s:curPos][0]
let s:endCol = g:snipPos[s:curPos][1]
let s:prevLen = [line('$'), col('$')]
return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord()
endf
fun s:UpdatePlaceholderTabStops()
let changeLen = s:origWordLen - g:snipPos[s:curPos][2]
unl s:startCol s:origWordLen s:update
if !exists('s:oldVars') | return | endif
" Update tab stops in snippet if text has been added via "$#"
" (e.g., in "${1:foo}bar$1${2}").
if changeLen != 0
let curLine = line('.')
for pos in g:snipPos
if pos == g:snipPos[s:curPos] | continue | endif
let changed = pos[0] == curLine && pos[1] > s:oldEndCol
let changedVars = 0
let endPlaceholder = pos[2] - 1 + pos[1]
" Subtract changeLen from each tab stop that was after any of
" the current tab stop's placeholders.
for [lnum, col] in s:oldVars
if lnum > pos[0] | break | endif
if pos[0] == lnum
if pos[1] > col || (pos[2] == -1 && pos[1] == col)
let changed += 1
elseif col < endPlaceholder
let changedVars += 1
endif
endif
endfor
let pos[1] -= changeLen * changed
let pos[2] -= changeLen * changedVars " Parse variables within placeholders
" e.g., "${1:foo} ${2:$1bar}"
if pos[2] == -1 | continue | endif
" Do the same to any placeholders in the other tab stops.
for nPos in pos[3]
let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol
for [lnum, col] in s:oldVars
if lnum > nPos[0] | break | endif
if nPos[0] == lnum && nPos[1] > col
let changed += 1
endif
endfor
let nPos[1] -= changeLen * changed
endfor
endfor
endif
unl s:endCol s:oldVars s:oldEndCol
endf
fun s:UpdateTabStops()
let changeLine = s:endLine - g:snipPos[s:curPos][0]
let changeCol = s:endCol - g:snipPos[s:curPos][1]
if exists('s:origWordLen')
let changeCol -= s:origWordLen
unl s:origWordLen
endif
let lnum = g:snipPos[s:curPos][0]
let col = g:snipPos[s:curPos][1]
" Update the line number of all proceeding tab stops if <cr> has
" been inserted.
if changeLine != 0
let changeLine -= 1
for pos in g:snipPos
if pos[0] >= lnum
if pos[0] == lnum | let pos[1] += changeCol | endif
let pos[0] += changeLine
endif
if pos[2] == -1 | continue | endif
for nPos in pos[3]
if nPos[0] >= lnum
if nPos[0] == lnum | let nPos[1] += changeCol | endif
let nPos[0] += changeLine
endif
endfor
endfor
elseif changeCol != 0
" Update the column of all proceeding tab stops if text has
" been inserted/deleted in the current line.
for pos in g:snipPos
if pos[1] >= col && pos[0] == lnum
let pos[1] += changeCol
endif
if pos[2] == -1 | continue | endif
for nPos in pos[3]
if nPos[0] > lnum | break | endif
if nPos[0] == lnum && nPos[1] >= col
let nPos[1] += changeCol
endif
endfor
endfor
endif
endf
fun s:SelectWord()
let s:origWordLen = g:snipPos[s:curPos][2]
let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1,
\ s:origWordLen)
let s:prevLen[1] -= s:origWordLen
if !empty(g:snipPos[s:curPos][3])
let s:update = 1
let s:endCol = -1
let s:startCol = g:snipPos[s:curPos][1] - 1
endif
if !s:origWordLen | return '' | endif
let l = col('.') != 1 ? 'l' : ''
if &sel == 'exclusive'
return "\<esc>".l.'v'.s:origWordLen."l\<c-g>"
endif
return s:origWordLen == 1 ? "\<esc>".l.'gh'
\ : "\<esc>".l.'v'.(s:origWordLen - 1)."l\<c-g>"
endf
" This updates the snippet as you type when text needs to be inserted
" into multiple places (e.g. in "${1:default text}foo$1bar$1",
" "default text" would be highlighted, and if the user types something,
" UpdateChangedSnip() would be called so that the text after "foo" & "bar"
" are updated accordingly)
"
" It also automatically quits the snippet if the cursor is moved out of it
" while in insert mode.
fun s:UpdateChangedSnip(entering)
if exists('g:snipPos') && bufnr(0) != s:lastBuf
call s:RemoveSnippet()
elseif exists('s:update') " If modifying a placeholder
if !exists('s:oldVars') && s:curPos + 1 < s:snipLen
" Save the old snippet & word length before it's updated
" s:startCol must be saved too, in case text is added
" before the snippet (e.g. in "foo$1${2}bar${1:foo}").
let s:oldEndCol = s:startCol
let s:oldVars = deepcopy(g:snipPos[s:curPos][3])
endif
let col = col('.') - 1
if s:endCol != -1
let changeLen = col('$') - s:prevLen[1]
let s:endCol += changeLen
else " When being updated the first time, after leaving select mode
if a:entering | return | endif
let s:endCol = col - 1
endif
" If the cursor moves outside the snippet, quit it
if line('.') != g:snipPos[s:curPos][0] || col < s:startCol ||
\ col - 1 > s:endCol
unl! s:startCol s:origWordLen s:oldVars s:update
return s:RemoveSnippet()
endif
call s:UpdateVars()
let s:prevLen[1] = col('$')
elseif exists('g:snipPos')
if !a:entering && g:snipPos[s:curPos][2] != -1
let g:snipPos[s:curPos][2] = -2
endif
let col = col('.')
let lnum = line('.')
let changeLine = line('$') - s:prevLen[0]
if lnum == s:endLine
let s:endCol += col('$') - s:prevLen[1]
let s:prevLen = [line('$'), col('$')]
endif
if changeLine != 0
let s:endLine += changeLine
let s:endCol = col
endif
" Delete snippet if cursor moves out of it in insert mode
if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1]))
\ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0]
call s:RemoveSnippet()
endif
endif
endf
" This updates the variables in a snippet when a placeholder has been edited.
" (e.g., each "$1" in "${1:foo} $1bar $1bar")
fun s:UpdateVars()
let newWordLen = s:endCol - s:startCol + 1
let newWord = strpart(getline('.'), s:startCol, newWordLen)
if newWord == s:oldWord || empty(g:snipPos[s:curPos][3])
return
endif
let changeLen = g:snipPos[s:curPos][2] - newWordLen
let curLine = line('.')
let startCol = col('.')
let oldStartSnip = s:startCol
let updateTabStops = changeLen != 0
let i = 0
for [lnum, col] in g:snipPos[s:curPos][3]
if updateTabStops
let start = s:startCol
if lnum == curLine && col <= start
let s:startCol -= changeLen
let s:endCol -= changeLen
endif
for nPos in g:snipPos[s:curPos][3][(i):]
" This list is in ascending order, so quit if we've gone too far.
if nPos[0] > lnum | break | endif
if nPos[0] == lnum && nPos[1] > col
let nPos[1] -= changeLen
endif
endfor
if lnum == curLine && col > start
let col -= changeLen
let g:snipPos[s:curPos][3][i][1] = col
endif
let i += 1
endif
" "Very nomagic" is used here to allow special characters.
call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'.
\ escape(s:oldWord, '\'), escape(newWord, '\&'), ''))
endfor
if oldStartSnip != s:startCol
call cursor(0, startCol + s:startCol - oldStartSnip)
endif
let s:oldWord = newWord
let g:snipPos[s:curPos][2] = newWordLen
endf
" vim:noet:sw=4:ts=4:ft=vim

356
autoload/pathogen.vim Normal file → Executable file
View file

@ -1,44 +1,56 @@
" pathogen.vim - path option manipulation " pathogen.vim - path option manipulation
" Maintainer: Tim Pope <http://tpo.pe/> " Maintainer: Tim Pope <http://tpo.pe/>
" Version: 2.0 " Version: 2.3
" Install in ~/.vim/autoload (or ~\vimfiles\autoload). " Install in ~/.vim/autoload (or ~\vimfiles\autoload).
" "
" For management of individually installed plugins in ~/.vim/bundle (or " For management of individually installed plugins in ~/.vim/bundle (or
" ~\vimfiles\bundle), adding `call pathogen#infect()` to your .vimrc " ~\vimfiles\bundle), adding `execute pathogen#infect()` to the top of your
" prior to `filetype plugin indent on` is the only other setup necessary. " .vimrc is the only other setup necessary.
" "
" The API is documented inline below. For maximum ease of reading, " The API is documented inline below.
" :set foldmethod=marker
if exists("g:loaded_pathogen") || &cp if exists("g:loaded_pathogen") || &cp
finish finish
endif endif
let g:loaded_pathogen = 1 let g:loaded_pathogen = 1
" Point of entry for basic default usage. Give a directory name to invoke " Point of entry for basic default usage. Give a relative path to invoke
" pathogen#runtime_append_all_bundles() (defaults to "bundle"), or a full path " pathogen#interpose() (defaults to "bundle/{}"), or an absolute path to invoke
" to invoke pathogen#runtime_prepend_subdirectories(). Afterwards, " pathogen#surround(). Curly braces are expanded with pathogen#expand():
" pathogen#cycle_filetype() is invoked. " "bundle/{}" finds all subdirectories inside "bundle" inside all directories
function! pathogen#infect(...) abort " {{{1 " in the runtime path.
let source_path = a:0 ? a:1 : 'bundle' function! pathogen#infect(...) abort
if source_path =~# '[\\/]' for path in a:0 ? filter(reverse(copy(a:000)), 'type(v:val) == type("")') : ['bundle/{}']
call pathogen#runtime_prepend_subdirectories(source_path) if path =~# '^\%({\=[$~\\/]\|{\=\w:[\\/]\).*[{}*]'
call pathogen#surround(path)
elseif path =~# '^\%([$~\\/]\|\w:[\\/]\)'
call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')')
call pathogen#surround(path . '/{}')
elseif path =~# '[{}*]'
call pathogen#interpose(path)
else else
call pathogen#runtime_append_all_bundles(source_path) call s:warn('Change pathogen#infect('.string(path).') to pathogen#infect('.string(path.'/{}').')')
call pathogen#interpose(path . '/{}')
endif endif
endfor
call pathogen#cycle_filetype() call pathogen#cycle_filetype()
endfunction " }}}1 if pathogen#is_disabled($MYVIMRC)
return 'finish'
endif
return ''
endfunction
" Split a path into a list. " Split a path into a list.
function! pathogen#split(path) abort " {{{1 function! pathogen#split(path) abort
if type(a:path) == type([]) | return a:path | endif if type(a:path) == type([]) | return a:path | endif
if empty(a:path) | return [] | endif
let split = split(a:path,'\\\@<!\%(\\\\\)*\zs,') let split = split(a:path,'\\\@<!\%(\\\\\)*\zs,')
return map(split,'substitute(v:val,''\\\([\\,]\)'',''\1'',"g")') return map(split,'substitute(v:val,''\\\([\\,]\)'',''\1'',"g")')
endfunction " }}}1 endfunction
" Convert a list to a path. " Convert a list to a path.
function! pathogen#join(...) abort " {{{1 function! pathogen#join(...) abort
if type(a:1) == type(1) && a:1 if type(a:1) == type(1) && a:1
let i = 1 let i = 1
let space = ' ' let space = ' '
@ -62,15 +74,143 @@ function! pathogen#join(...) abort " {{{1
let i += 1 let i += 1
endwhile endwhile
return substitute(path,'^,','','') return substitute(path,'^,','','')
endfunction " }}}1 endfunction
" Convert a list to a path with escaped spaces for 'path', 'tag', etc. " Convert a list to a path with escaped spaces for 'path', 'tag', etc.
function! pathogen#legacyjoin(...) abort " {{{1 function! pathogen#legacyjoin(...) abort
return call('pathogen#join',[1] + a:000) return call('pathogen#join',[1] + a:000)
endfunction " }}}1 endfunction
" Turn filetype detection off and back on again if it was already enabled.
function! pathogen#cycle_filetype() abort
if exists('g:did_load_filetypes')
filetype off
filetype on
endif
endfunction
" Check if a bundle is disabled. A bundle is considered disabled if its
" basename or full name is included in the list g:pathogen_disabled.
function! pathogen#is_disabled(path) abort
if a:path =~# '\~$'
return 1
endif
let sep = pathogen#slash()
let blacklist = map(
\ get(g:, 'pathogen_blacklist', get(g:, 'pathogen_disabled', [])) +
\ pathogen#split($VIMBLACKLIST),
\ 'substitute(v:val, "[\\/]$", "", "")')
return index(blacklist, fnamemodify(a:path, ':t')) != -1 || index(blacklist, a:path) != -1
endfunction "}}}1
" Prepend the given directory to the runtime path and append its corresponding
" after directory. Curly braces are expanded with pathogen#expand().
function! pathogen#surround(path) abort
let sep = pathogen#slash()
let rtp = pathogen#split(&rtp)
let path = fnamemodify(a:path, ':p:?[\\/]\=$??')
let before = filter(pathogen#expand(path), '!pathogen#is_disabled(v:val)')
let after = filter(reverse(pathogen#expand(path.sep.'after')), '!pathogen#is_disabled(v:val[0:-7])')
call filter(rtp, 'index(before + after, v:val) == -1')
let &rtp = pathogen#join(before, rtp, after)
return &rtp
endfunction
" For each directory in the runtime path, add a second entry with the given
" argument appended. Curly braces are expanded with pathogen#expand().
function! pathogen#interpose(name) abort
let sep = pathogen#slash()
let name = a:name
if has_key(s:done_bundles, name)
return ""
endif
let s:done_bundles[name] = 1
let list = []
for dir in pathogen#split(&rtp)
if dir =~# '\<after$'
let list += reverse(filter(pathogen#expand(dir[0:-6].name.sep.'after'), '!pathogen#is_disabled(v:val[0:-7])')) + [dir]
else
let list += [dir] + filter(pathogen#expand(dir.sep.name), '!pathogen#is_disabled(v:val)')
endif
endfor
let &rtp = pathogen#join(pathogen#uniq(list))
return 1
endfunction
let s:done_bundles = {}
" Invoke :helptags on all non-$VIM doc directories in runtimepath.
function! pathogen#helptags() abort
let sep = pathogen#slash()
for glob in pathogen#split(&rtp)
for dir in map(split(glob(glob), "\n"), 'v:val.sep."/doc/".sep')
if (dir)[0 : strlen($VIMRUNTIME)] !=# $VIMRUNTIME.sep && filewritable(dir) == 2 && !empty(split(glob(dir.'*.txt'))) && (!filereadable(dir.'tags') || filewritable(dir.'tags'))
silent! execute 'helptags' pathogen#fnameescape(dir)
endif
endfor
endfor
endfunction
command! -bar Helptags :call pathogen#helptags()
" Execute the given command. This is basically a backdoor for --remote-expr.
function! pathogen#execute(...) abort
for command in a:000
execute command
endfor
return ''
endfunction
" Section: Unofficial
function! pathogen#is_absolute(path) abort
return a:path =~# (has('win32') ? '^\%([\\/]\|\w:\)[\\/]\|^[~$]' : '^[/~$]')
endfunction
" Given a string, returns all possible permutations of comma delimited braced
" alternatives of that string. pathogen#expand('/{a,b}/{c,d}') yields
" ['/a/c', '/a/d', '/b/c', '/b/d']. Empty braces are treated as a wildcard
" and globbed. Actual globs are preserved.
function! pathogen#expand(pattern) abort
if a:pattern =~# '{[^{}]\+}'
let [pre, pat, post] = split(substitute(a:pattern, '\(.\{-\}\){\([^{}]\+\)}\(.*\)', "\\1\001\\2\001\\3", ''), "\001", 1)
let found = map(split(pat, ',', 1), 'pre.v:val.post')
let results = []
for pattern in found
call extend(results, pathogen#expand(pattern))
endfor
return results
elseif a:pattern =~# '{}'
let pat = matchstr(a:pattern, '^.*{}[^*]*\%($\|[\\/]\)')
let post = a:pattern[strlen(pat) : -1]
return map(split(glob(substitute(pat, '{}', '*', 'g')), "\n"), 'v:val.post')
else
return [a:pattern]
endif
endfunction
" \ on Windows unless shellslash is set, / everywhere else.
function! pathogen#slash() abort
return !exists("+shellslash") || &shellslash ? '/' : '\'
endfunction
function! pathogen#separator() abort
return pathogen#slash()
endfunction
" Convenience wrapper around glob() which returns a list.
function! pathogen#glob(pattern) abort
let files = split(glob(a:pattern),"\n")
return map(files,'substitute(v:val,"[".pathogen#slash()."/]$","","")')
endfunction "}}}1
" Like pathogen#glob(), only limit the results to directories.
function! pathogen#glob_directories(pattern) abort
return filter(pathogen#glob(a:pattern),'isdirectory(v:val)')
endfunction "}}}1
" Remove duplicates from a list. " Remove duplicates from a list.
function! pathogen#uniq(list) abort " {{{1 function! pathogen#uniq(list) abort
let i = 0 let i = 0
let seen = {} let seen = {}
while i < len(a:list) while i < len(a:list)
@ -85,103 +225,10 @@ function! pathogen#uniq(list) abort " {{{1
endif endif
endwhile endwhile
return a:list return a:list
endfunction " }}}1
" \ on Windows unless shellslash is set, / everywhere else.
function! pathogen#separator() abort " {{{1
return !exists("+shellslash") || &shellslash ? '/' : '\'
endfunction " }}}1
" Convenience wrapper around glob() which returns a list.
function! pathogen#glob(pattern) abort " {{{1
let files = split(glob(a:pattern),"\n")
return map(files,'substitute(v:val,"[".pathogen#separator()."/]$","","")')
endfunction "}}}1
" Like pathogen#glob(), only limit the results to directories.
function! pathogen#glob_directories(pattern) abort " {{{1
return filter(pathogen#glob(a:pattern),'isdirectory(v:val)')
endfunction "}}}1
" Turn filetype detection off and back on again if it was already enabled.
function! pathogen#cycle_filetype() " {{{1
if exists('g:did_load_filetypes')
filetype off
filetype on
endif
endfunction " }}}1
" Checks if a bundle is 'disabled'. A bundle is considered 'disabled' if
" its 'basename()' is included in g:pathogen_disabled[]' or ends in a tilde.
function! pathogen#is_disabled(path) " {{{1
if a:path =~# '\~$'
return 1
elseif !exists("g:pathogen_disabled")
return 0
endif
let sep = pathogen#separator()
return index(g:pathogen_disabled, strpart(a:path, strridx(a:path, sep)+1)) != -1
endfunction "}}}1
" Prepend all subdirectories of path to the rtp, and append all 'after'
" directories in those subdirectories.
function! pathogen#runtime_prepend_subdirectories(path) " {{{1
let sep = pathogen#separator()
let before = filter(pathogen#glob_directories(a:path.sep."*"), '!pathogen#is_disabled(v:val)')
let after = filter(pathogen#glob_directories(a:path.sep."*".sep."after"), '!pathogen#is_disabled(v:val[0:-7])')
let rtp = pathogen#split(&rtp)
let path = expand(a:path)
call filter(rtp,'v:val[0:strlen(path)-1] !=# path')
let &rtp = pathogen#join(pathogen#uniq(before + rtp + after))
return &rtp
endfunction " }}}1
" For each directory in rtp, check for a subdirectory named dir. If it
" exists, add all subdirectories of that subdirectory to the rtp, immediately
" after the original directory. If no argument is given, 'bundle' is used.
" Repeated calls with the same arguments are ignored.
function! pathogen#runtime_append_all_bundles(...) " {{{1
let sep = pathogen#separator()
let name = a:0 ? a:1 : 'bundle'
if "\n".s:done_bundles =~# "\\M\n".name."\n"
return ""
endif
let s:done_bundles .= name . "\n"
let list = []
for dir in pathogen#split(&rtp)
if dir =~# '\<after$'
let list += filter(pathogen#glob_directories(substitute(dir,'after$',name,'').sep.'*[^~]'.sep.'after'), '!pathogen#is_disabled(v:val[0:-7])') + [dir]
else
let list += [dir] + filter(pathogen#glob_directories(dir.sep.name.sep.'*[^~]'), '!pathogen#is_disabled(v:val)')
endif
endfor
let &rtp = pathogen#join(pathogen#uniq(list))
return 1
endfunction endfunction
let s:done_bundles = ''
" }}}1
" Invoke :helptags on all non-$VIM doc directories in runtimepath.
function! pathogen#helptags() " {{{1
let sep = pathogen#separator()
for dir in pathogen#split(&rtp)
if (dir.sep)[0 : strlen($VIMRUNTIME)] !=# $VIMRUNTIME.sep && filewritable(dir.sep.'doc') == 2 && !empty(filter(split(glob(dir.sep.'doc'.sep.'*'),"\n>"),'!isdirectory(v:val)')) && (!filereadable(dir.sep.'doc'.sep.'tags') || filewritable(dir.sep.'doc'.sep.'tags'))
helptags `=dir.'/doc'`
endif
endfor
endfunction " }}}1
command! -bar Helptags :call pathogen#helptags()
" Like findfile(), but hardcoded to use the runtimepath.
function! pathogen#runtime_findfile(file,count) "{{{1
let rtp = pathogen#join(1,pathogen#split(&rtp))
return fnamemodify(findfile(a:file,rtp,a:count),':p')
endfunction " }}}1
" Backport of fnameescape(). " Backport of fnameescape().
function! pathogen#fnameescape(string) " {{{1 function! pathogen#fnameescape(string) abort
if exists('*fnameescape') if exists('*fnameescape')
return fnameescape(a:string) return fnameescape(a:string)
elseif a:string ==# '-' elseif a:string ==# '-'
@ -189,24 +236,79 @@ function! pathogen#fnameescape(string) " {{{1
else else
return substitute(escape(a:string," \t\n*?[{`$\\%#'\"|!<"),'^[+>]','\\&','') return substitute(escape(a:string," \t\n*?[{`$\\%#'\"|!<"),'^[+>]','\\&','')
endif endif
endfunction " }}}1 endfunction
function! s:find(count,cmd,file,lcd) " {{{1 " Like findfile(), but hardcoded to use the runtimepath.
function! pathogen#runtime_findfile(file,count) abort "{{{1
let rtp = pathogen#join(1,pathogen#split(&rtp))
let file = findfile(a:file,rtp,a:count)
if file ==# ''
return ''
else
return fnamemodify(file,':p')
endif
endfunction
" Section: Deprecated
function! s:warn(msg) abort
echohl WarningMsg
echomsg a:msg
echohl NONE
endfunction
" Prepend all subdirectories of path to the rtp, and append all 'after'
" directories in those subdirectories. Deprecated.
function! pathogen#runtime_prepend_subdirectories(path) abort
call s:warn('Change pathogen#runtime_prepend_subdirectories('.string(a:path).') to pathogen#infect('.string(a:path.'/{}').')')
return pathogen#surround(a:path . pathogen#slash() . '{}')
endfunction
function! pathogen#incubate(...) abort
let name = a:0 ? a:1 : 'bundle/{}'
call s:warn('Change pathogen#incubate('.(a:0 ? string(a:1) : '').') to pathogen#infect('.string(name).')')
return pathogen#interpose(name)
endfunction
" Deprecated alias for pathogen#interpose().
function! pathogen#runtime_append_all_bundles(...) abort
if a:0
call s:warn('Change pathogen#runtime_append_all_bundles('.string(a:1).') to pathogen#infect('.string(a:1.'/{}').')')
else
call s:warn('Change pathogen#runtime_append_all_bundles() to pathogen#infect()')
endif
return pathogen#interpose(a:0 ? a:1 . '/{}' : 'bundle/{}')
endfunction
if exists(':Vedit')
finish
endif
let s:vopen_warning = 0
function! s:find(count,cmd,file,lcd)
let rtp = pathogen#join(1,pathogen#split(&runtimepath)) let rtp = pathogen#join(1,pathogen#split(&runtimepath))
let file = pathogen#runtime_findfile(a:file,a:count) let file = pathogen#runtime_findfile(a:file,a:count)
if file ==# '' if file ==# ''
return "echoerr 'E345: Can''t find file \"".a:file."\" in runtimepath'" return "echoerr 'E345: Can''t find file \"".a:file."\" in runtimepath'"
elseif a:lcd endif
if !s:vopen_warning
let s:vopen_warning = 1
let warning = '|echohl WarningMsg|echo "Install scriptease.vim to continue using :V'.a:cmd.'"|echohl NONE'
else
let warning = ''
endif
if a:lcd
let path = file[0:-strlen(a:file)-2] let path = file[0:-strlen(a:file)-2]
execute 'lcd `=path`' execute 'lcd `=path`'
return a:cmd.' '.pathogen#fnameescape(a:file) return a:cmd.' '.pathogen#fnameescape(a:file) . warning
else else
return a:cmd.' '.pathogen#fnameescape(file) return a:cmd.' '.pathogen#fnameescape(file) . warning
endif endif
endfunction " }}}1 endfunction
function! s:Findcomplete(A,L,P) " {{{1 function! s:Findcomplete(A,L,P)
let sep = pathogen#separator() let sep = pathogen#slash()
let cheats = { let cheats = {
\'a': 'autoload', \'a': 'autoload',
\'d': 'doc', \'d': 'doc',
@ -219,7 +321,7 @@ function! s:Findcomplete(A,L,P) " {{{1
else else
let request = a:A let request = a:A
endif endif
let pattern = substitute(request,'\'.sep,'*'.sep,'g').'*' let pattern = substitute(request,'/\|\'.sep,'*'.sep,'g').'*'
let found = {} let found = {}
for path in pathogen#split(&runtimepath) for path in pathogen#split(&runtimepath)
let path = expand(path, ':p') let path = expand(path, ':p')
@ -231,7 +333,7 @@ function! s:Findcomplete(A,L,P) " {{{1
endfor endfor
endfor endfor
return sort(keys(found)) return sort(keys(found))
endfunction " }}}1 endfunction
command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Ve :execute s:find(<count>,'edit<bang>',<q-args>,0) command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Ve :execute s:find(<count>,'edit<bang>',<q-args>,0)
command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vedit :execute s:find(<count>,'edit<bang>',<q-args>,0) command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vedit :execute s:find(<count>,'edit<bang>',<q-args>,0)
@ -242,4 +344,4 @@ command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vtabed
command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vpedit :execute s:find(<count>,'pedit',<q-args>,<bang>1) command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vpedit :execute s:find(<count>,'pedit',<q-args>,<bang>1)
command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vread :execute s:find(<count>,'read',<q-args>,<bang>1) command! -bar -bang -range=1 -nargs=1 -complete=customlist,s:Findcomplete Vread :execute s:find(<count>,'read',<q-args>,<bang>1)
" vim:set ft=vim ts=8 sw=2 sts=2: " vim:set et sw=2 foldmethod=expr foldexpr=getline(v\:lnum)=~'^\"\ Section\:'?'>1'\:getline(v\:lnum)=~#'^fu'?'a1'\:getline(v\:lnum)=~#'^endf'?'s1'\:'=':

View file

@ -36,7 +36,7 @@ if exists("syntax_on")
syntax reset syntax reset
endif endif
let g:colors_name = expand("<sfile>:t:r") let g:colors_name = "peaksea"
" I don't want to abuse folding, but here folding is used to avoid confusion. " I don't want to abuse folding, but here folding is used to avoid confusion.
if &background=='light' if &background=='light'
@ -281,7 +281,7 @@ elseif &background=='dark'
hi ModeMsg guifg=fg guibg=#000080 gui=NONE hi ModeMsg guifg=fg guibg=#000080 gui=NONE
hi VisualNOS guifg=fg guibg=#000080 gui=NONE hi VisualNOS guifg=fg guibg=#000080 gui=NONE
hi SpecialKey guifg=#b0d0f0 guibg=NONE gui=NONE hi SpecialKey guifg=#b0d0f0 guibg=NONE gui=NONE
hi NonText guifg=#6080f0 guibg=#101010 gui=NONE hi NonText guifg=#202020 guibg=#202020 gui=NONE
hi Directory guifg=#80c0e0 guibg=NONE gui=NONE hi Directory guifg=#80c0e0 guibg=NONE gui=NONE
hi ErrorMsg guifg=#d0d090 guibg=#800000 gui=NONE hi ErrorMsg guifg=#d0d090 guibg=#800000 gui=NONE
hi MoreMsg guifg=#c0e080 guibg=NONE gui=NONE hi MoreMsg guifg=#c0e080 guibg=NONE gui=NONE
@ -294,7 +294,7 @@ elseif &background=='dark'
hi DiffChange guifg=NONE guibg=#800080 gui=NONE hi DiffChange guifg=NONE guibg=#800080 gui=NONE
hi DiffDelete guifg=#6080f0 guibg=#202020 gui=NONE hi DiffDelete guifg=#6080f0 guibg=#202020 gui=NONE
hi DiffText guifg=#000000 guibg=#c0e080 gui=NONE hi DiffText guifg=#000000 guibg=#c0e080 gui=NONE
hi SignColumn guifg=#e0e0e0 guibg=#008000 gui=NONE hi SignColumn guifg=#e0e0e0 guibg=#202020 gui=NONE
hi IncSearch guifg=White guibg=DarkRed gui=NONE hi IncSearch guifg=White guibg=DarkRed gui=NONE
hi StatusLineNC guifg=#000000 guibg=#c0c0c0 gui=NONE hi StatusLineNC guifg=#000000 guibg=#c0c0c0 gui=NONE
hi VertSplit guifg=#000000 guibg=#c0c0c0 gui=NONE hi VertSplit guifg=#000000 guibg=#c0c0c0 gui=NONE

File diff suppressed because one or more lines are too long

View file

@ -1,107 +0,0 @@
=================
Powerline for vim
=================
:Author: Kim Silkebækken (kim.silkebaekken+vim@gmail.com)
:Source: https://github.com/Lokaltog/vim-powerline
:Version: β
Introduction
------------
Powerline is a utility plugin which allows you to create better-looking,
more functional vim statuslines. See the screenshots below for
a demonstration of the plugin's capabilities.
It's recommended that you install the plugin using Pathogen_ or Vundle_.
After the plugin is installed update your help tags and see ``:help
Powerline`` for instructions on how to enable and configure the plugin.
See the `Troubleshooting`_ section below if you're having any issues with
the plugin or the font patcher.
**Note:** You need a patched font to be able to use the symbols in the
statusline. An experimental Python/fontforge-based font patcher is included
in the ``fontpatcher`` directory. See ``fontpatcher/README.rst`` for usage
instructions.
.. _Pathogen: https://github.com/tpope/vim-pathogen
.. _Vundle: https://github.com/gmarik/vundle
Screenshots
-----------
.. image:: http://i.imgur.com/MsuIB.png
Troubleshooting
---------------
I can't see the fancy symbols, what's wrong?
Make sure that you have ``let g:Powerline_symbols = 'fancy'`` in your
``vimrc`` file. The settings may be loaded too late if you have this in
``gvimrc``, so always put this in your ``vimrc``.
Clear the cache using ``:PowerlineClearCache`` and restart vim.
Make sure that you've configured gvim or your terminal emulator to use
a patched font.
Make sure that vim is compiled with the ``--with-features=big`` flag.
The fancy symbols look a bit blurry or "off"!
Make sure that you have patched all variants of your font (i.e. both the
regular and the bold font files).
I'm unable to patch my font, what should I do?
Font patching is only known to work on most Linux and OS X machines. If
you have followed the instructions in the fontpatcher README and still
have problems, please submit an issue on GitHub.
You can download some community-contributed patched fonts from the
`Powerline wiki`_ if you don't want to mess around with the font
patcher.
The Syntastic/Fugitive statusline flags don't work!
These flags should work without any configuration. If you installed
either plugin after Powerline, you'll have to clear the cache using
``:PowerlineClearCache`` and restart vim.
The colors are weird in the default OS X Terminal app!
The default OS X Terminal app is known to have some issues with the
Powerline colors. Please use another terminal emulator. iTerm2 should
work fine.
The arrows may have the wrong colors if you have changed the "minimum
contrast" slider in the color tab of your OS X settings.
The statusline has strange characters like ``^B`` in it!
Please add ``set encoding=utf-8`` to your ``vimrc``.
You may also need to set your ``LANG`` and ``LC_*`` environment
variables to a UTF-8 locale (e.g. ``LANG=en_US.utf8``). Consult your
Linux distro's documentation for information about setting these
variables correctly.
The statusline has a lot of ``^`` or underline characters in it!
You need to configure the ``fillchars`` setting to disable statusline
fillchars (see ``:h fillchars`` for details). Add this to your
``vimrc`` to solve this issue::
set fillchars+=stl:\ ,stlnc:\
The statusline is hidden/only appears in split windows!
Make sure that you have ``set laststatus=2`` in your ``vimrc``.
I'm using tmux and Powerline looks like crap, what's wrong?
You need to tell tmux that it has 256-color capabilities. Add this to
your ``.tmux.conf`` to solve this issue::
set -g default-terminal "screen-256color"
If you use iTerm2, make sure that you have enabled the setting 'Set
locale variables automatically' in Profiles > Terminal > Environment.
If you have any other issues and you can't find the answer in the docs,
please submit an issue on GitHub.
.. _`Powerline wiki`: https://github.com/Lokaltog/vim-powerline/wiki/Patched-fonts

View file

@ -1,183 +0,0 @@
" Powerline - The ultimate statusline utility
"
" Author: Kim Silkebækken <kim.silkebaekken+vim@gmail.com>
" Source repository: https://github.com/Lokaltog/vim-powerline
" Script variables {{{
let g:Pl#OLD_STL = ''
let g:Pl#THEME = []
let g:Pl#THEME_CALLBACKS = []
let g:Pl#HL = []
" Cache revision, this must be incremented whenever the cache format is changed
let s:CACHE_REVISION = 7
" }}}
" Script initialization {{{
function! Pl#LoadCache() " {{{
if filereadable(g:Powerline_cache_file) && g:Powerline_cache_enabled
exec 'source' escape(g:Powerline_cache_file, ' \')
if ! exists('g:Powerline_cache_revision') || g:Powerline_cache_revision != s:CACHE_REVISION
" Cache revision differs, cache is invalid
unlet! g:Powerline_cache_revision
return 0
endif
" Create highlighting groups
for hi_cmd in g:Pl#HL
exec hi_cmd
endfor
" Run theme callbacks
for callback in g:Pl#THEME_CALLBACKS
" Substitute {{NEWLINE}} with newlines (strings must be
" stored without newlines characters to avoid vim errors)
exec substitute(callback[0], "{{NEWLINE}}", "\n", 'g')
exec substitute(callback[1], "{{NEWLINE}}", "\n", 'g')
endfor
return 1
endif
return 0
endfunction " }}}
function! Pl#ClearCache() " {{{
if filereadable(g:Powerline_cache_file)
" Delete the cache file
call delete(g:Powerline_cache_file)
endif
echo 'Powerline cache cleared. Please restart vim for the changes to take effect.'
endfunction " }}}
function! Pl#ReloadColorscheme() " {{{
call Pl#ClearCache()
" The colorscheme and theme files must be manually sourced because
" vim won't reload previously autoloaded files
"
" This is a bit hackish, but it works
unlet! g:Powerline#Colorschemes#{g:Powerline_colorscheme}#colorscheme
exec "source" split(globpath(&rtp, 'autoload/Powerline/Colorschemes/'. g:Powerline_colorscheme .'.vim', 1), '\n')[0]
unlet! g:Powerline#Themes#{g:Powerline_theme}#theme
exec "source" split(globpath(&rtp, 'autoload/Powerline/Themes/'. g:Powerline_theme .'.vim', 1), '\n')[0]
let g:Pl#THEME = []
call Pl#Load()
endfunction " }}}
function! Pl#Load() " {{{
if empty(g:Pl#OLD_STL)
" Store old statusline
let g:Pl#OLD_STL = &statusline
endif
if ! Pl#LoadCache()
try
" Autoload the theme dict first
let raw_theme = g:Powerline#Themes#{g:Powerline_theme}#theme
catch
echom 'Invalid Powerline theme! Please check your theme and colorscheme settings.'
return
endtry
" Create list with parsed statuslines
for buffer_statusline in raw_theme
unlet! mode_statuslines
let mode_statuslines = Pl#Parser#GetStatusline(buffer_statusline.segments)
if ! empty(buffer_statusline.callback)
" The callback function passes its arguments on to
" Pl#StatuslineCallback along with the normal/current mode
" statusline.
let s:cb_func = "function! PowerlineStatuslineCallback_". buffer_statusline.callback[1] ."(...)\n"
let s:cb_func .= "return Pl#StatuslineCallback(". string(mode_statuslines['n']) .", a:000)\n"
let s:cb_func .= "endfunction"
" The callback expression should be used to initialize any
" variables that will use the callback function. The
" expression requires a %s which will be replaced by the
" callback function name.
let s:cb_expr = printf(buffer_statusline.callback[2], 'PowerlineStatuslineCallback_'. buffer_statusline.callback[1])
exec s:cb_func
exec s:cb_expr
" Newlines must be substituted with another character
" because vim doesn't like newlines in strings
call add(g:Pl#THEME_CALLBACKS, [substitute(s:cb_func, "\n", "{{NEWLINE}}", 'g'), substitute(s:cb_expr, "\n", "{{NEWLINE}}", 'g')])
unlet! s:cb_func s:cb_expr
continue
endif
" Store the statuslines for matching specific buffers
call add(g:Pl#THEME, {
\ 'matches': buffer_statusline.matches,
\ 'mode_statuslines': mode_statuslines
\ })
endfor
if ! g:Powerline_cache_enabled
" Don't cache anything if caching is disabled or cache file isn't writeable
return
endif
" Prepare commands and statuslines for caching
let cache = [
\ 'let g:Powerline_cache_revision = '. string(s:CACHE_REVISION),
\ 'let g:Pl#HL = '. string(g:Pl#HL),
\ 'let g:Pl#THEME = '. string(g:Pl#THEME),
\ 'let g:Pl#THEME_CALLBACKS = '. string(g:Pl#THEME_CALLBACKS),
\ ]
call writefile(cache, g:Powerline_cache_file)
endif
endfunction " }}}
" }}}
" Statusline updater {{{
function! Pl#Statusline(statusline, current) " {{{
let mode = mode()
if ! a:current
let mode = 'N' " Normal (non-current)
elseif mode =~# '\v(v|V|)'
let mode = 'v' " Visual mode
elseif mode =~# '\v(s|S|)'
let mode = 's' " Select mode
elseif mode =~# '\vi'
let mode = 'i' " Insert mode
elseif mode =~# '\v(R|Rv)'
let mode = 'r' " Replace mode
else
" Fallback to normal mode
let mode = 'n' " Normal (current)
endif
return g:Pl#THEME[a:statusline].mode_statuslines[mode]
endfunction " }}}
function! Pl#StatuslineCallback(statusline, args) " {{{
" Replace %1, %2, etc. in the statusline with the callback args
return substitute(
\ a:statusline,
\ '\v\%(\d+)',
\ '\=a:args[submatch(1)]',
\ 'g')
endfunction " }}}
function! Pl#UpdateStatusline(current) " {{{
if empty(g:Pl#THEME)
" Load statuslines if they aren't loaded yet
call Pl#Load()
endif
for i in range(0, len(g:Pl#THEME) - 1)
if Pl#Match#Validate(g:Pl#THEME[i])
" Update window-local statusline
let &l:statusline = '%!Pl#Statusline('. i .','. a:current .')'
endif
endfor
endfunction " }}}
" }}}

View file

@ -1,145 +0,0 @@
function! Pl#Colorscheme#Init(hi) " {{{
let colorscheme = {}
for hi in a:hi
" Ensure that the segments are a list
let segments = type(hi[0]) == type('') ? [ hi[0] ] : hi[0]
let mode_hi_dict = hi[1]
for segment in segments
let colorscheme[segment] = mode_hi_dict
endfor
endfor
return colorscheme
endfunction " }}}
function! Pl#Colorscheme#Apply(colorscheme, buffer_segments) " {{{
" Set color parameters for all segments in a:buffer_segments
" TODO This function should be recursive and work on both segments and groups
" TODO We could probably handle the NS stuff here...
try
let colorscheme = g:Powerline#Colorschemes#{a:colorscheme}#colorscheme
catch
echom 'Color scheme "'. a:colorscheme .'" doesn''t exist!'
return
endtry
let buffer_segments = a:buffer_segments
" This is a bit complex, I'll walk you through exactly what happens here...
"
" First of all we loop through the buffer_segments, which are the segments that
" this specific buffer will have.
for buffer_segment in buffer_segments
" The buffer_segment consists of a 'matches' list and a 'segments' list.
" The 'matches' list has conditions to limit this statusline to specific buffers/windows.
" The 'segments' list has each segment and segment group for this buffer
for segment in buffer_segment.segments
let type = get(segment, 'type', '')
if type == 'segment_group'
" We're going to handle segment groups different from single segments. Segment groups
" have child segments which may have their own highlighting (e.g. fileinfo.flags),
" and these child segments may be grouped (e.g. fileinfo.flags.ro) to provide very
" specific highlighting. So here we'll handle all that:
" Set the default/fallback colors for this group
for i in range(len(segment.variants), 0, -1)
" Check for available highlighting for the main group segment
"
" This works like the segment highlighting below
" TODO Create a function for this
let seg_variants = join(segment.variants[0:i], '.')
let seg_name = i > 0 ? segment.name .'.'. seg_variants : segment.name
let seg_ns_name = len(segment.ns) > 0 ? segment.ns .':'. seg_name : seg_name
if has_key(colorscheme, seg_ns_name)
" We have a namespaced highlight group
let segment.colors = colorscheme[seg_ns_name]
break
elseif has_key(colorscheme, seg_name)
" We have a non-namespaced group
let segment.colors = colorscheme[seg_name]
break
endif
endfor
" The reason why we need to deepcopy the group's segments is that the child segments
" all point to the same base segments and that screws up highlighting if we highlight
" some child segments with different namespaced colors
let segment.segments = deepcopy(segment.segments)
" Apply colors to each child segment
for child_segment in segment.segments
" Check if this child segment is grouped (e.g. fileinfo.flags.group.subgroup)
" We're going to prioritize the most specific grouping and then work back to the
" most common group (e.g. fileinfo.flags)
" FIXME We don't have the variants from before because group children aren't run through Pl#Segment#Get
let child_segment.variants = [seg_name] + split(child_segment.name, '\.')
" Use the parent group's namespace
let child_segment.ns = segment.ns
for i in range(len(child_segment.variants), 0, -1)
" Check for available highlighting for the main group segment
let child_seg_name = join(child_segment.variants[0:i], '.')
let child_seg_ns_name = len(child_segment.ns) > 0 ? child_segment.ns .':'. child_seg_name : child_seg_name
if has_key(colorscheme, child_seg_ns_name)
" We have a namespaced highlight group
let child_segment.colors = colorscheme[child_seg_ns_name]
break
elseif has_key(colorscheme, child_seg_name)
" We have a non-namespaced group
let child_segment.colors = colorscheme[child_seg_name]
break
endif
endfor
endfor
elseif type == 'segment'
for i in range(len(segment.variants), 0, -1)
" Check for available highlighting
"
" This is done in the following manner, using the segment gundo:static_filename.text.buffer as an example:
"
" * Look for the hl group: gundo:static_filename.text.buffer
" * Look for the hl group: static_filename.text.buffer
" * Look for the hl group: gundo:static_filename.text
" * Look for the hl group: static_filename.text
" * Look for the hl group: gundo:static_filename
" * Look for the hl group: static_filename
" * Return the segment without highlighting, causing an error in the parser
let seg_variants = join(segment.variants[0:i], '.')
let seg_name = i > 0 ? segment.name .'.'. seg_variants : segment.name
let seg_ns_name = len(segment.ns) > 0 ? segment.ns .':'. seg_name : seg_name
if has_key(colorscheme, seg_ns_name)
" We have a namespaced highlight group
let segment.colors = colorscheme[seg_ns_name]
break
elseif has_key(colorscheme, seg_name)
" We have a non-namespaced group
let segment.colors = colorscheme[seg_name]
break
endif
endfor
endif
unlet! segment
endfor
endfor
" Good luck parsing this return value
"
" It's a huge dict with all segments for all buffers with their respective syntax highlighting.
" It will be parsed by the main Powerline code, where all the data will be shortened to a simple
" array consiting of a statusline for each mode, with generated highlighting groups and dividers.
return buffer_segments
endfunction " }}}

View file

@ -1,140 +0,0 @@
" cterm -> gui color dict {{{
let s:cterm2gui_dict = {
\ 16: 0x000000, 17: 0x00005f, 18: 0x000087, 19: 0x0000af, 20: 0x0000d7, 21: 0x0000ff,
\ 22: 0x005f00, 23: 0x005f5f, 24: 0x005f87, 25: 0x005faf, 26: 0x005fd7, 27: 0x005fff,
\ 28: 0x008700, 29: 0x00875f, 30: 0x008787, 31: 0x0087af, 32: 0x0087d7, 33: 0x0087ff,
\ 34: 0x00af00, 35: 0x00af5f, 36: 0x00af87, 37: 0x00afaf, 38: 0x00afd7, 39: 0x00afff,
\ 40: 0x00d700, 41: 0x00d75f, 42: 0x00d787, 43: 0x00d7af, 44: 0x00d7d7, 45: 0x00d7ff,
\ 46: 0x00ff00, 47: 0x00ff5f, 48: 0x00ff87, 49: 0x00ffaf, 50: 0x00ffd7, 51: 0x00ffff,
\ 52: 0x5f0000, 53: 0x5f005f, 54: 0x5f0087, 55: 0x5f00af, 56: 0x5f00d7, 57: 0x5f00ff,
\ 58: 0x5f5f00, 59: 0x5f5f5f, 60: 0x5f5f87, 61: 0x5f5faf, 62: 0x5f5fd7, 63: 0x5f5fff,
\ 64: 0x5f8700, 65: 0x5f875f, 66: 0x5f8787, 67: 0x5f87af, 68: 0x5f87d7, 69: 0x5f87ff,
\ 70: 0x5faf00, 71: 0x5faf5f, 72: 0x5faf87, 73: 0x5fafaf, 74: 0x5fafd7, 75: 0x5fafff,
\ 76: 0x5fd700, 77: 0x5fd75f, 78: 0x5fd787, 79: 0x5fd7af, 80: 0x5fd7d7, 81: 0x5fd7ff,
\ 82: 0x5fff00, 83: 0x5fff5f, 84: 0x5fff87, 85: 0x5fffaf, 86: 0x5fffd7, 87: 0x5fffff,
\ 88: 0x870000, 89: 0x87005f, 90: 0x870087, 91: 0x8700af, 92: 0x8700d7, 93: 0x8700ff,
\ 94: 0x875f00, 95: 0x875f5f, 96: 0x875f87, 97: 0x875faf, 98: 0x875fd7, 99: 0x875fff,
\ 100: 0x878700, 101: 0x87875f, 102: 0x878787, 103: 0x8787af, 104: 0x8787d7, 105: 0x8787ff,
\ 106: 0x87af00, 107: 0x87af5f, 108: 0x87af87, 109: 0x87afaf, 110: 0x87afd7, 111: 0x87afff,
\ 112: 0x87d700, 113: 0x87d75f, 114: 0x87d787, 115: 0x87d7af, 116: 0x87d7d7, 117: 0x87d7ff,
\ 118: 0x87ff00, 119: 0x87ff5f, 120: 0x87ff87, 121: 0x87ffaf, 122: 0x87ffd7, 123: 0x87ffff,
\ 124: 0xaf0000, 125: 0xaf005f, 126: 0xaf0087, 127: 0xaf00af, 128: 0xaf00d7, 129: 0xaf00ff,
\ 130: 0xaf5f00, 131: 0xaf5f5f, 132: 0xaf5f87, 133: 0xaf5faf, 134: 0xaf5fd7, 135: 0xaf5fff,
\ 136: 0xaf8700, 137: 0xaf875f, 138: 0xaf8787, 139: 0xaf87af, 140: 0xaf87d7, 141: 0xaf87ff,
\ 142: 0xafaf00, 143: 0xafaf5f, 144: 0xafaf87, 145: 0xafafaf, 146: 0xafafd7, 147: 0xafafff,
\ 148: 0xafd700, 149: 0xafd75f, 150: 0xafd787, 151: 0xafd7af, 152: 0xafd7d7, 153: 0xafd7ff,
\ 154: 0xafff00, 155: 0xafff5f, 156: 0xafff87, 157: 0xafffaf, 158: 0xafffd7, 159: 0xafffff,
\ 160: 0xd70000, 161: 0xd7005f, 162: 0xd70087, 163: 0xd700af, 164: 0xd700d7, 165: 0xd700ff,
\ 166: 0xd75f00, 167: 0xd75f5f, 168: 0xd75f87, 169: 0xd75faf, 170: 0xd75fd7, 171: 0xd75fff,
\ 172: 0xd78700, 173: 0xd7875f, 174: 0xd78787, 175: 0xd787af, 176: 0xd787d7, 177: 0xd787ff,
\ 178: 0xd7af00, 179: 0xd7af5f, 180: 0xd7af87, 181: 0xd7afaf, 182: 0xd7afd7, 183: 0xd7afff,
\ 184: 0xd7d700, 185: 0xd7d75f, 186: 0xd7d787, 187: 0xd7d7af, 188: 0xd7d7d7, 189: 0xd7d7ff,
\ 190: 0xd7ff00, 191: 0xd7ff5f, 192: 0xd7ff87, 193: 0xd7ffaf, 194: 0xd7ffd7, 195: 0xd7ffff,
\ 196: 0xff0000, 197: 0xff005f, 198: 0xff0087, 199: 0xff00af, 200: 0xff00d7, 201: 0xff00ff,
\ 202: 0xff5f00, 203: 0xff5f5f, 204: 0xff5f87, 205: 0xff5faf, 206: 0xff5fd7, 207: 0xff5fff,
\ 208: 0xff8700, 209: 0xff875f, 210: 0xff8787, 211: 0xff87af, 212: 0xff87d7, 213: 0xff87ff,
\ 214: 0xffaf00, 215: 0xffaf5f, 216: 0xffaf87, 217: 0xffafaf, 218: 0xffafd7, 219: 0xffafff,
\ 220: 0xffd700, 221: 0xffd75f, 222: 0xffd787, 223: 0xffd7af, 224: 0xffd7d7, 225: 0xffd7ff,
\ 226: 0xffff00, 227: 0xffff5f, 228: 0xffff87, 229: 0xffffaf, 230: 0xffffd7, 231: 0xffffff,
\ 232: 0x080808, 233: 0x121212, 234: 0x1c1c1c, 235: 0x262626, 236: 0x303030, 237: 0x3a3a3a,
\ 238: 0x444444, 239: 0x4e4e4e, 240: 0x585858, 241: 0x626262, 242: 0x6c6c6c, 243: 0x767676,
\ 244: 0x808080, 245: 0x8a8a8a, 246: 0x949494, 247: 0x9e9e9e, 248: 0xa8a8a8, 249: 0xb2b2b2,
\ 250: 0xbcbcbc, 251: 0xc6c6c6, 252: 0xd0d0d0, 253: 0xdadada, 254: 0xe4e4e4, 255: 0xeeeeee
\ }
" }}}
" Allocated color dict {{{
let s:allocated_colors = {
\ 'NONE': 'NONE',
\ }
" }}}
function! s:Cterm2GUI(cterm) " {{{
if toupper(a:cterm) == 'NONE'
return 'NONE'
endif
if ! has_key(s:cterm2gui_dict, a:cterm)
return 0xff0000
endif
return s:cterm2gui_dict[a:cterm]
endfunction " }}}
function! Pl#Hi#Segments(segments, mode_colors) " {{{
let mode_translate = {
\ 'normal': 'n',
\ 'noncurrent': 'N',
\ 'insert': 'i',
\ 'visual': 'v',
\ 'replace': 'r',
\ 'select': 's',
\ }
let attributes = ['bold', 'italic', 'underline']
let segments = a:segments
let mode_hi_dict = {}
" Mode dict
for [mode, colors] in items(a:mode_colors)
if has_key(mode_translate, mode)
let mode = mode_translate[mode]
endif
unlet! fg
let fg = s:allocated_colors[colors[0]]
let hi = {
\ 'cterm': [fg['cterm'], ''],
\ 'gui' : [fg['gui'], ''],
\ 'attr' : []
\ }
if exists('colors[1]')
if type(colors[1]) == type([])
" We don't have a BG color, but we have attributes
let hi.attr = colors[1]
else
" The second parameter is the background color
unlet! bg
let bg = s:allocated_colors[colors[1]]
let hi.cterm[1] = bg['cterm']
let hi.gui[1] = bg['gui']
endif
endif
if exists('colors[2]') && type(colors[2]) == type([])
" The third parameter is always an attribute list
let hi.attr = colors[2]
endif
let mode_hi_dict[mode] = {
\ 'ctermfg': (empty(hi['cterm'][0]) ? '' : (string(hi['cterm'][0]) == 'NONE' ? 'NONE' : hi['cterm'][0])),
\ 'ctermbg': (empty(hi['cterm'][1]) ? '' : (string(hi['cterm'][1]) == 'NONE' ? 'NONE' : hi['cterm'][1])),
\ 'guifg' : (empty(hi['gui'][0]) ? '' : (string(hi['gui'][0]) == 'NONE' ? 'NONE' : hi['gui'][0])),
\ 'guibg' : (empty(hi['gui'][1]) ? '' : (string(hi['gui'][1]) == 'NONE' ? 'NONE' : hi['gui'][1])),
\ 'attr' : (! len(hi['attr']) ? 'NONE' : join(hi['attr'], ','))
\ }
endfor
return [segments, mode_hi_dict]
endfunction " }}}
function! Pl#Hi#Allocate(colors) " {{{
for [key, color] in items(a:colors)
if type(color) == type(0)
" Only terminal color
let cterm = color
let gui = s:Cterm2GUI(color)
elseif type(color) == type([]) && len(color) == 2
" Terminal and GUI colors
let cterm = color[0]
let gui = color[1]
endif
let s:allocated_colors[key] = {
\ 'cterm': cterm,
\ 'gui': gui,
\ }
unlet! color
endfor
endfunction " }}}

View file

@ -1,43 +0,0 @@
function! Pl#Match#Add(pat, expr) " {{{
return [a:pat, a:expr]
endfunction " }}}
function! Pl#Match#Any(...) " {{{
let matches = []
for match_name in a:000
if empty(match_name)
" Skip empty match parameters
continue
endif
if has_key(g:Powerline#Matches#matches, match_name)
call add(matches, g:Powerline#Matches#matches[match_name])
endif
unlet! match_name
endfor
return ['match', 'any', matches]
endfunction " }}}
function! Pl#Match#Validate(theme) " {{{
let match = a:theme.matches[1]
if match == 'none'
return 0
elseif match == 'any'
let matches = a:theme.matches[2]
if ! len(matches)
" Empty match array matches everything
return 1
endif
for [eval, re] in matches
if match(eval(eval), '\v'. re) != -1
return 1
endif
endfor
return 0
endif
endfunction " }}}

View file

@ -1,40 +0,0 @@
let s:segment_mods = []
function! Pl#Mod#AddSegmentMod(action, properties) " {{{
call add(s:segment_mods, [a:action, a:properties])
endfunction " }}}
function! Pl#Mod#ApplySegmentMods(theme) " {{{
let theme = deepcopy(a:theme)
for mod in s:segment_mods
let [action, properties] = mod
" We have to loop through the segments instead of using index() because some
" segments are lists!
let target_seg_idx = -1
for i in range(0, len(theme) - 1)
unlet! segment
let segment = theme[i]
if type(segment) == type(properties.target_segment) && segment == properties.target_segment
let target_seg_idx = i
break
endif
endfor
if action == 'insert_segment'
" Insert segment
if target_seg_idx != -1
call insert(theme, properties.new_segment, (properties.where == 'before' ? target_seg_idx : target_seg_idx + 1))
endif
elseif action == 'remove_segment'
" Remove segment
if target_seg_idx != -1
call remove(theme, target_seg_idx)
endif
endif
endfor
return theme
endfunction " }}}

View file

@ -1,371 +0,0 @@
let g:Pl#Parser#Symbols = {
\ 'compatible': {
\ 'dividers': [ '', [0x2502], '', [0x2502] ]
\ , 'symbols' : {
\ 'BRANCH': 'BR:'
\ , 'RO' : 'RO'
\ , 'FT' : 'FT'
\ , 'LINE' : 'LN'
\ }
\ },
\ 'unicode': {
\ 'dividers': [ [0x25b6], [0x276f], [0x25c0], [0x276e] ]
\ , 'symbols' : {
\ 'BRANCH': [0x26a1]
\ , 'RO' : [0x2613]
\ , 'FT' : [0x2691]
\ , 'LINE' : [0x204b]
\ },
\ },
\ 'fancy': {
\ 'dividers': [ [0x2b80], [0x2b81], [0x2b82], [0x2b83] ]
\ , 'symbols' : {
\ 'BRANCH': [0x2b60]
\ , 'RO' : [0x2b64]
\ , 'FT' : [0x2b62, 0x2b63]
\ , 'LINE' : [0x2b61]
\ }
\ }
\ }
" Handle symbol overrides
for [s:key, s:value] in items(g:Powerline_symbols_override)
let g:Pl#Parser#Symbols[g:Powerline_symbols].symbols[s:key] = s:value
unlet! s:key s:value
endfor
" Handle divider overrides
if len(g:Powerline_dividers_override) == 4
let g:Pl#Parser#Symbols[g:Powerline_symbols].dividers = g:Powerline_dividers_override
endif
let s:LEFT_SIDE = 0
let s:RIGHT_SIDE = 2
let s:PADDING = 1
let s:EMPTY_SEGMENT = { 'type': 'empty' }
let s:HARD_DIVIDER = 0
let s:SOFT_DIVIDER = 1
function! Pl#Parser#GetStatusline(segments) " {{{
let statusline = {
\ 'n': ''
\ , 'N': ''
\ , 'v': ''
\ , 'i': ''
\ , 'r': ''
\ , 's': ''
\ }
" Run through the different modes and create the statuslines
for mode in keys(statusline)
" Create an empty statusline list
let stl = []
call extend(stl, s:ParseSegments(mode, s:LEFT_SIDE, a:segments))
let statusline[mode] .= join(stl, '')
endfor
return statusline
endfunction " }}}
function! Pl#Parser#ParseChars(arg) " {{{
" Handles symbol arrays which can be either an array of hex values,
" or a string. Will convert the hex array to a string, or return the
" string as-is.
let arg = a:arg
if type(arg) == type([])
" Hex array
call map(arg, 'nr2char(v:val)')
return join(arg, '')
endif
" Anything else, just return it as it is
return arg
endfunction " }}}
function! s:ParseSegments(mode, side, segments, ...) " {{{
let mode = a:mode
let side = a:side
let segments = a:segments
let level = exists('a:1') ? a:1 : 0
let base_color = exists('a:2') ? a:2 : {}
let ret = []
for i in range(0, len(segments) - 1)
unlet! seg_prev seg_curr seg_next
" Prepare some resources (fetch previous, current and next segment)
let seg_curr = deepcopy(get(segments, i))
" Find previous segment
let seg_prev = s:EMPTY_SEGMENT
" If we're currently at i = 0 we have to start on 0 or else we will start on the last segment (list[-1])
let range_start = (i == 0 ? i : i - 1)
for j in range(range_start, 0, -1)
let seg = deepcopy(get(segments, j))
if get(seg, 'name') ==# 'TRUNCATE'
" Skip truncate segments
continue
endif
" Look ahead for another segment that's visible in this mode
if index(get(seg, 'modes'), mode) != -1
" Use this segment
let seg_prev = seg
break
endif
endfor
"" Find next segment
let seg_next = s:EMPTY_SEGMENT
" If we're currently at i = len(segments) - 1 we have to start on i or else we will get an error because the index doesn't exist
let range_start = (i == len(segments) - 1 ? i : i + 1)
for j in range(range_start, len(segments) - 1, 1)
let seg = deepcopy(get(segments, j))
if get(seg, 'name') ==# 'TRUNCATE'
" Skip truncate segments
continue
endif
" Look ahead for another segment that's visible in this mode
if index(get(seg, 'modes'), mode) != -1
" Use this segment
let seg_next = seg
break
endif
endfor
if index(get(seg_curr, 'modes', []), mode) == -1
" The segment is invisible in this mode, skip it
" FIXME When two segments after each other are hidden, a gap appears where the segments would be, this is probably due to segment padding
continue
endif
" Handle the different segment types
if seg_curr.type == 'segment'
if seg_curr.name ==# 'TRUNCATE'
" Truncate statusline
call add(ret, '%<')
elseif seg_curr.name ==# 'SPLIT'
" Split statusline
" Switch sides
let side = s:RIGHT_SIDE
" Handle highlighting
let mode_colors = get(seg_curr.colors, mode, seg_curr.colors['n'])
let hl_group = s:HlCreate(mode_colors)
" Add segment text
call add(ret, '%#'. hl_group .'#%=')
else
" Add segment text
let text = seg_curr.text
" Decide on whether to use the group's colors or the segment's colors
let colors = get(seg_curr, 'colors', base_color)
" Fallback to normal (current) highlighting if we don't have mode-specific highlighting
let mode_colors = get(colors, mode, get(colors, 'n', {}))
if empty(mode_colors)
echom 'Segment doesn''t have any colors! NS: "'. seg_curr.ns .'" SEG: "'. seg_curr.name .'"'
continue
endif
" Check if we're in a group (level > 0)
if level > 0
" If we're in a group we don't have dividers between
" segments, so we should only pad one side, but only pad
" if the segment doesn't have Pl#Segment#NoPadding() set
let padding_right = (seg_curr.padding && side == s:LEFT_SIDE ? repeat(' ', s:PADDING) : '')
let padding_left = (seg_curr.padding && side == s:RIGHT_SIDE ? repeat(' ', s:PADDING) : '')
" Check if we lack a bg/fg color for this segment
" If we do, use the bg/fg color from base_color
let base_color_mode = ! has_key(base_color, mode) ? base_color['n'] : base_color[mode]
for col in ['ctermbg', 'ctermfg', 'guibg', 'guifg']
if empty(mode_colors[col])
let mode_colors[col] = base_color_mode[col]
endif
endfor
else
"" If we're outside a group we have dividers and must pad both sides
let padding_left = repeat(' ', s:PADDING)
let padding_right = repeat(' ', s:PADDING)
endif
" Get main hl group for segment
let hl_group = s:HlCreate(mode_colors)
" Prepare segment text
let text = '%(%#'. hl_group .'#'. padding_left . text . padding_right . '%)'
if level == 0
" Add divider to single segments
let text = s:AddDivider(text, side, mode, colors, seg_prev, seg_curr, seg_next)
endif
call add(ret, text)
endif
elseif seg_curr.type == 'segment_group'
" Recursively parse segment group
let func_params = [mode, side, seg_curr.segments, level + 1]
if has_key(seg_curr, 'colors')
" Pass the base colors on to the child segments
call add(func_params, seg_curr.colors)
endif
" Get segment group string
let text = join(call('s:ParseSegments', func_params), '')
" Pad on the opposite side of the divider
let padding_right = (side == s:RIGHT_SIDE ? repeat(' ', s:PADDING) : '')
let padding_left = (side == s:LEFT_SIDE ? repeat(' ', s:PADDING) : '')
let text = s:AddDivider(padding_left . text . padding_right, side, mode, seg_curr.colors, seg_prev, seg_curr, seg_next)
call add(ret, text)
endif
endfor
return ret
endfunction " }}}
function! s:HlCreate(hl) " {{{
" Create a short and unique highlighting group name
" It uses the hex values of all the color properties and an attribute flag at the end
" NONE colors are translated to NN for cterm and NNNNNN for gui colors
let hi_group = printf('Pl%s%s%s%s%s'
\ , (a:hl['ctermfg'] == 'NONE' ? 'NN' : printf('%02x', a:hl['ctermfg']))
\ , (a:hl['guifg'] == 'NONE' ? 'NNNNNN' : printf('%06x', a:hl['guifg'] ))
\ , (a:hl['ctermbg'] == 'NONE' ? 'NN' : printf('%02x', a:hl['ctermbg']))
\ , (a:hl['guibg'] == 'NONE' ? 'NNNNNN' : printf('%06x', a:hl['guibg'] ))
\ , substitute(a:hl['attr'], '\v([a-zA-Z])[a-zA-Z]*,?', '\1', 'g')
\ )
if ! s:HlExists(hi_group)
let ctermbg = a:hl['ctermbg'] == 'NONE' ? 'NONE' : printf('%d', a:hl['ctermbg'])
if (has('win32') || has('win64')) && !has('gui_running') && ctermbg != 'NONE' && ctermbg > 128
let ctermbg -= 128
endif
let hi_cmd = printf('hi %s ctermfg=%s ctermbg=%s cterm=%s guifg=%s guibg=%s gui=%s'
\ , hi_group
\ , a:hl['ctermfg'] == 'NONE' ? 'NONE' : printf('%d', a:hl['ctermfg'])
\ , ctermbg
\ , a:hl['attr']
\ , (a:hl['guifg'] == 'NONE' ? 'NONE' : printf('#%06x', a:hl['guifg']))
\ , (a:hl['guibg'] == 'NONE' ? 'NONE' : printf('#%06x', a:hl['guibg']))
\ , a:hl['attr']
\ )
exec hi_cmd
" Add command to Pl#HL list for caching
call add(g:Pl#HL, hi_cmd)
endif
" Return only the highlighting group name
return hi_group
endfunction " }}}
function! s:HlExists(hl) " {{{
if ! hlexists(a:hl)
return 0
endif
redir => hlstatus
silent exec 'hi' a:hl
redir END
return (hlstatus !~ 'cleared')
endfunction " }}}
function! s:AddDivider(text, side, mode, colors, prev, curr, next) " {{{
let seg_prev = a:prev
let seg_curr = a:curr
let seg_next = a:next
" Set default color/type for the divider
let div_colors = get(a:colors, a:mode, a:colors['n'])
let div_type = s:SOFT_DIVIDER
" Define segment to compare
let cmp_seg = a:side == s:LEFT_SIDE ? seg_next : seg_prev
let cmp_all_colors = get(cmp_seg, 'colors', {})
let cmp_colors = get(cmp_all_colors, a:mode, get(cmp_all_colors, 'n', {}))
if ! empty(cmp_colors)
" Compare the highlighting groups
"
" If the background color for cterm is equal, use soft divider with the current segment's highlighting
" If not, use hard divider with a new highlighting group
"
" Note that if the previous/next segment is the split, a hard divider is always used
if get(div_colors, 'ctermbg') != get(cmp_colors, 'ctermbg') || get(seg_next, 'name') ==# 'SPLIT' || get(seg_prev, 'name') ==# 'SPLIT'
let div_type = s:HARD_DIVIDER
" Create new highlighting group
if div_colors['attr'] =~ 'reverse' && cmp_colors['attr'] =~ 'reverse'
" Use FG = CURRENT FG, BG = CMP FG
let div_colors['ctermbg'] = get(cmp_colors, 'ctermfg')
let div_colors['guibg'] = get(cmp_colors, 'guifg')
let div_colors['attr'] = div_colors['attr'] =~ 'bold' ? 'bold' : 'NONE'
elseif div_colors['attr'] =~ 'reverse'
" Use FG = CURRENT FG, BG = CMP BG
let div_colors['ctermbg'] = get(cmp_colors, 'ctermbg')
let div_colors['guibg'] = get(cmp_colors, 'guibg')
let div_colors['attr'] = div_colors['attr'] =~ 'bold' ? 'bold' : 'NONE'
elseif cmp_colors['attr'] =~ 'reverse'
" Use FG = CMP FG, BG = CURRENT BG : reversed
let div_colors['ctermfg'] = get(cmp_colors, 'ctermfg')
let div_colors['guifg'] = get(cmp_colors, 'guifg')
let div_colors['attr'] = 'reverse'
else
" Use FG = CURRENT BG, BG = CMP BG
let div_colors['ctermfg'] = get(div_colors, 'ctermbg')
let div_colors['guifg'] = get(div_colors, 'guibg')
let div_colors['ctermbg'] = get(cmp_colors, 'ctermbg')
let div_colors['guibg'] = get(cmp_colors, 'guibg')
let div_colors['attr'] = 'NONE'
endif
endif
endif
" Prepare divider
let divider_raw = deepcopy(g:Pl#Parser#Symbols[g:Powerline_symbols].dividers[a:side + div_type])
let divider = Pl#Parser#ParseChars(divider_raw)
" Don't add dividers for segments adjacent to split (unless it's a hard divider)
if ((get(seg_next, 'name') ==# 'SPLIT' || get(seg_prev, 'name') ==# 'SPLIT') && div_type != s:HARD_DIVIDER)
return ''
endif
if a:side == s:LEFT_SIDE
" Left side
" Divider to the right
return printf('%%(%s%%#%s#%s%%)', a:text, s:HlCreate(div_colors), divider)
else
" Right side
" Divider to the left
return printf('%%(%%#%s#%s%s%%)', s:HlCreate(div_colors), divider, a:text)
endif
endfunction " }}}

View file

@ -1,188 +0,0 @@
let s:default_modes = ['n', 'N', 'v', 'i', 'r', 's']
function! s:CheckConditions(params) " {{{
" Check conditions for a segment/group
" Integer parameters are always conditions
for param in a:params
if type(param) == type(0) && param == 0
" Break here if it's an integer parameter and it's false (0)
return 0
endif
unlet! param
endfor
return 1
endfunction " }}}
function! Pl#Segment#Create(name, ...) " {{{
" Check condition parameters
if ! s:CheckConditions(a:000)
return {}
endif
let name = a:name
let modes = s:default_modes
let padding = 1
let segments = []
for param in a:000
" Lookup modes for this segment/group
if type(param) == type([]) && param[0] == 'modes'
let modes = param[1]
elseif type(param) == type([]) && param[0] == 'nopadding'
let padding = 0
elseif type(a:1) == type([]) && a:1[0] == 'segment'
call add(segments, param[1])
endif
unlet! param
endfor
if type(a:1) == type([]) && a:1[0] == 'segment'
" This is a segment group
return ['segment_group', {
\ 'type': 'segment_group'
\ , 'name': name
\ , 'segments': segments
\ , 'modes': modes
\ , 'padding': padding
\ }]
else
" This is a single segment
let text = a:1
" Search/replace symbols
for [key, symbol] in items(g:Pl#Parser#Symbols[g:Powerline_symbols].symbols)
let text = substitute(
\ text,
\ '\v\$('. key .')',
\ '\=Pl#Parser#ParseChars(g:Pl#Parser#Symbols[g:Powerline_symbols].symbols[submatch(1)])',
\ 'g')
unlet! key symbol
endfor
return ['segment', {
\ 'type': 'segment'
\ , 'name': name
\ , 'text': text
\ , 'modes': modes
\ , 'padding': padding
\ }]
endif
endfunction " }}}
function! Pl#Segment#Init(params) " {{{
" Check condition parameters
if ! s:CheckConditions(a:params)
return {}
endif
let segments = {}
let ns = ''
for param in a:params
if type(param) == type('')
" String parameters is the namespace
let ns = param
elseif type(param) == type([])
" The data dict is in param[1]
" By default we don't have a namespace for the segment
let segment = param[1]
if ! empty(ns)
" Update segment so that it includes the namespace
" Add the namespace to the segment dict key
let segment.ns = ns
let segment.name = join([segment.ns, segment.name], ':')
endif
let key = segment.name
let segments[key] = segment
endif
unlet! param
endfor
return segments
endfunction " }}}
function! Pl#Segment#Modes(modes) " {{{
" Handle modes for both segments and groups
let modes = split(a:modes, '\zs')
if modes[0] == '!'
" Filter modes (e.g. "!nr" will ignore the segment in normal and replace modes)
let modes = filter(deepcopy(s:default_modes), 'v:val !~# "['. join(modes[1:]) .']"')
endif
return ['modes', modes]
endfunction " }}}
function! Pl#Segment#NoPadding() " {{{
return ['nopadding']
endfunction " }}}
function! Pl#Segment#Split(...) " {{{
return a:0 ? a:1 .':SPLIT' : 'SPLIT'
endfunction " }}}
function! Pl#Segment#Truncate() " {{{
return 'TRUNCATE'
endfunction " }}}
function! Pl#Segment#Get(name) " {{{
" Return a segment data dict
let args = []
" Check for printf segments (lists)
if type(a:name) == type([])
" We're dealing with a segment with printf arguments
let seg_orig_name = a:name[0]
let args = a:name[1:]
else
let seg_orig_name = a:name
endif
" Fetch namespace and variants for storing in the segment dict
let seg_ns = ''
let seg_variants = []
" Retrieve color scheme variants
let seg_name_split = split(seg_orig_name, '\v\.')
if len(seg_name_split) > 1
let seg_variants = seg_name_split[1:]
endif
" Retrieve segment name and namespace
" Use the first piece of the split string, we can't have variants in the final segment name
let seg_name_split = split(seg_name_split[0], '\v:')
let seg_name = seg_name_split[0]
if len(seg_name_split) > 1
let seg_ns = seg_name_split[0]
let seg_name = seg_name_split[-1]
endif
try
" If we have a namespace, try to use the namespaced segment first (i.e. search for the segment in the namespaced file first)
let return_segment = deepcopy(g:Powerline#Segments#{seg_ns}#segments[seg_ns .':'. seg_name])
catch
try
" We didn't find a namespaced segment, fall back to common segments
let return_segment = deepcopy(g:Powerline#Segments#segments[seg_name])
catch
" Didn't find the segment among the common segments either, just skip it
return {}
endtry
endtry
if len(args) && has_key(return_segment, 'text')
" Handle segment printf arguments
" printf doesn't accept lists as its second argument, so we have to work around that
let return_segment.text = call('printf', [ return_segment.text ] + args)
endif
" Assign namespace, name and variants
let return_segment.ns = seg_ns
let return_segment.name = seg_name
let return_segment.orig_name = seg_orig_name
let return_segment.variants = seg_variants
return return_segment
endfunction " }}}

View file

@ -1,100 +0,0 @@
function! Pl#Theme#Create(...) " {{{
let buffer_segments = []
for buffer_segment in a:000
" Remove empty segments (e.g. 'Pl#Theme#Function's)
if empty(buffer_segment)
continue
endif
call add(buffer_segments, buffer_segment)
endfor
let buffer_segments = Pl#Colorscheme#Apply(g:Powerline_colorscheme, buffer_segments)
return buffer_segments
endfunction " }}}
function! Pl#Theme#Callback(name, expr) " {{{
return ['callback', a:name, a:expr]
endfunction " }}}
function! Pl#Theme#Buffer(ns, ...) " {{{
let segments = []
let ns = ! empty(a:ns) ? a:ns .':' : ''
" Match namespace parameter by default
let matches = Pl#Match#Any(a:ns)
let callback = []
let args = a:000
let args = Pl#Mod#ApplySegmentMods(args)
" Fetch segment data dicts
for item in args
if type(item) == type([])
if item[0] == 'match'
" Match item, overrides default namespace match
let matches = item
unlet! item
continue
elseif item[0] == 'callback'
" Store the item as a callback expression
let matches = ['match', 'none']
let callback = [a:ns, item[1], item[2]]
unlet! item
continue
endif
" printf segment, append ns to first item in list
let item[0] = ns . item[0]
else
let item = ns . item
endif
let segment = Pl#Segment#Get(item)
if ! empty(segment)
" Skip empty (possible disabled) segments
call add(segments, segment)
endif
unlet! item
endfor
return {
\ 'matches': matches
\ , 'callback': callback
\ , 'segments': segments
\ }
endfunction " }}}
function! Pl#Theme#InsertSegment(new_segment, where, target_segment) " {{{
" It's very important to NOT refer to the theme dict until everything's loaded!
"
" Because these functions are called from the vimrc, we need to put the
" actions in a list which will be parsed later.
"
" These functions don't accept a name parameter, because they work on the
" currently selected theme (will change any selected theme)
call Pl#Mod#AddSegmentMod('insert_segment', {
\ 'new_segment': a:new_segment,
\ 'where': a:where,
\ 'target_segment': a:target_segment
\ })
endfunction " }}}
function! Pl#Theme#RemoveSegment(target_segment) " {{{
" It's very important to NOT refer to the theme dict until everything's loaded!
"
" Because these functions are called from the vimrc, we need to put the
" actions in a list which will be parsed later.
"
" These functions don't accept a name parameter, because they work on the
" currently selected theme (will change any selected theme)
call Pl#Mod#AddSegmentMod('remove_segment', {
\ 'target_segment': a:target_segment
\ })
endfunction " }}}
function! Pl#Theme#ReplaceSegment(old_segment, new_segment) " {{{
call Pl#Theme#InsertSegment(a:new_segment, 'after', a:old_segment)
call Pl#Theme#RemoveSegment(a:old_segment)
endfunction " }}}

View file

@ -1,166 +0,0 @@
call Pl#Hi#Allocate({
\ 'black' : 16,
\ 'white' : 231,
\
\ 'darkestgreen' : 22,
\ 'darkgreen' : 28,
\ 'mediumgreen' : 70,
\ 'brightgreen' : 148,
\
\ 'darkestcyan' : 23,
\ 'mediumcyan' : 117,
\
\ 'darkestblue' : 24,
\ 'darkblue' : 31,
\
\ 'darkestred' : 52,
\ 'darkred' : 88,
\ 'mediumred' : 124,
\ 'brightred' : 160,
\ 'brightestred' : 196,
\
\ 'darkestpurple' : 55,
\ 'mediumpurple' : 98,
\ 'brightpurple' : 189,
\
\ 'brightorange' : 208,
\ 'brightestorange': 214,
\
\ 'gray0' : 233,
\ 'gray1' : 235,
\ 'gray2' : 236,
\ 'gray3' : 239,
\ 'gray4' : 240,
\ 'gray5' : 241,
\ 'gray6' : 244,
\ 'gray7' : 245,
\ 'gray8' : 247,
\ 'gray9' : 250,
\ 'gray10' : 252,
\ })
let g:Powerline#Colorschemes#default#colorscheme = Pl#Colorscheme#Init([
\ Pl#Hi#Segments(['SPLIT'], {
\ 'n': ['white', 'gray2'],
\ 'N': ['white', 'gray0'],
\ 'i': ['white', 'darkestblue'],
\ }),
\
\ Pl#Hi#Segments(['mode_indicator'], {
\ 'n': ['gray10', 'gray0', ['bold']],
\ 'i': ['darkestcyan', 'white', ['bold']],
\ 'v': ['white', 'darkestblue', ['bold']],
\ 'r': ['white', 'brightred', ['bold']],
\ 's': ['white', 'gray5', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['branch', 'scrollpercent', 'raw', 'filesize'], {
\ 'n': ['gray9', 'gray4'],
\ 'N': ['gray4', 'gray1'],
\ 'i': ['mediumcyan', 'darkblue'],
\ }),
\
\ Pl#Hi#Segments(['fileinfo', 'filename'], {
\ 'n': ['white', 'gray4', ['bold']],
\ 'N': ['gray7', 'gray0', ['bold']],
\ 'i': ['white', 'darkblue', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['fileinfo.filepath'], {
\ 'n': ['gray10'],
\ 'N': ['gray5'],
\ 'i': ['mediumcyan'],
\ }),
\
\ Pl#Hi#Segments(['static_str'], {
\ 'n': ['white', 'gray4'],
\ 'N': ['gray7', 'gray1'],
\ 'i': ['white', 'darkblue'],
\ }),
\
\ Pl#Hi#Segments(['fileinfo.flags'], {
\ 'n': ['brightestred', ['bold']],
\ 'N': ['darkred'],
\ 'i': ['brightestred', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['currenttag', 'fullcurrenttag', 'fileformat', 'fileencoding', 'pwd', 'filetype', 'rvm:string', 'rvm:statusline', 'virtualenv:statusline', 'charcode', 'currhigroup'], {
\ 'n': ['gray8', 'gray2'],
\ 'i': ['mediumcyan', 'darkestblue'],
\ }),
\
\ Pl#Hi#Segments(['lineinfo'], {
\ 'n': ['gray2', 'gray10', ['bold']],
\ 'N': ['gray7', 'gray1', ['bold']],
\ 'i': ['darkestcyan', 'mediumcyan', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['errors'], {
\ 'n': ['brightestorange', 'gray2', ['bold']],
\ 'i': ['brightestorange', 'darkestblue', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['lineinfo.line.tot'], {
\ 'n': ['gray6'],
\ 'N': ['gray5'],
\ 'i': ['darkestcyan'],
\ }),
\
\ Pl#Hi#Segments(['paste_indicator', 'ws_marker'], {
\ 'n': ['white', 'brightred', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['gundo:static_str.name', 'command_t:static_str.name'], {
\ 'n': ['white', 'mediumred', ['bold']],
\ 'N': ['brightred', 'darkestred', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['gundo:static_str.buffer', 'command_t:raw.line'], {
\ 'n': ['white', 'darkred'],
\ 'N': ['brightred', 'darkestred'],
\ }),
\
\ Pl#Hi#Segments(['gundo:SPLIT', 'command_t:SPLIT'], {
\ 'n': ['white', 'darkred'],
\ 'N': ['white', 'darkestred'],
\ }),
\
\ Pl#Hi#Segments(['lustyexplorer:static_str.name', 'minibufexplorer:static_str.name', 'nerdtree:raw.name', 'tagbar:static_str.name'], {
\ 'n': ['white', 'mediumgreen', ['bold']],
\ 'N': ['mediumgreen', 'darkestgreen', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['lustyexplorer:static_str.buffer', 'tagbar:static_str.buffer'], {
\ 'n': ['brightgreen', 'darkgreen'],
\ 'N': ['mediumgreen', 'darkestgreen'],
\ }),
\
\ Pl#Hi#Segments(['lustyexplorer:SPLIT', 'minibufexplorer:SPLIT', 'nerdtree:SPLIT', 'tagbar:SPLIT'], {
\ 'n': ['white', 'darkgreen'],
\ 'N': ['white', 'darkestgreen'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:focus', 'ctrlp:byfname'], {
\ 'n': ['brightpurple', 'darkestpurple'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:prev', 'ctrlp:next', 'ctrlp:pwd'], {
\ 'n': ['white', 'mediumpurple'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:item'], {
\ 'n': ['darkestpurple', 'white', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:marked'], {
\ 'n': ['brightestred', 'darkestpurple', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:count'], {
\ 'n': ['darkestpurple', 'white'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:SPLIT'], {
\ 'n': ['white', 'darkestpurple'],
\ }),
\ ])

View file

@ -1,192 +0,0 @@
" This theme is based on Solarized-dark colors, combined
" with Powerline native colors
call Pl#Hi#Allocate({
\ 'black' : 16,
\ 'white' : 231,
\
\ 'darkestgreen' : 22,
\ 'darkgreen' : 28,
\ 'mediumgreen' : 70,
\ 'brightgreen' : 148,
\
\ 'darkestcyan' : 23,
\ 'mediumcyan' : 117,
\
\ 'darkestblue' : 24,
\ 'darkblue' : 31,
\
\ 'darkestred' : 52,
\ 'darkred' : 88,
\ 'mediumred' : 124,
\ 'brightred' : 160,
\ 'brightestred' : 196,
\
\ 'darkestpurple' : 55,
\ 'mediumpurple' : 98,
\ 'brightpurple' : 189,
\
\ 'brightorange' : 208,
\ 'brightestorange': 214,
\
\ 'gray0' : 233,
\ 'gray1' : 235,
\ 'gray2' : 236,
\ 'gray3' : 239,
\ 'gray4' : 240,
\ 'gray5' : 241,
\ 'gray6' : 244,
\ 'gray7' : 245,
\ 'gray8' : 247,
\ 'gray9' : 250,
\ 'gray10' : 252,
\
\ 'base00' : [241, 0x657b83],
\ 'base01' : [240, 0x586e75],
\ 'base02' : [0, 0x073642],
\ 'base03' : [234, 0x002b36],
\ 'base0' : [244, 0x839496],
\ 'base1' : [245, 0x93a1a1],
\ 'base2' : [254, 0xeee8d5],
\ 'base3' : [230, 0xfdf6e3],
\ 'yellow' : [136, 0xb58900],
\ 'orange' : [166, 0xcb4b16],
\ 'red' : [160, 0xdc322f],
\ 'magenta' : [125, 0xd33682],
\ 'violet' : [61, 0x6c71c4],
\ 'blue' : [33, 0x268bd2],
\ 'cyan' : [37, 0x2aa198],
\ 'green' : [64, 0x859900],
\ })
let g:Powerline#Colorschemes#skwp#colorscheme = Pl#Colorscheme#Init([
\ Pl#Hi#Segments(['SPLIT'], {
\ 'n': ['white', 'base02'],
\ 'N': ['white', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['mode_indicator'], {
\ 'n': ['darkestgreen', 'brightgreen', ['bold']],
\ 'i': ['darkestcyan', 'white', ['bold']],
\ 'v': ['red', 'brightorange', ['bold']],
\ 'r': ['white', 'violet', ['bold']],
\ 's': ['white', 'gray5', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['branch', 'raw', 'filesize'], {
\ 'n': ['base03', 'blue'],
\ 'N': ['gray5', 'base03'],
\ }),
\
\ Pl#Hi#Segments(['scrollpercent'], {
\ 'n': ['gray7', 'gray2'],
\ 'N': ['base2', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['fileinfo', 'filename', 'filepath'], {
\ 'n': ['base2', 'darkestblue', ['bold']],
\ 'N': ['base1', 'base02', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['fileinfo.filepath'], {
\ 'n': ['gray10'],
\ 'N': ['gray5'],
\ 'i': ['mediumcyan'],
\ }),
\
\ Pl#Hi#Segments(['static_str'], {
\ 'n': ['base3', 'violet'],
\ 'N': ['base1', 'base02'],
\ 'i': ['white', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['fileinfo.flags'], {
\ 'n': ['base03', ['bold']],
\ 'N': ['gray5'],
\ 'i': ['base03', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['currenttag', 'fullcurrenttag', 'fileformat', 'fileencoding', 'pwd', 'filetype', 'rvm:string', 'rvm:statusline', 'virtualenv:statusline', 'charcode', 'currhigroup'], {
\ 'n': ['gray5', 'gray2'],
\ 'i': ['mediumcyan', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['lineinfo'], {
\ 'n': ['gray2', 'gray10', ['bold']],
\ 'N': ['gray7', 'gray1', ['bold']],
\ 'i': ['darkestcyan', 'mediumcyan', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['errors'], {
\ 'n': ['orange', 'base02', ['bold']],
\ 'N': ['gray5', 'base03', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['lineinfo.line.tot'], {
\ 'n': ['gray6'],
\ 'N': ['gray5'],
\ 'i': ['darkestcyan'],
\ }),
\
\ Pl#Hi#Segments(['paste_indicator', 'ws_marker'], {
\ 'n': ['base3', 'red', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['gundo:static_str.name', 'command_t:static_str.name'], {
\ 'n': ['base3', 'darkblue', ['bold']],
\ 'N': ['base1', 'base03', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['gundo:static_str.buffer', 'command_t:raw.line'], {
\ 'n': ['white', 'base02'],
\ 'N': ['gray5', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['gundo:SPLIT', 'command_t:SPLIT'], {
\ 'n': ['white', 'base02'],
\ 'N': ['white', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['lustyexplorer:static_str.name', 'minibufexplorer:static_str.name', 'nerdtree:raw.name', 'tagbar:static_str.name'], {
\ 'n': ['gray10', 'darkestblue', ['bold']],
\ 'N': ['gray3', 'base02', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['lustyexplorer:static_str.buffer', 'tagbar:static_str.buffer'], {
\ 'n': ['base3', 'blue'],
\ 'N': ['gray5', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['lustyexplorer:SPLIT', 'minibufexplorer:SPLIT', 'nerdtree:SPLIT', 'tagbar:SPLIT'], {
\ 'n': ['gray3', 'base02'],
\ 'N': ['gray3', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:focus', 'ctrlp:byfname'], {
\ 'n': ['green', 'base03'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:prev', 'ctrlp:next', 'ctrlp:pwd'], {
\ 'n': ['green', 'base02'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:item'], {
\ 'n': ['base2', 'darkestblue', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:marked'], {
\ 'n': ['brightgreen', 'base03', ['bold']],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:count'], {
\ 'n': ['base0', 'base03'],
\ }),
\
\ Pl#Hi#Segments(['ctrlp:SPLIT'], {
\ 'n': ['white', 'base03'],
\ }),
\
\ Pl#Hi#Segments(['status'], {
\ 'n': ['green', 'base02'],
\ 'N': ['gray5', 'base02'],
\ }),
\ ])

View file

@ -1,141 +0,0 @@
" Recalculate the trailing whitespace warning when idle, and after saving
autocmd CursorHold,BufWritePost,InsertLeave * unlet! b:statusline_trailing_space_warning
function! Powerline#Functions#GetFilepath() " {{{
" Recalculate the filepath when cwd changes.
let cwd = getcwd()
if exists("b:Powerline_cwd") && cwd != b:Powerline_cwd
unlet! b:Powerline_filepath
endif
let b:Powerline_cwd = cwd
if exists('b:Powerline_filepath')
return b:Powerline_filepath
endif
let dirsep = has('win32') && ! &shellslash ? '\' : '/'
let filepath = expand('%:p')
if empty(filepath)
return ''
endif
let ret = ''
if g:Powerline_stl_path_style == 'short'
" Display a short path where the first directory is displayed with its
" full name, and the subsequent directories are shortened to their
" first letter, i.e. "/home/user/foo/foo/bar/baz.vim" becomes
" "~/foo/f/b/baz.vim"
"
" This displays the shortest possible path, relative to ~ or the
" current directory.
let mod = (exists('+acd') && &acd) ? ':~:h' : ':~:.:h'
let fpath = split(fnamemodify(filepath, mod), dirsep)
let fpath_shortparts = map(fpath[1:], 'v:val[0]')
let ret = join(extend([fpath[0]], fpath_shortparts), dirsep) . dirsep
elseif g:Powerline_stl_path_style == 'relative'
" Display a relative path, similar to the %f statusline item
let ret = fnamemodify(filepath, ':~:.:h') . dirsep
elseif g:Powerline_stl_path_style == 'full'
" Display the full path, similar to the %F statusline item
let ret = fnamemodify(filepath, ':h') . dirsep
endif
if ret == ('.' . dirsep)
let ret = ''
endif
let b:Powerline_filepath = ret
return ret
endfunction " }}}
function! Powerline#Functions#GetShortPath(threshold) " {{{
let fullpath = split(substitute(expand('%:p:h'), $HOME, '~', 'g'), '/')
if len(fullpath) > a:threshold
let fullpath = [fullpath[0], '…'] + fullpath[-a:threshold + 1 :]
endif
return join(fullpath, '/')
endfunction " }}}
function! Powerline#Functions#GetMode() " {{{
let mode = mode()
if mode ==# 'v'
let mode = get(g:, "Powerline_mode_v", "VISUAL")
elseif mode ==# 'V'
let mode = get(g:, "Powerline_mode_V", "V⋅LINE")
elseif mode ==# ''
let mode = get(g:, "Powerline_mode_cv", "V⋅BLOCK")
elseif mode ==# 's'
let mode = get(g:, "Powerline_mode_s", "SELECT")
elseif mode ==# 'S'
let mode = get(g:, "Powerline_mode_S", "S⋅LINE")
elseif mode ==# ''
let mode = get(g:, "Powerline_mode_cs", "S⋅BLOCK")
elseif mode =~# '\vi'
let mode = get(g:, "Powerline_mode_i", "INSERT")
elseif mode =~# '\v(R|Rv)'
let mode = get(g:, "Powerline_mode_R", "REPLACE")
else
" Fallback to normal mode
let mode = get(g:, "Powerline_mode_n", "NORMAL")
endif
return mode
endfunction " }}}
function! Powerline#Functions#GetFilesize() " {{{
let bytes = getfsize(expand("%:p"))
if bytes <= 0
return ''
endif
if bytes < 1024
return bytes . 'B'
else
return (bytes / 1024) . 'kB'
endif
endfunction "}}}
function! Powerline#Functions#GetCharCode() " {{{
" Get the output of :ascii
redir => ascii
silent! ascii
redir END
if match(ascii, 'NUL') != -1
return 'NUL'
endif
" Zero pad hex values
let nrformat = '0x%02x'
let encoding = (&fenc == '' ? &enc : &fenc)
if encoding == 'utf-8'
" Zero pad with 4 zeroes in unicode files
let nrformat = '0x%04x'
endif
" Get the character and the numeric value from the return value of :ascii
" This matches the two first pieces of the return value, e.g.
" "<F> 70" => char: 'F', nr: '70'
let [str, char, nr; rest] = matchlist(ascii, '\v\<(.{-1,})\>\s*([0-9]+)')
" Format the numeric value
let nr = printf(nrformat, nr)
return "'". char ."' ". nr
endfunction "}}}
function! Powerline#Functions#GetWSMarker() " {{{
" Return '...' if trailing white space is detected
" Return '' otherwise
if ! exists("b:statusline_trailing_space_warning")
if search('\s$', 'nw') != 0
let b:statusline_trailing_space_warning = ' … '
else
let b:statusline_trailing_space_warning = ''
endif
endif
return b:statusline_trailing_space_warning
endfunction " }}}

View file

@ -1,12 +0,0 @@
function! Powerline#Functions#ft_man#GetName() " {{{
let matches = matchlist(getline(1), '\v^([a-zA-Z_\.\-]+)\((\d+)\)')
if ! len(matches)
return 'n/a'
endif
let file = tolower(matches[1])
let num = matches[2]
return file
endfunction " }}}

View file

@ -1,7 +0,0 @@
function! Powerline#Functions#fugitive#GetBranch(symbol) " {{{
let ret = fugitive#statusline()
let ret = substitute(ret, '\c\v\[?GIT\(([a-z0-9\-_\./:]+)\)\]?', a:symbol .' \1', 'g')
return ret
endfunction " }}}

View file

@ -1,17 +0,0 @@
function! Powerline#Functions#hgrev#Status(symbol) " {{{
if ! exists('*HGRev')
" HGRev hasn't been loaded yet
return ''
endif
if !exists("b:statusline_hg_status")
silent execute "RefreshMercurialRev"
endif
let b:statusline_hg_status=HGRev()
if b:statusline_hg_status != '-'
let ret = "\u26A1". '' . substitute(b:statusline_hg_status, '^[^ ]*', '\1', 'g')
let ret=substitute(ret,' M$','+','g')
else
let ret=''
endif
return ret
endfunction " }}}

View file

@ -1,16 +0,0 @@
function! Powerline#Functions#syntastic#GetErrors(line_symbol) " {{{
if ! exists('g:syntastic_stl_format')
" Syntastic hasn't been loaded yet
return ''
endif
" Temporarily change syntastic output format
let old_stl_format = g:syntastic_stl_format
let g:syntastic_stl_format = '%E{ ERRORS (%e) '. a:line_symbol .' %fe }%W{ WARNINGS (%w) '. a:line_symbol .' %fw }'
let ret = SyntasticStatuslineFlag()
let g:syntastic_stl_format = old_stl_format
return ret
endfunction " }}}

View file

@ -1,13 +0,0 @@
let g:Powerline#Matches#matches = {
\ 'command_t' : Pl#Match#Add('bufname("%")', 'GoToFile'),
\ 'bt_help' : Pl#Match#Add('&bt' , 'help'),
\ 'ft_man' : Pl#Match#Add('&ft' , 'man'),
\ 'ft_qf' : Pl#Match#Add('&ft' , 'qf'),
\ 'ft_vimpager' : Pl#Match#Add('&ft' , 'vimpager'),
\ 'gundo_preview' : Pl#Match#Add('bufname("%")', '__Gundo_Preview__'),
\ 'gundo_tree' : Pl#Match#Add('bufname("%")', '__Gundo__'),
\ 'lustyexplorer' : Pl#Match#Add('bufname("%")', '\[LustyExplorer-Buffers\]'),
\ 'minibufexplorer' : Pl#Match#Add('bufname("%")', '\-MiniBufExplorer\-'),
\ 'tagbar' : Pl#Match#Add('&ft' , 'tagbar'),
\ 'nerdtree' : Pl#Match#Add('&ft' , 'nerdtree'),
\ }

View file

@ -1,30 +0,0 @@
let g:Powerline#Segments#segments = Pl#Segment#Init([
\ Pl#Segment#Create('SPLIT' , '__split__'),
\ Pl#Segment#Create('TRUNCATE', '__truncate__'),
\
\ Pl#Segment#Create('paste_indicator' , '%{&paste ? "PASTE" : ""}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('mode_indicator' , '%{Powerline#Functions#GetMode()}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('fileinfo',
\ Pl#Segment#Create('flags.ro' , '%{&readonly ? "$RO" : ""}'),
\ Pl#Segment#Create('filepath' , '%{Powerline#Functions#GetFilepath()}', Pl#Segment#NoPadding()),
\ Pl#Segment#Create('filename' , '%t'),
\ Pl#Segment#Create('flags.mod' , '%M'),
\ Pl#Segment#Create('flags.type' , '%H%W'),
\ ),
\ Pl#Segment#Create('filename' , '%t'),
\ Pl#Segment#Create('filesize' , '%{Powerline#Functions#GetFilesize()}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('pwd' , '%{substitute(getcwd(), expand("$HOME"), "~", "g")}'),
\ Pl#Segment#Create('static_str' , '%%{"%s"}'),
\ Pl#Segment#Create('raw' , '%s'),
\ Pl#Segment#Create('fileformat' , '%{&fileformat}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('fileencoding' , '%{(&fenc == "" ? &enc : &fenc)}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('filetype' , '%{strlen(&ft) ? &ft : "no ft"}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('scrollpercent' , '%3p%%'),
\ Pl#Segment#Create('lineinfo',
\ Pl#Segment#Create('line.cur' , '$LINE %3l'),
\ Pl#Segment#Create('line.tot' , ':%-2v', Pl#Segment#NoPadding()),
\ ),
\ Pl#Segment#Create('charcode' , '%{Powerline#Functions#GetCharCode()}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('currhigroup' , '%{synIDattr(synID(line("."), col("."), 1), "name")}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('ws_marker' , '%{Powerline#Functions#GetWSMarker()}', Pl#Segment#Modes('!N')),
\ ])

View file

@ -1,20 +0,0 @@
if !exists("g:Powerline#Segments#ctrlp#segments#focus ")
let g:Powerline#Segments#ctrlp#segments#focus = '%{"%0"}'
endif
if !exists("g:Powerline#Segments#ctrlp#segments#prev ")
let g:Powerline#Segments#ctrlp#segments#prev = '%-3{"%3"}'
endif
if !exists("g:Powerline#Segments#ctrlp#segments#next ")
let g:Powerline#Segments#ctrlp#segments#next = '%-3{"%5"}'
endif
let g:Powerline#Segments#ctrlp#segments = Pl#Segment#Init(['ctrlp'
\ , Pl#Segment#Create('focus', g:Powerline#Segments#ctrlp#segments#focus)
\ , Pl#Segment#Create('byfname', '%{"%1"}')
\ , Pl#Segment#Create('prev', g:Powerline#Segments#ctrlp#segments#prev)
\ , Pl#Segment#Create('item', '%-9{"%4"}')
\ , Pl#Segment#Create('next', g:Powerline#Segments#ctrlp#segments#next)
\ , Pl#Segment#Create('marked', '%{"%6" == " <+>" ? "" : strpart("%6", 2, len("%6") - 3)}')
\
\ , Pl#Segment#Create('count', '%-6{"%0"}')
\ ])

View file

@ -1,3 +0,0 @@
let g:Powerline#Segments#ft_man#segments = Pl#Segment#Init(['ft_man',
\ Pl#Segment#Create('filename', '%{Powerline#Functions#ft_man#GetName()}')
\ ])

View file

@ -1,5 +0,0 @@
let g:Powerline#Segments#fugitive#segments = Pl#Segment#Init(['fugitive',
\ (exists('g:loaded_fugitive') && g:loaded_fugitive == 1),
\
\ Pl#Segment#Create('branch', '%{Powerline#Functions#fugitive#GetBranch("$BRANCH")}')
\ ])

View file

@ -1,4 +0,0 @@
let g:Powerline#Segments#hgrev#segments = Pl#Segment#Init(['hgrev',
\ (exists('hgrev_loaded')),
\ Pl#Segment#Create('branch', '%{Powerline#Functions#hgrev#Status("$BRANCH")}')
\ ])

View file

@ -1,6 +0,0 @@
let g:Powerline#Segments#rvm#segments = Pl#Segment#Init(['rvm',
\ (exists('g:loaded_rvm') && g:loaded_rvm == 1),
\
\ Pl#Segment#Create('string', '%{rvm#string()}'),
\ Pl#Segment#Create('statusline', '%{rvm#statusline()}')
\ ])

View file

@ -1,5 +0,0 @@
let g:Powerline#Segments#syntastic#segments = Pl#Segment#Init(['syntastic',
\ (exists('g:loaded_syntastic_plugin') && g:loaded_syntastic_plugin == 1),
\
\ Pl#Segment#Create('errors', '%{Powerline#Functions#syntastic#GetErrors("$LINE")}', Pl#Segment#Modes('!N'))
\ ])

View file

@ -1,6 +0,0 @@
let g:Powerline#Segments#tagbar#segments = Pl#Segment#Init(['tagbar',
\ (exists(':Tagbar') > 0),
\
\ Pl#Segment#Create('currenttag', '%{tagbar#currenttag("%s", "")}', Pl#Segment#Modes('!N')),
\ Pl#Segment#Create('fullcurrenttag', '%{tagbar#currenttag("%s", "", "f")}', Pl#Segment#Modes('!N'))
\ ])

View file

@ -1,5 +0,0 @@
let g:Powerline#Segments#virtualenv#segments = Pl#Segment#Init(['virtualenv',
\ has('python') && (exists('g:virtualenv_loaded') && g:virtualenv_loaded == 1),
\
\ Pl#Segment#Create('statusline', '%{virtualenv#statusline()}')
\ ])

View file

@ -1,116 +0,0 @@
let g:Powerline#Themes#default#theme = Pl#Theme#Create(
\ Pl#Theme#Buffer(''
\ , 'paste_indicator'
\ , 'mode_indicator'
\ , 'fugitive:branch'
\ , 'hgrev:branch'
\ , 'fileinfo'
\ , 'syntastic:errors'
\ , Pl#Segment#Truncate()
\ , 'tagbar:currenttag'
\ , Pl#Segment#Split()
\ , 'rvm:string'
\ , 'virtualenv:statusline'
\ , 'fileformat'
\ , 'fileencoding'
\ , 'filetype'
\ , 'scrollpercent'
\ , 'lineinfo'
\ ),
\
\ Pl#Theme#Buffer('command_t'
\ , ['static_str.name', 'Command-T']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , ['raw.line', '%10(Match #%l%)']
\ ),
\
\ Pl#Theme#Buffer('gundo', Pl#Match#Any('gundo_tree')
\ , ['static_str.name', 'Gundo']
\ , ['static_str.buffer', 'Undo tree']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('gundo', Pl#Match#Any('gundo_preview')
\ , ['static_str.name', 'Gundo']
\ , ['static_str.buffer', 'Diff preview']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('bt_help'
\ , ['static_str.name', 'Help']
\ , 'filename'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'scrollpercent'
\ ),
\
\ Pl#Theme#Buffer('ft_vimpager'
\ , ['static_str.name', 'Pager']
\ , 'filename'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'scrollpercent'
\ ),
\
\ Pl#Theme#Buffer('lustyexplorer'
\ , ['static_str.name', 'LustyExplorer']
\ , ['static_str.buffer', 'Buffer list']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('ft_man'
\ , ['static_str.name', 'Man page']
\ , 'filename'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'scrollpercent'
\ ),
\
\ Pl#Theme#Buffer('minibufexplorer'
\ , ['static_str.name', 'MiniBufExplorer']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('ft_qf'
\ , ['static_str.name', 'Quickfix']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('tagbar'
\ , ['static_str.name', 'Tagbar']
\ , ['static_str.buffer', 'Tree']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('ctrlp', Pl#Theme#Callback('ctrlp_main', 'if ! exists("g:ctrlp_status_func") | let g:ctrlp_status_func = {} | endif | let g:ctrlp_status_func.main = "%s"')
\ , 'ctrlp:prev'
\ , 'ctrlp:item'
\ , 'ctrlp:next'
\ , 'ctrlp:marked'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'ctrlp:focus'
\ , 'ctrlp:byfname'
\ , 'pwd'
\ ),
\
\ Pl#Theme#Buffer('ctrlp', Pl#Theme#Callback('ctrlp_prog', 'if ! exists("g:ctrlp_status_func") | let g:ctrlp_status_func = {} | endif | let g:ctrlp_status_func.prog = "%s"')
\ , 'ctrlp:count'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'pwd'
\ ),
\
\ Pl#Theme#Buffer('nerdtree'
\ , ['raw.name', '%{Powerline#Functions#GetShortPath(4)}']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ )
\ )

View file

@ -1,116 +0,0 @@
" Disabled:
" Add the following line into the first theme group to see the highlight
" group
" \ , 'currhigroup'
"
" Line info taken out - I know which line number I'm on from the gutter
"\ , 'lineinfo'
let g:Powerline#Themes#skwp#theme = Pl#Theme#Create(
\ Pl#Theme#Buffer(''
\ , 'fugitive:branch'
\ , 'fileinfo'
\ , 'flags.mod'
\ , 'syntastic:errors'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'sass:status'
\ , 'rvm:string'
\ , 'paste_indicator'
\ ),
\
\ Pl#Theme#Buffer('command_t'
\ , ['static_str.name', 'Command-T']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , ['raw.line', '%10(Match #%l%)']
\ ),
\
\ Pl#Theme#Buffer('gundo', Pl#Match#Any('gundo_tree')
\ , ['static_str.name', 'Gundo']
\ , ['static_str.buffer', 'Undo tree']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('gundo', Pl#Match#Any('gundo_preview')
\ , ['static_str.name', 'Gundo']
\ , ['static_str.buffer', 'Diff preview']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('bt_help'
\ , ['static_str.name', 'Help']
\ , 'filename'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'scrollpercent'
\ ),
\
\ Pl#Theme#Buffer('ft_vimpager'
\ , ['static_str.name', 'Pager']
\ , 'filename'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'scrollpercent'
\ ),
\
\ Pl#Theme#Buffer('lustyexplorer'
\ , ['static_str.name', 'LustyExplorer']
\ , ['static_str.buffer', 'Buffer list']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('ft_man'
\ , ['static_str.name', 'Man page']
\ , 'filename'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'scrollpercent'
\ ),
\
\ Pl#Theme#Buffer('minibufexplorer'
\ , ['static_str.name', 'MiniBufExplorer']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('ft_qf'
\ , ['static_str.name', 'Quickfix']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('tagbar'
\ , ['static_str.name', 'Tagbar']
\ , ['static_str.buffer', 'Tree']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ ),
\
\ Pl#Theme#Buffer('ctrlp', Pl#Theme#Callback('ctrlp_main', 'if ! exists("g:ctrlp_status_func") | let g:ctrlp_status_func = {} | endif | let g:ctrlp_status_func.main = "%s"')
\ , 'ctrlp:prev'
\ , 'ctrlp:item'
\ , 'ctrlp:next'
\ , 'ctrlp:marked'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'ctrlp:focus'
\ , 'ctrlp:byfname'
\ , 'pwd'
\ ),
\
\ Pl#Theme#Buffer('ctrlp', Pl#Theme#Callback('ctrlp_prog', 'if ! exists("g:ctrlp_status_func") | let g:ctrlp_status_func = {} | endif | let g:ctrlp_status_func.prog = "%s"')
\ , 'ctrlp:count'
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ , 'pwd'
\ ),
\
\ Pl#Theme#Buffer('nerdtree'
\ , ['raw.name', '%{Powerline#Functions#GetShortPath(4)}']
\ , Pl#Segment#Truncate()
\ , Pl#Segment#Split()
\ )
\ )

View file

@ -1,429 +0,0 @@
*Powerline.txt* For Vim version 7.3. Last change: 2011 Nov 23
______
_________ \ /__
\_____ \______ _ _____________ / /'__' ___ ____
| ___/ _ \ \/ \/ / __ \_ ___\ / | |/ \_/ __ \
| | | (_) \ _ / ___/| | / /__| | | \ ___/
'___' \____/ \/ \/ \___ |__' /___ /'__'__| /\___ \
\/ / / \/ \/
| /
|/
'
==============================================================================
CONTENTS *Powerline-contents*
1. Introduction ....................... |Powerline-introduction|
2. Usage .............................. |Powerline-usage|
3. Requirements ....................... |Powerline-requirements|
3.1 Recommended settings ........... |Powerline-recommended-settings|
4. Configuration ...................... |Powerline-configuration|
4.1 Powerline_cache_file ........... |Powerline_cache_file|
4.1.1 Clearing the cache ....... |:PowerlineClearCache|
4.2 Powerline_cache_enabled ........ |Powerline_cache_enabled|
4.3 Powerline_symbols .............. |Powerline_symbols|
4.3.1 Compatible symbols ....... |Powerline-symbols-compatible|
4.3.2 Fancy symbols ............ |Powerline-symbols-fancy|
4.3.3 Overriding symbols ....... |Powerline_symbols_override|
4.3.4 Overriding dividers ...... |Powerline_dividers_override|
4.4 Powerline_theme ................ |Powerline_theme|
4.5 Powerline_colorscheme .......... |Powerline_colorscheme|
4.6 Powerline_stl_path_style ....... |Powerline_stl_path_style|
5. Fonts .............................. |Powerline-fonts|
6. Customization ...................... |Powerline-customization|
6.1 Basic customization ............ |Powerline-basic-customization|
6.2 Advanced customization ......... |Powerline-advanced-customization|
6.2.1 Colorschemes ............. |Powerline-cust-colorschemes|
6.2.2 Functions ................ |Powerline-cust-functions|
6.2.3 Segments ................. |Powerline-cust-segments|
6.2.4 Themes ................... |Powerline-cust-themes|
7. License ............................ |Powerline-license|
8. Known issues ....................... |Powerline-known-issues|
9. Contributing ....................... |Powerline-contributing|
==============================================================================
1. Introduction *Powerline* *Powerline-introduction*
Powerline is a utility plugin which allows you to create better-looking, more
functional Vim statuslines.
==============================================================================
2. Usage *Powerline-usage*
Powerline is automatically enabled when it's installed, either by unzipping
the provided archive or by adding it as a Pathogen/Vundle bundle.
Powerline replaces the standard Vim 'statusline' with a custom statusline made
up of Powerline segments.
Powerline ignores any 'statusline' customizations you have defined in your
|vimrc|. If you remove Powerline, your 'statusline' customizations are
restored.
==============================================================================
3. Requirements *Powerline-requirements*
Powerline has been developed and tested in Vim 7.3, but it should run without
any problems in Vim 7.2. The default configuration requires a Unix-like system
to work properly.
The plugin only works with Vim running in an 88/256-color terminal or Gvim.
Vi-compatible mode must be disabled.
------------------------------------------------------------------------------
3.1 Recommended settings *Powerline-recommended-settings*
The following configuration options should be set in your |vimrc|: >
set nocompatible " Disable vi-compatibility
set laststatus=2 " Always show the statusline
set encoding=utf-8 " Necessary to show Unicode glyphs
Note: If you're using an 88/256-color terminal but still don't see the colored
statusline, you may have to set the following option as well: >
set t_Co=256 " Explicitly tell Vim that the terminal supports 256 colors
==============================================================================
4. Configuration *Powerline-configuration*
Powerline will work fine without any user configuration, but default behavior
can be overridden by setting configuration variables globally in your |vimrc|
file.
------------------------------------------------------------------------------
4.1 Powerline_cache_file *Powerline_cache_file*
By default Powerline caches all the statuslines and colors in a cache file in
the plugin's directory (or the Vim directory, depending on the installation
method used).
It's recommended that you enable the cache, as this dramatically improves Vim
startup time after the cache file has been generated (the plugin usually loads
within ~100ms without the cache and ~1ms with the cache).
Note: The default cache filename includes the current theme, colorscheme and
symbol settings in order to tie the cache file to your current configuration,
so the cache file will be regenerated when you change any settings. This may
leave several old cache files in your Vim folder, and these may safely be
deleted.
Defaults: "<plugin_directory>/Powerline_<theme>_<colorscheme>_<symbols>.cache"
------------------------------------------------------------------------------
4.1.1 Clearing the cache *:PowerlineClearCache*
Powerline provides a command to easily clear the cache after changing your
settings or updating your theme. Simply run the following command to clear
your cache, and restart Vim afterwards: >
:PowerlineClearCache
<
------------------------------------------------------------------------------
4.2 Powerline_cache_enabled *Powerline_cache_enabled*
It's possible to disable statusline caching by setting this option to 0. This
is mostly useful when developing statuslines.
Example: >
let g:Powerline_cache_enabled = 0
<
Default: 1
------------------------------------------------------------------------------
4.3 Powerline_symbols *Powerline_symbols*
This option defines which set of symbols and dividers you want to use. There
are currently three available options: "compatible", "unicode" and "fancy".
TYPE DESCRIPTION ~
compatible Doesn't use any special characters.
unicode Simulates icons and arrows using similar Unicode glyphs.
fancy Custom icons and arrows. Requires a patched font.
Example: >
let g:Powerline_symbols = 'fancy'
<
Default: "compatible"
Symbols can be inserted into statuslines by using the following variables
(just insert the variables as text in your segments):
VARIABLE DESCRIPTION ~
$BRANCH Inserts a branch symbol
$RO Inserts a read-only symbol
$FT Inserts a filetype symbol
$LINE Inserts a line number symbol
------------------------------------------------------------------------------
4.3.1 Compatible symbols *Powerline-symbols-compatible*
These symbols will work in any configuration, and do not require a special
font to work. This option will replace the fancy icons with plain text, and
the pointy dividers with straight lines.
------------------------------------------------------------------------------
4.3.2 Fancy symbols *Powerline-symbols-fancy*
These symbols require a custom font to work. A font patcher is provided for
adding the required symbols to any outline font and some bitmap fonts, see
|Powerline-fonts| and the provided README file for usage details.
------------------------------------------------------------------------------
4.3.3 Overriding symbols *Powerline_symbols_override*
You can override symbols by adding your symbols to the
g:Powerline_symbols_override dictionary. Example: If you want the branch
symbol to be "∓" (hex code 0x2213) and the line symbol to be "L" you can add
the following to your |vimrc|: >
let g:Powerline_symbols_override = {
\ 'BRANCH': [0x2213],
\ 'LINE': 'L',
\ }
<
------------------------------------------------------------------------------
4.3.4 Overriding dividers *Powerline_dividers_override*
If you for some reason want to override the dividers then you can set
g:Powerline_dividers_override to a list with exactly four elements:
1: Hard right-pointing arrow
2: Soft right-pointing arrow
3: Hard left-pointing arrow
4: Soft left-pointing arrow
Example: >
let g:Powerline_dividers_override = ['>>', '>', '<<', '<']
<
------------------------------------------------------------------------------
4.3.5 Overriding mode names *Powerline_mode*
You can change the names used for modes at the far left by setting some
variables in your |vimrc|. For example you can change "N" to "NORMAL" with: >
let g:Powerline_mode_n = 'NORMAL'
<
The variables are all named beginning with 'g:Powerline_mode_', as follows:
mode name default note ~
Normal n ' N ' (surrounded by spaces)
Insert i INSERT
Replace R REPLACE |Replace-mode|
Visual v VISUAL |Visual-mode|
Visual linewise V V⋅LINE
Visual blockwise cv V⋅BLOCK
Select s SELECT |Select-mode|
Select linewise S S⋅LINE
Select blockwise cs S⋅BLOCK
-----------------------------------------------------------------------------
4.4 Powerline_theme *Powerline_theme*
This option defines the theme Powerline uses. The available themes are located
in autoload/Powerline/Themes/. A theme is a pre-defined set of Powerline
segments which make up the statusline.
Example: >
let g:Powerline_theme = 'skwp'
<
Default: "default"
------------------------------------------------------------------------------
4.5 Powerline_colorscheme *Powerline_colorscheme*
This option defines the colorscheme Powerline uses. The available colorschemes
are located in autoload/Powerline/Colorschemes/.
Example: >
let g:Powerline_colorscheme = 'skwp'
<
Default: "default"
------------------------------------------------------------------------------
4.6 Powerline_stl_path_style *Powerline_stl_path_style*
There are currently four ways to display the current path and file name. The
default is to only display the file name like the %t statusline item. By
setting this configuration value you can choose from the following ways
display the current path and file name:
VALUE DESCRIPTION ~
filename Display only the file name using the %t statusline item.
short Display a short path. The home directory is substituted with
"~", the first directory is displayed with its full name, and
subsequent directories are shortened to their first letter.
I.e. "/home/user/foo/bar/baz.vim" becomes "~/f/b/baz.vim" and
"long/relative/path/foo/bar/baz.vim becomes
"long/r/p/f/b/baz.vim".
relative Display a relative path, similar to the %f statusline item.
full Display the full path, similar to the %F statusline item.
Example: >
let g:Powerline_stl_path_style = 'full'
<
Default: "relative"
==============================================================================
5. Fonts *Powerline-fonts*
TODO
==============================================================================
6. Customization *Powerline-customization*
There are currently two ways of customizing Powerline: Basic customization
using a couple of functions to insert and remove existing segments from the
statusline, and advanced customization using your own autoload files. The
customization features of Powerline allow you to create your own statuslines
without ever touching the original source code.
------------------------------------------------------------------------------
6.1 Basic customization *Powerline-basic-customization*
Powerline provides the following functions to alter the default statusline
look. These functions should be called from your |vimrc| file or another file
which is sourced at Vim startup.
Note: These functions are currently applied to all statuslines, so if you
insert a segment after a segment which is present in many statuslines (e.g.
the "filename" segment), all the statuslines will have the inserted segment.
This behavior may be changed in a future version of Powerline.
Note: Remember to clear your cache with |:PowerlineClearCache| after changing
your statusline!
Example: >
" Insert the charcode segment after the filetype segment
call Pl#Theme#InsertSegment('charcode', 'after', 'filetype')
" Replace the scrollpercent segment with the charcode segment
call Pl#Theme#ReplaceSegment('scrollpercent', 'fileinfo')
<
*Pl#Theme#InsertSegment*
Pl#Theme#InsertSegment({newsegment}, {location}, {targetsegment})
This function inserts {newsegment} before or after {targetsegment}. The
{location} parameter specifies the location of the new segment, valid values
are "before" and "after". You can see all the available segments in
autoload/Powerline/Segments.vim and the files specified in
|Powerline-cust-segments|.
Pl#Theme#RemoveSegment({targetsegment}) *Pl#Theme#RemoveSegment*
This function removes the {targetsegment} segment entirely.
Pl#Theme#ReplaceSegment({oldsegment}, {newsegment}) *Pl#Theme#ReplaceSegment*
This function replaces {oldsegment} with {newsegment}.
------------------------------------------------------------------------------
6.2 Advanced customization *Powerline-advanced-customization*
Because Powerline utilizes Vim's autoload functionality, you can easily create
your own segments, themes, functions and colorschemes without touching the
original source code. This is a bit more complex than using the utility
functions, but it allows you to do a lot more with your statusline.
Your custom autoload files should be stored in your |runtimepath| (usually in
"~/.vim/autoload/Powerline/*").
Note: Remember to clear your cache with |:PowerlineClearCache| after changing
your statusline!
6.2.1 Colorschemes *Powerline-cust-colorschemes*
------------------------------------------------------------------------------
Colorschemes should be stored as separate files in
{runtimepath}/autoload/Powerline/Colorschemes/.
SYNTAX ~
TODO
EXAMPLE ~
TODO
6.2.2 Functions *Powerline-cust-functions*
------------------------------------------------------------------------------
Functions should be stored as separate files in
{runtimepath}/autoload/Powerline/Functions/.
SYNTAX ~
TODO
EXAMPLE ~
TODO
6.2.3 Segments *Powerline-cust-segments*
------------------------------------------------------------------------------
Segments should be stored as separate files in
{runtimepath}/autoload/Powerline/Segments/.
SYNTAX ~
TODO
EXAMPLE ~
TODO
6.2.4 Themes *Powerline-cust-themes*
------------------------------------------------------------------------------
Themes should be stored as separate files in
{runtimepath}/autoload/Powerline/Themes/.
SYNTAX ~
TODO
EXAMPLE ~
TODO
==============================================================================
7. License *Powerline-license*
Creative Commons Attribution-ShareAlike 3.0 Unported
http://creativecommons.org/licenses/by-sa/3.0/
==============================================================================
8. Known issues *Powerline-known-issues*
See the issue tracker at
https://github.com/Lokaltog/vim-powerline/issues
==============================================================================
9. Contributing *Powerline-contributing*
If you experience any bugs or have feature requests, please open an issue on
GitHub. Fork the source repository on GitHub and send a pull request if you
have any code improvements.
Author: Kim Silkebækken <kim.silkebaekken+vim@gmail.com>
Source repository: https://github.com/Lokaltog/vim-powerline
==============================================================================
vim:tw=78:sw=4:ts=8:ft=help:norl:

View file

@ -1,34 +0,0 @@
:PowerlineClearCache Powerline.txt /*:PowerlineClearCache*
Pl#Theme#InsertSegment Powerline.txt /*Pl#Theme#InsertSegment*
Pl#Theme#RemoveSegment Powerline.txt /*Pl#Theme#RemoveSegment*
Pl#Theme#ReplaceSegment Powerline.txt /*Pl#Theme#ReplaceSegment*
Powerline Powerline.txt /*Powerline*
Powerline-advanced-customization Powerline.txt /*Powerline-advanced-customization*
Powerline-basic-customization Powerline.txt /*Powerline-basic-customization*
Powerline-configuration Powerline.txt /*Powerline-configuration*
Powerline-contents Powerline.txt /*Powerline-contents*
Powerline-contributing Powerline.txt /*Powerline-contributing*
Powerline-cust-colorschemes Powerline.txt /*Powerline-cust-colorschemes*
Powerline-cust-functions Powerline.txt /*Powerline-cust-functions*
Powerline-cust-segments Powerline.txt /*Powerline-cust-segments*
Powerline-cust-themes Powerline.txt /*Powerline-cust-themes*
Powerline-customization Powerline.txt /*Powerline-customization*
Powerline-fonts Powerline.txt /*Powerline-fonts*
Powerline-introduction Powerline.txt /*Powerline-introduction*
Powerline-known-issues Powerline.txt /*Powerline-known-issues*
Powerline-license Powerline.txt /*Powerline-license*
Powerline-recommended-settings Powerline.txt /*Powerline-recommended-settings*
Powerline-requirements Powerline.txt /*Powerline-requirements*
Powerline-symbols-compatible Powerline.txt /*Powerline-symbols-compatible*
Powerline-symbols-fancy Powerline.txt /*Powerline-symbols-fancy*
Powerline-usage Powerline.txt /*Powerline-usage*
Powerline.txt Powerline.txt /*Powerline.txt*
Powerline_cache_enabled Powerline.txt /*Powerline_cache_enabled*
Powerline_cache_file Powerline.txt /*Powerline_cache_file*
Powerline_colorscheme Powerline.txt /*Powerline_colorscheme*
Powerline_dividers_override Powerline.txt /*Powerline_dividers_override*
Powerline_mode Powerline.txt /*Powerline_mode*
Powerline_stl_path_style Powerline.txt /*Powerline_stl_path_style*
Powerline_symbols Powerline.txt /*Powerline_symbols*
Powerline_symbols_override Powerline.txt /*Powerline_symbols_override*
Powerline_theme Powerline.txt /*Powerline_theme*

View file

@ -1,319 +0,0 @@
SplineFontDB: 3.0
FontName: PowerlineSymbols
FullName: PowerlineSymbols
FamilyName: PowerlineSymbols
Weight: Medium
Copyright:
UComments: "2011-11-21: Created."
Version: 001.000
ItalicAngle: 0
UnderlinePosition: -98.6328
UnderlineWidth: 48.8281
Ascent: 800
Descent: 200
LayerCount: 2
Layer: 0 0 "Back" 1
Layer: 1 0 "Fore" 0
XUID: [1021 211 26716215 11021609]
FSType: 0
OS2Version: 0
OS2_WeightWidthSlopeOnly: 0
OS2_UseTypoMetrics: 1
CreationTime: 1321867751
ModificationTime: 1326665029
OS2TypoAscent: 0
OS2TypoAOffset: 1
OS2TypoDescent: 0
OS2TypoDOffset: 1
OS2TypoLinegap: 90
OS2WinAscent: 0
OS2WinAOffset: 1
OS2WinDescent: 0
OS2WinDOffset: 1
HheadAscent: 0
HheadAOffset: 1
HheadDescent: 0
HheadDOffset: 1
OS2Vendor: 'PfEd'
MarkAttachClasses: 1
DEI: 91125
Encoding: UnicodeFull
Compacted: 1
UnicodeInterp: none
NameList: Adobe Glyph List
DisplaySize: -24
AntiAlias: 1
FitToEm: 1
WinInfo: 0 31 18
BeginPrivate: 0
EndPrivate
BeginChars: 1114112 9
StartChar: uni2B80
Encoding: 11136 11136 0
Width: 621
Flags: HMW
LayerCount: 2
Fore
SplineSet
0 1000 m 1
621 379 l 1
0 -243 l 1
0 1000 l 1
EndSplineSet
EndChar
StartChar: uni2B81
Encoding: 11137 11137 1
Width: 621
Flags: HMW
LayerCount: 2
Fore
SplineSet
10 991 m 0
16 997 23 1000 32 1000 c 0
41 1000 48 996 54 990 c 2
613 400 l 2
619 394 621 386 621 378 c 0
621 370 618 362 613 357 c 2
54 -233 l 2
48 -239 41 -242 32 -242 c 0
23 -242 16 -240 10 -234 c 0
4 -228 0 -221 0 -212 c 0
0 -203 3 -196 8 -190 c 2
547 379 l 1
8 948 l 2
3 954 0 961 0 970 c 0
0 979 4 985 10 991 c 0
EndSplineSet
EndChar
StartChar: uni2B82
Encoding: 11138 11138 2
Width: 621
Flags: HMW
LayerCount: 2
Fore
SplineSet
621 1000 m 5
621 -243 l 5
0 379 l 5
621 1000 l 5
EndSplineSet
EndChar
StartChar: uni2B83
Encoding: 11139 11139 3
Width: 621
Flags: HMW
LayerCount: 2
Fore
SplineSet
612 991 m 0
618 985 621 979 621 970 c 0
621 961 619 954 613 948 c 2
74 379 l 1
613 -190 l 2
619 -196 621 -203 621 -212 c 0
621 -221 618 -228 612 -234 c 0
606 -240 598 -242 589 -242 c 0
580 -242 574 -239 568 -233 c 2
8 357 l 2
3 362 0 370 0 378 c 0
0 386 3 394 8 400 c 2
568 990 l 2
574 996 580 1000 589 1000 c 0
598 1000 606 997 612 991 c 0
EndSplineSet
EndChar
StartChar: uni2B61
Encoding: 11105 11105 4
Width: 555
VWidth: 0
Flags: HMW
LayerCount: 2
Fore
SplineSet
0 800 m 5
92 800 l 5
92 513 l 5
253 513 l 5
253 444 l 5
0 444 l 5
0 800 l 5
236 312 m 5
339 312 l 5
468 67 l 5
468 312 l 5
555 312 l 5
555 -44 l 5
453 -44 l 5
323 200 l 5
323 -44 l 5
236 -44 l 5
236 312 l 5
EndSplineSet
EndChar
StartChar: uni2B60
Encoding: 11104 11104 5
Width: 676
Flags: HMW
LayerCount: 2
Fore
SplineSet
0 197 m 1
94 207 419 279 419 384 c 2
419 537 l 1
278 501 l 1
478 794 l 1
677 501 l 1
536 537 l 1
536 384 l 2
536 196 208 126 208 21 c 2
208 -244 l 1
0 -244 l 1
0 197 l 1
0 288 m 1
0 405 0 944 0 944 c 1
208 944 l 1
208 944 208 451 208 334 c 1
185 311 12 288 0 288 c 1
EndSplineSet
EndChar
StartChar: uni2B62
Encoding: 11106 11106 6
Width: 428
VWidth: 0
Flags: HMW
LayerCount: 2
Fore
SplineSet
88 677 m 2
429 677 l 1
429 589 l 1
88 589 l 1
88 162 l 1
198 162 l 1
198 343 l 1
374 343 l 1
374 427 l 1
198 427 l 1
198 506 l 1
429 506 l 1
429 274 l 1
416 263 391 255 374 255 c 2
286 255 l 1
286 162 l 2
286 114 246 74 198 74 c 2
88 74 l 2
40 74 0 114 0 162 c 2
0 589 l 2
0 637 40 677 88 677 c 2
EndSplineSet
EndChar
StartChar: uni2B63
Encoding: 11107 11107 7
Width: 428
VWidth: 0
Flags: HMW
LayerCount: 2
Fore
SplineSet
0 677 m 5
341 677 l 6
389 677 429 637 429 589 c 6
429 506 l 6
429 458 389 418 341 418 c 6
287 418 l 5
287 162 l 6
287 114 247 74 199 74 c 6
89 74 l 6
41 74 1 114 1 162 c 6
1 274 l 6
0 274 l 6
0 506 l 5
89 506 l 5
89 162 l 5
199 162 l 5
199 506 l 5
341 506 l 5
341 589 l 5
0 589 l 5
0 677 l 5
EndSplineSet
EndChar
StartChar: uni2B64
Encoding: 11108 11108 8
Width: 546
VWidth: 0
Flags: HMW
LayerCount: 2
Fore
SplineSet
273 733 m 4
429 733 430 538 430 538 c 5
430 420 l 5
547 420 l 5
547 303 l 5
547 303 546 -9 273 -9 c 4
0 -9 0 303 0 303 c 5
0 420 l 5
117 420 l 5
117 538 l 5
117 538 117 733 273 733 c 4
273 655 m 4
195 655 195 576 195 420 c 5
352 420 l 5
352 576 351 655 273 655 c 4
273 342 m 4
195 342 195 147 273 147 c 4
351 147 351 342 273 342 c 4
EndSplineSet
EndChar
EndChars
BitmapFont: 10 10 8 2 1
BDFChar: 0 11136 6 0 4 -2 7
JAC+4q"X@:^jlCb
BDFChar: 1 11137 6 0 4 -2 7
J3Y4g#RCta5_&h7
BDFChar: 2 11138 6 1 5 -2 7
#T,OGq"T(n(^L*A
BDFChar: 3 11139 6 1 5 -2 7
#S8+DJ:Km-&-r79
BDFChar: 4 11105 6 1 4 -1 7
J:N1>!0GR3O8o7\
BDFChar: 5 11104 7 0 5 -2 7
^rY<PaN2`d^q]pM
BDFChar: 6 11106 4 1 5 -1 6
G^u0KJ=)F+
BDFChar: 7 11107 4 0 5 -1 6
p]QtGOH>Q3
BDFChar: 8 11108 5 0 5 0 6
0M"b4bku\c
EndBitmapFont
BitmapFont: 12 10 10 2 1
BDFChar: 0 11136 7 0 6 -2 11
!!%Pbi:-O>r:od>^jlCb
BDFChar: 1 11137 7 0 6 -3 11
!!%O7+:ne]":,P]5_&h7
BDFChar: 2 11138 7 0 6 -2 11
!!!-1*'AWHr-UUH$j6P1
BDFChar: 3 11139 7 0 6 -2 11
!!!--&0O5gJ3Y4g#Qt,-
BDFChar: 4 11105 7 0 5 0 8
J:N1>!$jBP,QIfE
BDFChar: 5 11104 8 0 8 -3 11
z^];.Ma8juqa8j9]a8jQehuLOm^];.Mz
BDFChar: 6 11106 5 1 6 0 8
!-j$]R"1Qc?iU0,
BDFChar: 7 11107 5 0 5 0 7
p]QtGOH>Q3
BDFChar: 8 11108 7 0 5 0 8
0M"`*r63C_GQ7^D
EndBitmapFont
EndSplineFont

View file

@ -1,164 +0,0 @@
======================
Powerline font patcher
======================
:Author: Kim Silkebækken (kim.silkebaekken+vim@gmail.com)
Description
-----------
This font patcher creates dividers and symbols for use with Powerline. The
script requires Python 2 and FontForge compiled with Python bindings.
Patched fonts are renamed by default (" for Powerline" is added to the font
name) so they don't conflict with existing fonts. Use the ``--no-rename``
option to disable font renaming.
Glyph table
-----------
All the glyphs are stored in the ``U+2B60``-``U+2BFF`` range ("Misc symbols
and arrows").
+------------+-------------------+
| Code point | Description |
+============+===================+
| ``U+2B60`` | Branch symbol |
+------------+-------------------+
| ``U+2B61`` | LN (line) symbol |
+------------+-------------------+
| ``U+2B62`` | FT symbol, part 1 |
+------------+-------------------+
| ``U+2B63`` | FT symbol, part 2 |
+------------+-------------------+
| ``U+2B64`` | Padlock (closed) |
+------------+-------------------+
| ``U+2B80`` | Hard right arrow |
+------------+-------------------+
| ``U+2B81`` | Soft right arrow |
+------------+-------------------+
| ``U+2B82`` | Hard left arrow |
+------------+-------------------+
| ``U+2B83`` | Soft left arrow |
+------------+-------------------+
===================
Font patching guide
===================
There's a `GitHub wiki page`_ dedicated to community-contributed patched
fonts. You may download one of the fonts on that page if you don't want to
patch the fonts yourself.
If you do patch a font that's not included in the wiki (and you have
permission to distribute it), please include it on the wiki page.
**Note:** The fonts in the wiki may be outdated, and may have different
glyphs than the ones provided in the latest version of Powerline. It's
recommended that you always patch your fonts yourself if you have the
required software.
.. _`GitHub wiki page`: https://github.com/Lokaltog/vim-powerline/wiki/Patched-fonts
Linux
-----
1. Install fontforge with Python bindings. For Ubuntu users the required
package is ``python-fontforge``, for Arch Linux users the required
package is ``fontforge``. It should be something similar for other
distros.
2. Run the font patcher::
$ /path/to/fontpatcher MyFontFile.ttf
3. Copy the font file into ``~/.fonts`` (or another X font directory)::
$ cp MyFontFile-Powerline.otf ~/.fonts
**Note:** If the font is a pure bitmap font (e.g. a PCF font) it will be
stored in the BDF format. This is usually not a problem, and you may
convert the font back to the PCF format using ``bdftopcf`` if you want
to. All other fonts will be stored in the OTF format regardless of the
original format.
4. Update your font cache::
$ sudo fc-cache -vf
**Note:** If you use vim in rxvt-unicode in the client/daemon mode, you
may need to close all running terminals as well for the font to be
updated.
5. **For gvim users:** Update the GUI font in your ``vimrc`` file::
set guifont=MyFont\ for\ Powerline
**For terminal users:** Update your terminal configuration to use the
patched font.
6. Update your ``vimrc`` configuration to use the new symbols::
let g:Powerline_symbols = 'fancy'
7. Make sure that the cache file is deleted::
$ rm /tmp/Powerline.cache
8. Start vim and enjoy your new statusline!
OS X
----
1. Check if you have a FontForge version with Python support by running
``fontforge -version``. You should see something like this::
$ fontforge -version
Copyright (c) 2000-2011 by George Williams.
Executable based on sources from 13:48 GMT 22-Feb-2011-D.
Library based on sources from 13:48 GMT 22-Feb-2011.
fontforge 20110222
libfontforge 20110222
Make sure that the executable version number doesn't have ``NoPython`` in
it. If everything looks OK, skip ahead to step 4.
2. If you have FontForge but with ``NoPython`` in the version number, please
try to update to a later version::
$ brew uninstall fontforge
$ brew update
$ brew install --use-gcc fontforge
**Note:** You may have to use ``--use-clang`` instead of ``--use-gcc``
when compiling FontForge.
3. If you don't have FontForge, install it with Homebrew::
$ brew update
$ brew install --use-gcc fontforge
4. Patch your fonts by passing the ``fontpatcher`` script as a parameter to
FontForge::
$ fontforge -script /path/to/fontpatcher MyFontFile.ttf
5. Install the font by double-clicking the font file in Finder and click
"Install this font" from the preview window.
6. **For gvim users:** Update the GUI font in your ``vimrc`` file::
set guifont=MyFont\ for\ Powerline
**For terminal users:** Update your terminal configuration to use the
patched font.
7. Update your ``vimrc`` configuration to use the new symbols::
let g:Powerline_symbols = 'fancy'
8. Make sure that the cache file is deleted::
$ rm /tmp/Powerline.cache
9. Start vim and enjoy your new statusline!

View file

@ -1,240 +0,0 @@
#!/usr/bin/env python
"""Font patcher for Powerline.
Creates dividers and symbols for use with Powerline. Requires FontForge with Python bindings.
Stores glyphs in the 2b60-2bff Unicode range ("Misc symbols and arrows").
[2b60] Branch symbol
[2b61] LN (line) symbol
[2b62] FT symbol 1
[2b63] FT symbol 2
[2b64] Padlock (closed) symbol
[2b80] Hard right arrow
[2b81] Soft right arrow
[2b82] Hard left arrow
[2b83] Soft left arrow
"""
from __future__ import division
import argparse
import os
import sys
import re
try:
import fontforge
import psMat
except ImportError:
sys.stderr.write('The required FontForge modules could not be loaded.\n\n')
if sys.version_info.major > 2:
sys.stderr.write('FontForge only supports Python 2. Please run this script with the Python 2 executable - e.g. "python2 {0}"\n'.format(sys.argv[0]))
else:
sys.stderr.write('You need FontForge with Python bindings for this script to work.\n')
sys.exit(1)
# Handle command-line arguments
parser = argparse.ArgumentParser(description='Font patcher for Powerline. Creates dividers and symbols in FontForge-compatible font files. Requires FontForge with Python bindings. Stores glyphs in the U+2B80-U+2BFF range ("Miscellaneous symbols and arrows"). Stores the patched font as a new, renamed font file by default.')
parser.add_argument('fonts', help='font file to patch', metavar='font', nargs='+')
parser.add_argument('--no-rename', help='don\'t add " for Powerline" to the font name', default=True, action='store_false', dest='rename')
parser.add_argument('--symbol-font', help='font file with symbols', metavar='font', dest='symbol_font', default='{0}/PowerlineSymbols.sfd'.format(sys.path[0]))
parser.add_argument('--fix-mono', help='fixes some mono-fonts which have glyphs of 0 widths', default=False, action='store_true', dest='fixmono')
parser.add_argument('--fix-win', help='modifies font names such that Windows correctly recognizes font families', default=False, action='store_true', dest='fixwin')
args = parser.parse_args()
SYM_ATTR = {
# Right/left-aligned glyphs will have their advance width reduced in order to overlap the next glyph slightly
0x2b60: { 'align': 'c', 'stretch': 'y' , 'overlap': False },
0x2b61: { 'align': 'c', 'stretch': '' , 'overlap': False },
0x2b62: { 'align': 'r', 'stretch': '' , 'overlap': False },
0x2b63: { 'align': 'l', 'stretch': '' , 'overlap': False },
0x2b64: { 'align': 'c', 'stretch': '' , 'overlap': False },
0x2b80: { 'align': 'l', 'stretch': 'xy', 'overlap': True },
0x2b81: { 'align': 'l', 'stretch': 'xy', 'overlap': True },
0x2b82: { 'align': 'r', 'stretch': 'xy', 'overlap': True },
0x2b83: { 'align': 'r', 'stretch': 'xy', 'overlap': True },
}
# Open symbol font
try:
symbols = fontforge.open(args.symbol_font)
except EnvironmentError:
sys.exit(1)
# Patch provided fonts
for font_path in args.fonts:
try:
font = fontforge.open(font_path)
except EnvironmentError:
sys.exit(1)
# Rename font
if args.rename:
font.familyname += ' for Powerline'
font.fullname += ' for Powerline'
font.fontname += 'ForPowerline'
font.appendSFNTName('English (US)', 'Preferred Family', font.familyname)
font.appendSFNTName('English (US)', 'Compatible Full', font.fullname)
if args.fixwin:
font.fontname = re.sub(r'\W', '', font.familyname)
# Force the em size to be equal
symbols.em = font.em
# Initial font dimensions
font_dim = {
'xmin' : 0,
'ymin' : -font.descent,
'xmax' : 0,
'ymax' : font.ascent,
'width' : 0,
'height': 0,
}
# Find the biggest char width and height
#
# 0x00-0x17f is the Latin Extended-A range
# 0x2500-0x2600 is the box drawing range
for glyph in range(0x00, 0x17f) + range(0x2500, 0x2600):
try:
(xmin, ymin, xmax, ymax) = font[glyph].boundingBox()
except TypeError:
continue
if font_dim['width'] == 0:
font_dim['width'] = font[glyph].width
if ymin < font_dim['ymin']: font_dim['ymin'] = ymin
if ymax > font_dim['ymax']: font_dim['ymax'] = ymax
if xmax > font_dim['xmax']: font_dim['xmax'] = xmax
# Calculate font height
font_dim['height'] = abs(font_dim['ymin']) + font_dim['ymax']
# Update the font encoding to ensure that the Unicode glyphs are available
font.encoding = 'ISO10646'
# Fetch this property before adding outlines
onlybitmaps = font.onlybitmaps
def get_dim(glyph):
bbox = glyph.boundingBox()
return {
'xmin' : bbox[0],
'ymin' : bbox[1],
'xmax' : bbox[2],
'ymax' : bbox[3],
'width' : bbox[2] + (-bbox[0]),
'height': bbox[3] + (-bbox[1]),
}
# Create glyphs from symbol font
for sym_glyph in symbols.glyphs():
sym_attr = SYM_ATTR[sym_glyph.unicode]
# Prepare symbol glyph dimensions
sym_dim = get_dim(sym_glyph)
# Select and copy symbol from its encoding point
symbols.selection.select(sym_glyph.encoding)
symbols.copy()
# Select and paste symbol to its unicode code point
font.selection.select(sym_glyph.unicode)
font.paste()
# Now that we have copy/pasted the glyph, it's time to scale and move it
# Handle glyph stretching
if 'x' in sym_attr['stretch']:
# Stretch the glyph horizontally
scale_ratio = font_dim['width'] / sym_dim['width']
font.transform(psMat.scale(scale_ratio, 1))
if 'y' in sym_attr['stretch']:
# Stretch the glyph vertically
scale_ratio = font_dim['height'] / sym_dim['height']
font.transform(psMat.scale(1, scale_ratio))
# Use the dimensions from the pasted and stretched glyph
sym_dim = get_dim(font[sym_glyph.unicode])
# Center-align the glyph vertically
font_ycenter = font_dim['height'] / 2
sym_ycenter = sym_dim['height'] / 2
# First move it to the ymax (top)
font.transform(psMat.translate(0, font_dim['ymax'] - sym_dim['ymax']))
# Then move it the y center difference
font.transform(psMat.translate(0, sym_ycenter - font_ycenter))
# Ensure that the glyph doesn't extend outside the font's bounding box
if sym_dim['width'] > font_dim['width']:
# The glyph is too wide, scale it down to fit
scale_matrix = psMat.scale(font_dim['width'] / sym_dim['width'], 1)
font.transform(scale_matrix)
# Use the dimensions from the stretched glyph
sym_dim = get_dim(font[sym_glyph.unicode])
# Handle glyph alignment
if sym_attr['align'] == 'c':
# Center align
align_matrix = psMat.translate(font_dim['width'] / 2 - sym_dim['width'] / 2 , 0)
elif sym_attr['align'] == 'r':
# Right align
align_matrix = psMat.translate(font_dim['width'] - sym_dim['width'], 0)
else:
# No alignment (left alignment)
align_matrix = psMat.translate(0, 0)
font.transform(align_matrix)
if sym_attr['overlap'] is True:
overlap_width = font.em / 48
# Stretch the glyph slightly horizontally if it should overlap
font.transform(psMat.scale((sym_dim['width'] + overlap_width) / sym_dim['width'], 1))
if sym_attr['align'] == 'l':
# The glyph should be left-aligned, so it must be moved overlap_width to the left
# This only applies to left-aligned glyphs because the glyph is scaled to the right
font.transform(psMat.translate(-overlap_width, 0))
# Ensure the font is considered monospaced on Windows
font[sym_glyph.unicode].width = font_dim['width']
if font.bitmapSizes and not onlybitmaps:
# If this is an outline font with bitmaps, regenerate bitmaps for the changed glyphs
font.selection.changed()
for size in font.bitmapSizes:
font.regenBitmaps((size, ))
output_name, extension = os.path.split(font_path)[1].rsplit('.', 1)
if extension.lower() not in ['ttf', 'otf']:
# Default to OpenType if input is not TrueType/OpenType
extension = 'otf'
if args.fixmono:
for glyph in font.glyphs():
if glyph.width == 0: glyph.width = font_dim['width']
if onlybitmaps:
# Generate BDF font
font.generate('{0}-Powerline.bdf'.format(output_name, bitmap_type='bdf'))
else:
# Generate OTF/TTF font
font.generate('{0}-Powerline.{1}'.format(output_name, extension))

View file

@ -1,69 +0,0 @@
" Powerline - The ultimate statusline utility
"
" Author: Kim Silkebækken <kim.silkebaekken+vim@gmail.com>
" Source repository: https://github.com/Lokaltog/vim-powerline
" Script initialization {{{
if exists('g:Powerline_loaded') || &compatible || version < 702
finish
endif
let g:Powerline_loaded = 1
" }}}
" Commands {{{
command! PowerlineClearCache call Pl#ClearCache()
command! PowerlineReloadColorscheme call Pl#ReloadColorscheme()
" }}}
" Set default options {{{
for [s:key, s:value] in items({
\ 'theme' : 'default'
\ , 'colorscheme' : 'default'
\ , 'symbols' : 'compatible'
\ , 'symbols_override' : {}
\ , 'dividers_override': []
\ , 'stl_path_style' : 'relative'
\ , 'cache_enabled' : 1
\ })
if ! exists('g:Powerline_' . s:key)
exec printf('let g:Powerline_%s = %s', s:key, string(s:value))
endif
unlet! s:key s:value
endfor
if ! exists('g:Powerline_cache_file')
exec 'let g:Powerline_cache_file = '. string(printf('%s/Powerline_%s_%s_%s.cache'
\ , simplify(expand('<sfile>:p:h') .'/..')
\ , g:Powerline_theme
\ , g:Powerline_colorscheme
\ , g:Powerline_symbols
\ ))
endif
" }}}
" Autocommands {{{
function! s:CreateAutocmds()
augroup PowerlineMain
autocmd!
" Reload statuslines when changing color scheme
autocmd ColorScheme *
\ call Pl#Load()
autocmd BufEnter,WinEnter,FileType,BufUnload *
\ call Pl#UpdateStatusline(1)
autocmd BufLeave,WinLeave *
\ call Pl#UpdateStatusline(0)
autocmd BufWritePost */autoload/Powerline/Colorschemes/*.vim
\ :PowerlineReloadColorscheme
augroup END
endfunction
augroup PowerlineStartup
autocmd!
autocmd VimEnter * call s:CreateAutocmds() | call Pl#UpdateStatusline(1)
augroup END
" }}}

View file

@ -1,114 +1,148 @@
# ack.vim # # ack.vim
This plugin is a front for the Perl module Run your favorite search tool from Vim, with an enhanced results list.
[App::Ack](http://search.cpan.org/~petdance/ack/ack). Ack can be used as a
replacement for 99% of the uses of _grep_. This plugin will allow you to run
ack from vim, and shows the results in a split window.
The *Official Version* of this plugin is available at [vim.org](http://www.vim.org/scripts/script.php?script_id=2572). This plugin was designed as a Vim frontend for the Perl module [App::Ack]. Ack
can be used as a replacement for 99% of the uses of _grep_. The plugin allows
you to run ack from vim, and shows the results in a split window.
## Installation ## But here's a little secret for the Vim-seasoned: it's just a light wrapper for
Vim's [grepprg] and the [quickfix] window for match results. This makes it easy
to integrate with your own Vim configuration and use existing knowledge of core
features. It also means the plugin is flexible to use with other search tools.
[App::Ack]: http://search.cpan.org/~petdance/ack/ack
[grepprg]: http://vimdoc.sourceforge.net/htmldoc/options.html#'grepprg'
[quickfix]: http://vimdoc.sourceforge.net/htmldoc/quickfix.html#quickfix
## Installation
### Ack ### Ack
You have to install [ack](http://betterthangrep.com/), of course. You will need ack (>= 2.0), of course. To install it follow the
[manual](http://beyondgrep.com/install/).
Install on Debian / Ubuntu with:
sudo apt-get install ack-grep
Install on Fedora with:
su -l -c 'yum install ack'
Install on openSUSE with:
sudo zypper install ack
Install on Gentoo with:
sudo emerge ack
Install with Homebrew:
brew install ack
Install with MacPorts:
sudo port install p5-app-ack
Install with Gentoo Prefix:
emerge ack
Install on FreeBSD with:
cd /usr/ports/textproc/p5-ack/ && make install clean
You can specify a custom ack name and path in your .vimrc like so:
let g:ackprg="<custom-ack-path-goes-here> -H --nocolor --nogroup --column"
Otherwise, you are on your own.
### The Plugin ### The Plugin
If you have [Rake](http://rake.rubyforge.org/) installed, you can just run: `rake install`. It is recommended to use one of the popular plugin managers for Vim. There are
many and you probably already have a preferred one, but a few examples for your
copy-and-paste convenience:
Otherwise, the file ack.vim goes in ~/.vim/plugin, and the ack.txt file belongs in ~/.vim/doc. Be sure to run #### Vundle
:helptags ~/.vim/doc Plugin 'mileszs/ack.vim'
afterwards. #### NeoBundle
NeoBundle 'mileszs/ack.vim'
## Usage ## #### Manual (not recommended)
:Ack [options] {pattern} [{directory}] [Download][releases] the plugin and extract it in `~/.vim/` (or
`%PROGRAMFILES%/Vim/vimfiles` on Windows).
Search recursively in {directory} (which defaults to the current directory) for the {pattern}. [zipball]: https://github.com/mileszs/ack.vim/archive/master.zip
Files containing the search term will be listed in the split window, along with ## Usage
the line number of the occurrence, once for each occurrence. [Enter] on a line
in this window will open the file, and place the cursor on the matching line.
Just like where you use :grep, :grepadd, :lgrep, and :lgrepadd, you can use `:Ack`, `:AckAdd`, `:LAck`, and `:LAckAdd` respectively. (See `doc/ack.txt`, or install and `:h Ack` for more information.) :Ack [options] {pattern} [{directories}]
**From the [ack docs](http://betterthangrep.com/)** (my favorite feature): Search recursively in `{directories}` (which defaults to the current directory)
for the `{pattern}`.
--type=TYPE, --type=noTYPE Files containing the search term will be listed in the quickfix window, along
with the line number of the occurrence, once for each occurrence. `<Enter>` on
a line in this window will open the file, and place the cursor on the matching
line.
Specify the types of files to include or exclude from a search. TYPE is a filetype, like perl or xml. --type=perl can also be specified as --perl, and --type=noperl can be done as --noperl. Just like where you use `:grep`, `:grepadd`, `:lgrep`, and :`lgrepadd`, you can
use `:Ack`, `:AckAdd`, `:LAck`, and `:LAckAdd` respectively. (See `:help Ack`
after installing, or [`doc/ack.txt`][doc] in the repo, for more information.)
If a file is of both type "foo" and "bar", specifying --foo and --nobar will exclude the file, because an exclusion takes precedence over an inclusion. For more ack help see [ack documentation](http://beyondgrep.com/documentation/).
Type specifications can be repeated and are ORed together. [doc]: https://github.com/mileszs/ack.vim/blob/master/doc/ack.txt
See ack --help=types for a list of valid types. ### Keyboard Shortcuts
### Gotchas ### The quickfix results window is augmented with these convenience mappings:
Some characters have special meaning, and need to be escaped your search pattern. For instance, '#'. You have to escape it like this `:Ack '\\\#define foo'` to search for `#define foo`. (From [blueyed in issue #5](https://github.com/mileszs/ack.vim/issues/5).) ? a quick summary of these keys, repeat to close
o to open (same as Enter)
### Keyboard Shortcuts ### O to open and close the quickfix window
go to preview file, open but maintain focus on ack.vim results
In the quickfix window, you can use:
o to open (same as enter)
go to preview file (open but maintain focus on ack.vim results)
t to open in new tab t to open in new tab
T to open in new tab silently T to open in new tab without moving to it
h to open in horizontal split h to open in horizontal split
H to open in horizontal split silently H to open in horizontal split, keeping focus on the results
v to open in vertical split v to open in vertical split
gv to open in vertical split silently gv to open in vertical split, keeping focus on the results
q to close the quickfix window q to close the quickfix window
This Vim plugin is derived (and by derived, I mean copied, essentially) from ### Gotchas
Antoine Imbert's blog post [Ack and Vim
Integration](http://blog.ant0ine.com/typepad/2007/03/ack-and-vim-integration.html) (in Some characters have special meaning, and need to be escaped in your search
particular, the function at the bottom of the post). I added a help file that pattern. For instance, `#`. You need to escape it with `:Ack '\\\#define
provides just enough reference to get you going. I also highly recommend you foo'` to search for '#define foo'. See [issue #5].
check out the docs for the Perl script 'ack', for obvious reasons: [ack -
grep-like text finder](http://betterthangrep.com/). [issue #5]: https://github.com/mileszs/ack.vim/issues/5
## Possibly FAQ
#### Can I use `ag` ([The Silver Searcher]) with this?
Absolutely, and probably other tools if their output is similar or you can
write a pattern match for it--just set `g:ackprg`. If you like, you can fall
back to Ack in case you use your vimrc on a system without Ag available:
```vim
if executable('ag')
let g:ackprg = 'ag --vimgrep'
endif
```
Since Ack is quite portable you might check a copy of it into your dotfiles
repository in `~/bin` so you'll nearly always have it available.
#### What's the difference from ag.vim?
Well... not a lot really.
Present maintainer, yours truly, [kind of wishes they never forked][sadface],
contributes to both, and wouldn't mind seeing them merged again. ag.vim got a
nice code clean-up (which ack.vim is now hopefully getting), and ack.vim picked
up a few features that haven't made their way to ag.vim, like `:AckWindow`,
optional background search execution with [vim-dispatch], and auto-previewing.
[The Silver Searcher]: https://github.com/ggreer/the_silver_searcher
[sadface]: https://github.com/mileszs/ack.vim/commit/d97090fb502d40229e6976dfec0e06636ba227d5#commitcomment-5771145
## Changelog
Please see [the Github releases page][releases].
### 1.0.9 (unreleased)
* Fix location list and layout of quickfix when using Dispatch (#154)
* Fix the quick help overlay clobbering the list mappings
* Fix `:AckFile` when using Dispatch
* Restore original `'makeprg'` and `'errorformat'` when using Dispatch
* Internal refactoring and clean-up
## Credits
This plugin is derived from Antoine Imbert's blog post [Ack and Vim
Integration][] (in particular, the function in the update to the post). [Miles
Sterrett][mileszs] packaged it up as a plugin and documented it in Vim's help
format, and since then [many contributors][contributors] have submitted
enhancements and fixes.
And of course, where would we be without [Ack]. And, you know, Vim.
[Ack and Vim Integration]: http://blog.ant0ine.com/typepad/2007/03/ack-and-vim-integration.html
[mileszs]: https://github.com/mileszs
[contributors]: https://github.com/mileszs/ack.vim/graphs/contributors
[Ack]: http://beyondgrep.com/
[vim-dispatch]: https://github.com/tpope/vim-dispatch
[releases]: https://github.com/mileszs/ack.vim/releases

View file

@ -1,23 +0,0 @@
# Added by Josh Nichols, a.k.a. technicalpickles
require 'rake'
files = ['doc/ack.txt', 'plugin/ack.vim']
desc 'Install plugin and documentation'
task :install do
vimfiles = if ENV['VIMFILES']
ENV['VIMFILES']
elsif RUBY_PLATFORM =~ /(win|w)32$/
File.expand_path("~/vimfiles")
else
File.expand_path("~/.vim")
end
files.each do |file|
target_file = File.join(vimfiles, file)
FileUtils.mkdir_p File.dirname(target_file)
FileUtils.cp file, target_file
puts " Copied #{file} to #{target_file}"
end
end

View file

@ -0,0 +1,235 @@
if exists('g:ack_use_dispatch')
if g:ack_use_dispatch && !exists(':Dispatch')
call s:Warn('Dispatch not loaded! Falling back to g:ack_use_dispatch = 0.')
let g:ack_use_dispatch = 0
endif
else
let g:ack_use_dispatch = 0
end
"-----------------------------------------------------------------------------
" Public API
"-----------------------------------------------------------------------------
function! ack#Ack(cmd, args) "{{{
call s:Init(a:cmd)
redraw
" Local values that we'll temporarily set as options when searching
let l:grepprg = g:ackprg
let l:grepformat = '%f:%l:%c:%m,%f:%l:%m' " Include column number
" Strip some options that are meaningless for path search and set match
" format accordingly.
if s:SearchingFilepaths()
let l:grepprg = substitute(l:grepprg, '-H\|--column', '', 'g')
let l:grepformat = '%f'
endif
" If no pattern is provided, search for the word under the cursor
if empty(a:args)
let l:grepargs = expand("<cword>")
else
let l:grepargs = a:args . join(a:000, ' ')
end
" NOTE: we escape special chars, but not everything using shellescape to
" allow for passing arguments etc
let l:escaped_args = escape(l:grepargs, '|#%')
echo "Searching ..."
if g:ack_use_dispatch
call s:SearchWithDispatch(l:grepprg, l:escaped_args, l:grepformat)
else
call s:SearchWithGrep(a:cmd, l:grepprg, l:escaped_args, l:grepformat)
endif
" Dispatch has no callback mechanism currently, we just have to display the
" list window early and wait for it to populate :-/
call ack#ShowResults()
call s:Highlight(l:grepargs)
endfunction "}}}
function! ack#AckFromSearch(cmd, args) "{{{
let search = getreg('/')
" translate vim regular expression to perl regular expression.
let search = substitute(search, '\(\\<\|\\>\)', '\\b', 'g')
call ack#Ack(a:cmd, '"' . search . '" ' . a:args)
endfunction "}}}
function! ack#AckHelp(cmd, args) "{{{
let args = a:args . ' ' . s:GetDocLocations()
call ack#Ack(a:cmd, args)
endfunction "}}}
function! ack#AckWindow(cmd, args) "{{{
let files = tabpagebuflist()
" remove duplicated filenames (files appearing in more than one window)
let files = filter(copy(sort(files)), 'index(files,v:val,v:key+1)==-1')
call map(files, "bufname(v:val)")
" remove unnamed buffers as quickfix (empty strings before shellescape)
call filter(files, 'v:val != ""')
" expand to full path (avoid problems with cd/lcd in au QuickFixCmdPre)
let files = map(files, "shellescape(fnamemodify(v:val, ':p'))")
let args = a:args . ' ' . join(files)
call ack#Ack(a:cmd, args)
endfunction "}}}
function! ack#ShowResults() "{{{
let l:handler = s:UsingLocList() ? g:ack_lhandler : g:ack_qhandler
execute l:handler
call s:ApplyMappings()
redraw!
endfunction "}}}
"-----------------------------------------------------------------------------
" Private API
"-----------------------------------------------------------------------------
function! s:ApplyMappings() "{{{
if !s:UsingListMappings() || &filetype != 'qf'
return
endif
let l:wintype = s:UsingLocList() ? 'l' : 'c'
let l:closemap = ':' . l:wintype . 'close<CR>'
let g:ack_mappings.q = l:closemap
nnoremap <buffer> <silent> ? :call <SID>QuickHelp()<CR>
if g:ack_autoclose
" We just map the 'go' and 'gv' mappings to close on autoclose, wtf?
for key_map in items(g:ack_mappings)
execute printf("nnoremap <buffer> <silent> %s %s", get(key_map, 0), get(key_map, 1) . l:closemap)
endfor
execute "nnoremap <buffer> <silent> <CR> <CR>" . l:closemap
else
for key_map in items(g:ack_mappings)
execute printf("nnoremap <buffer> <silent> %s %s", get(key_map, 0), get(key_map, 1))
endfor
endif
if exists("g:ackpreview") " if auto preview in on, remap j and k keys
nnoremap <buffer> <silent> j j<CR><C-W><C-W>
nnoremap <buffer> <silent> k k<CR><C-W><C-W>
endif
endfunction "}}}
function! s:GetDocLocations() "{{{
let dp = ''
for p in split(&rtp, ',')
let p = p . '/doc/'
if isdirectory(p)
let dp = p . '*.txt ' . dp
endif
endfor
return dp
endfunction "}}}
function! s:Highlight(args) "{{{
if !g:ackhighlight
return
endif
let @/ = matchstr(a:args, "\\v(-)\@<!(\<)\@<=\\w+|['\"]\\zs.{-}\\ze['\"]")
call feedkeys(":let &hlsearch=1 \| echo \<CR>", "n")
endfunction "}}}
" Initialize state for an :Ack* or :LAck* search
function! s:Init(cmd) "{{{
let s:searching_filepaths = (a:cmd =~# '-g$') ? 1 : 0
let s:using_loclist = (a:cmd =~# '^l') ? 1 : 0
if g:ack_use_dispatch && s:using_loclist
call s:Warn('Dispatch does not support location lists! Proceeding with quickfix...')
let s:using_loclist = 0
endif
endfunction "}}}
function! s:QuickHelp() "{{{
execute 'edit' globpath(&rtp, 'doc/ack_quick_help.txt')
silent normal gg
setlocal buftype=nofile
setlocal bufhidden=hide
setlocal noswapfile
setlocal nobuflisted
setlocal nomodifiable
setlocal filetype=help
setlocal nonumber
setlocal norelativenumber
setlocal nowrap
setlocal foldlevel=20
setlocal foldmethod=diff
nnoremap <buffer> <silent> ? :q!<CR>:call ack#ShowResults()<CR>
endfunction "}}}
function! s:SearchWithDispatch(grepprg, grepargs, grepformat) "{{{
let l:makeprg_bak = &l:makeprg
let l:errorformat_bak = &l:errorformat
" We don't execute a :grep command for Dispatch, so add -g here instead
if s:SearchingFilepaths()
let l:grepprg = a:grepprg . ' -g'
else
let l:grepprg = a:grepprg
endif
try
let &l:makeprg = l:grepprg . ' ' . a:grepargs
let &l:errorformat = a:grepformat
Make
finally
let &l:makeprg = l:makeprg_bak
let &l:errorformat = l:errorformat_bak
endtry
endfunction "}}}
function! s:SearchWithGrep(grepcmd, grepprg, grepargs, grepformat) "{{{
let l:grepprg_bak = &l:grepprg
let l:grepformat_bak = &grepformat
try
let &l:grepprg = a:grepprg
let &grepformat = a:grepformat
silent execute a:grepcmd a:grepargs
finally
let &l:grepprg = l:grepprg_bak
let &grepformat = l:grepformat_bak
endtry
endfunction "}}}
" Are we finding matching files, not lines? (the -g option -- :AckFile)
function! s:SearchingFilepaths() "{{{
return get(s:, 'searching_filepaths', 0)
endfunction "}}}
" Predicate for whether mappings are enabled for list type of current search.
function! s:UsingListMappings() "{{{
if s:UsingLocList()
return g:ack_apply_lmappings
else
return g:ack_apply_qmappings
endif
endfunction "}}}
" Were we invoked with a :LAck command?
function! s:UsingLocList() "{{{
return get(s:, 'using_loclist', 0)
endfunction "}}}
function! s:Warn(msg) "{{{
echohl WarningMsg | echomsg 'Ack: ' . a:msg | echohl None
endf "}}}
" vim:set et sw=2 ts=2 tw=78 fdm=marker

View file

@ -16,7 +16,7 @@ shows the results in a split window.
Search recursively in {directory} (which defaults to the current Search recursively in {directory} (which defaults to the current
directory) for the {pattern}. Behaves just like the |:grep| command, but directory) for the {pattern}. Behaves just like the |:grep| command, but
will open the |Quickfix| window for you. If [!] is not given the first will open the |Quickfix| window for you. If [!] is not given the first
error is jumped to. occurence is jumped to.
:AckAdd [options] {pattern} [{directory}] *:AckAdd* :AckAdd [options] {pattern} [{directory}] *:AckAdd*
@ -53,12 +53,177 @@ shows the results in a split window.
Just like |:AckHelp| but instead of the |quickfix| list, matches are placed Just like |:AckHelp| but instead of the |quickfix| list, matches are placed
in the current |location-list|. in the current |location-list|.
:AckWindow[!] [options] {pattern} *:AckWindow*
Search all buffers visible in the screen (current tab page only) files for
the {pattern}.
:LAckWindow [options] {pattern} *:LAckWindow*
Just like |:AckWindow| but instead of the |quickfix| list, matches are
placed in the current |location-list|.
Files containing the search term will be listed in the split window, along Files containing the search term will be listed in the split window, along
with the line number of the occurrence, once for each occurrence. <Enter> on with the line number of the occurrence, once for each occurrence. <Enter> on
a line in this window will open the file, and place the cursor on the matching a line in this window will open the file, and place the cursor on the matching
line. line.
See http://betterthangrep.com/ for more information. Note that if you are using Dispatch.vim with |g:ack_use_dispatch|, location
lists are not supported, because Dispatch does not support them at this time.
`:LAck` versions of commands above will give a warning and proceed to use the
quickfix list instead.
See http://beyondgrep.com/ for more information on searching with ack.
==============================================================================
CONFIGURATION *ack-configuration*
*g:ackprg*
g:ackprg
Default for ubuntu: "ack-grep"
Default for other systems: "ack"
Use this option to specify the ack command and its options
Example:
>
let g:ackprg = "other-bin-ack"
<
*g:ack_default_options*
g:ack_default_options
Default: " -s -H --nocolor --nogroup --column"
Use this option to specify the options used by ack
Example:
>
let g:ack_default_options =
\ " -s -H --nocolor --nogroup --column --smart-case --follow"
<
*g:ack_apply_qmappings*
g:ack_apply_qmappings
Default: 1
This option enable mappings on quickview window.
*g:ack_apply_lmappings*
g:ack_apply_lmappings
Default: 1
This option enable mappings on Location list window.
*g:ack_mappings*
g:ack_mappings
Default: {
\ "t": "<C-W><CR><C-W>T",
\ "T": "<C-W><CR><C-W>TgT<C-W>j",
\ "o": "<CR>",
\ "O": "<CR><C-W><C-W>:ccl<CR>",
\ "go": "<CR><C-W>j",
\ "h": "<C-W><CR><C-W>K",
\ "H": "<C-W><CR><C-W>K<C-W>b",
\ "v": "<C-W><CR><C-W>H<C-W>b<C-W>J<C-W>t",
\ "gv": "<C-W><CR><C-W>H<C-W>b<C-W>J" }
This option list all maps create on quickfix/Location list window.
Example, if you want to open the result in the middle of the screen:
>
let g:ack_mappings = { "o": "<CR>zz" }
<
*g:ack_qhandler*
g:ack_qhandler
Default: "botright copen"
Command to open the quickview window.
If you want to open a quickview window with 30 lines you can do:
>
let g:ack_qhandler = "botright copen 30"
<
*g:ack_lhandler*
g:ack_lhandler
Default: "botright lopen"
Command to open the Location list window.
If you want to open a Location list window with 30 lines you can do:
>
let g:ack_lhandler = "botright lopen 30"
<
*g:ackhighlight*
g:ackhighlight
Default: 0
Use this option to highlight the searched term.
Example:
>
let g:ackhighlight = 1
<
*g:ack_autoclose*
g:ack_autoclose
Default: 0
Use this option to specify whether to close the quickfix window after
using any of the shortcuts.
Example:
>
let g:ack_autoclose = 1
<
*g:ack_autofold_results*
g:ack_autofold_results
Default: 0
Use this option to fold the results in quickfix by file name. Only the current
fold will be open by default and while you press 'j' and 'k' to move between the
results if you hit other fold the last one will be closed and the current will
be open.
Example:
>
let g:ack_autofold_results = 1
<
*g:ackpreview*
g:ackpreview
Default: 0
Use this option to automagically open the file with 'j' or 'k'.
Example:
>
let g:ackpreview = 1
<
*g:ack_use_dispatch*
g:ack_use_dispatch
Default: 0
Use this option to use vim-dispatch to run searches in the background, with a
variety of execution backends for different systems.
Due to limitations in Dispatch at this time, location lists are unsupported
and result windows will appear before results are ready. Still, these may be
acceptable tradeoffs for very large projects where searches are slow.
Example:
>
let g:ack_use_dispatch = 1
<
============================================================================== ==============================================================================
MAPPINGS *ack-mappings* MAPPINGS *ack-mappings*
@ -67,6 +232,8 @@ The following keyboard shortcuts are available in the quickfix window:
o open file (same as enter). o open file (same as enter).
O open file and close quickfix window.
go preview file (open but maintain focus on ack.vim results). go preview file (open but maintain focus on ack.vim results).
t open in a new tab. t open in a new tab.

View file

@ -0,0 +1,14 @@
==== ack.vim quick help ===============
*?:* Show/quit this help
*t:* Open in a new tab
*T:* Open in a new tab silently
*o:* Open
*O:* Open and close result window
*go:* Preview
*h:* Horizontal open
*H:* Horizontal open silently
*v:* Vertical open
*gv:* Vertical open silently
========================================

View file

@ -0,0 +1,9 @@
if exists("g:ack_autofold_results") && g:ack_autofold_results
setlocal foldlevel=0
setlocal foldmethod=expr
setlocal foldexpr=matchstr(getline(v:lnum),'^[^\|]\\+')==#matchstr(getline(v:lnum+1),'^[^\|]\\+')?1:'<1'
setlocal foldenable
setlocal foldclose=all
setlocal foldopen=all
nnoremap <buffer> j jzz
endif

View file

@ -1,16 +1,21 @@
" NOTE: You must, of course, install the ack script if exists('g:loaded_ack')
" in your path. finish
" On Debian / Ubuntu: endif
" sudo apt-get install ack-grep
" With MacPorts: if !exists("g:ack_default_options")
" sudo port install p5-app-ack let g:ack_default_options = " -s -H --nocolor --nogroup --column"
" With Homebrew: endif
" brew install ack
" Location of the ack utility " Location of the ack utility
if !exists("g:ackprg") if !exists("g:ackprg")
let s:ackcommand = executable('ack-grep') ? 'ack-grep' : 'ack' if executable('ack')
let g:ackprg=s:ackcommand." -H --nocolor --nogroup --column" let g:ackprg = "ack"
elseif executable('ack-grep')
let g:ackprg = "ack-grep"
else
finish
endif
let g:ackprg .= g:ack_default_options
endif endif
if !exists("g:ack_apply_qmappings") if !exists("g:ack_apply_qmappings")
@ -21,100 +26,54 @@ if !exists("g:ack_apply_lmappings")
let g:ack_apply_lmappings = !exists("g:ack_lhandler") let g:ack_apply_lmappings = !exists("g:ack_lhandler")
endif endif
let s:ack_mappings = {
\ "t": "<C-W><CR><C-W>T",
\ "T": "<C-W><CR><C-W>TgT<C-W>j",
\ "o": "<CR>",
\ "O": "<CR><C-W>p<C-W>c",
\ "go": "<CR><C-W>p",
\ "h": "<C-W><CR><C-W>K",
\ "H": "<C-W><CR><C-W>K<C-W>b",
\ "v": "<C-W><CR><C-W>H<C-W>b<C-W>J<C-W>t",
\ "gv": "<C-W><CR><C-W>H<C-W>b<C-W>J" }
if exists("g:ack_mappings")
let g:ack_mappings = extend(s:ack_mappings, g:ack_mappings)
else
let g:ack_mappings = s:ack_mappings
endif
if !exists("g:ack_qhandler") if !exists("g:ack_qhandler")
let g:ack_qhandler="botright copen" let g:ack_qhandler = "botright copen"
endif endif
if !exists("g:ack_lhandler") if !exists("g:ack_lhandler")
let g:ack_lhandler="botright lopen" let g:ack_lhandler = "botright lopen"
endif endif
function! s:Ack(cmd, args) if !exists("g:ackhighlight")
redraw let g:ackhighlight = 0
echo "Searching ..." endif
" If no pattern is provided, search for the word under the cursor if !exists("g:ack_autoclose")
if empty(a:args) let g:ack_autoclose = 0
let l:grepargs = expand("<cword>") endif
else
let l:grepargs = a:args . join(a:000, ' ')
end
" Format, used to manage column jump if !exists("g:ack_autofold_results")
if a:cmd =~# '-g$' let g:ack_autofold_results = 0
let g:ackformat="%f" endif
else
let g:ackformat="%f:%l:%c:%m"
end
let grepprg_bak=&grepprg command! -bang -nargs=* -complete=file Ack call ack#Ack('grep<bang>', <q-args>)
let grepformat_bak=&grepformat command! -bang -nargs=* -complete=file AckAdd call ack#Ack('grepadd<bang>', <q-args>)
try command! -bang -nargs=* -complete=file AckFromSearch call ack#AckFromSearch('grep<bang>', <q-args>)
let &grepprg=g:ackprg command! -bang -nargs=* -complete=file LAck call ack#Ack('lgrep<bang>', <q-args>)
let &grepformat=g:ackformat command! -bang -nargs=* -complete=file LAckAdd call ack#Ack('lgrepadd<bang>', <q-args>)
silent execute a:cmd . " " . escape(l:grepargs, '|') command! -bang -nargs=* -complete=file AckFile call ack#Ack('grep<bang> -g', <q-args>)
finally command! -bang -nargs=* -complete=help AckHelp call ack#AckHelp('grep<bang>', <q-args>)
let &grepprg=grepprg_bak command! -bang -nargs=* -complete=help LAckHelp call ack#AckHelp('lgrep<bang>', <q-args>)
let &grepformat=grepformat_bak command! -bang -nargs=* -complete=help AckWindow call ack#AckWindow('grep<bang>', <q-args>)
endtry command! -bang -nargs=* -complete=help LAckWindow call ack#AckWindow('lgrep<bang>', <q-args>)
if a:cmd =~# '^l' let g:loaded_ack = 1
exe g:ack_lhandler
let l:apply_mappings = g:ack_apply_lmappings
else
exe g:ack_qhandler
let l:apply_mappings = g:ack_apply_qmappings
endif
if l:apply_mappings " vim:set et sw=2 ts=2 tw=78 fdm=marker
exec "nnoremap <silent> <buffer> q :ccl<CR>"
exec "nnoremap <silent> <buffer> t <C-W><CR><C-W>T"
exec "nnoremap <silent> <buffer> T <C-W><CR><C-W>TgT<C-W><C-W>"
exec "nnoremap <silent> <buffer> o <CR>"
exec "nnoremap <silent> <buffer> go <CR><C-W><C-W>"
exec "nnoremap <silent> <buffer> h <C-W><CR><C-W>K"
exec "nnoremap <silent> <buffer> H <C-W><CR><C-W>K<C-W>b"
exec "nnoremap <silent> <buffer> v <C-W><CR><C-W>H<C-W>b<C-W>J<C-W>t"
exec "nnoremap <silent> <buffer> gv <C-W><CR><C-W>H<C-W>b<C-W>J"
endif
" If highlighting is on, highlight the search keyword.
if exists("g:ackhighlight")
let @/=a:args
set hlsearch
end
redraw!
endfunction
function! s:AckFromSearch(cmd, args)
let search = getreg('/')
" translate vim regular expression to perl regular expression.
let search = substitute(search,'\(\\<\|\\>\)','\\b','g')
call s:Ack(a:cmd, '"' . search .'" '. a:args)
endfunction
function! s:GetDocLocations()
let dp = ''
for p in split(&rtp,',')
let p = p.'/doc/'
if isdirectory(p)
let dp = p.'*.txt '.dp
endif
endfor
return dp
endfunction
function! s:AckHelp(cmd,args)
let args = a:args.' '.s:GetDocLocations()
call s:Ack(a:cmd,args)
endfunction
command! -bang -nargs=* -complete=file Ack call s:Ack('grep<bang>',<q-args>)
command! -bang -nargs=* -complete=file AckAdd call s:Ack('grepadd<bang>', <q-args>)
command! -bang -nargs=* -complete=file AckFromSearch call s:AckFromSearch('grep<bang>', <q-args>)
command! -bang -nargs=* -complete=file LAck call s:Ack('lgrep<bang>', <q-args>)
command! -bang -nargs=* -complete=file LAckAdd call s:Ack('lgrepadd<bang>', <q-args>)
command! -bang -nargs=* -complete=file AckFile call s:Ack('grep<bang> -g', <q-args>)
command! -bang -nargs=* -complete=help AckHelp call s:AckHelp('grep<bang>',<q-args>)
command! -bang -nargs=* -complete=help LAckHelp call s:AckHelp('lgrep<bang>',<q-args>)

View file

@ -1,24 +0,0 @@
bufexplorer bufexplorer.txt /*bufexplorer*
bufexplorer-changelog bufexplorer.txt /*bufexplorer-changelog*
bufexplorer-credits bufexplorer.txt /*bufexplorer-credits*
bufexplorer-customization bufexplorer.txt /*bufexplorer-customization*
bufexplorer-installation bufexplorer.txt /*bufexplorer-installation*
bufexplorer-todo bufexplorer.txt /*bufexplorer-todo*
bufexplorer-usage bufexplorer.txt /*bufexplorer-usage*
bufexplorer-windowlayout bufexplorer.txt /*bufexplorer-windowlayout*
bufexplorer.txt bufexplorer.txt /*bufexplorer.txt*
buffer-explorer bufexplorer.txt /*buffer-explorer*
g:bufExplorerChgWin bufexplorer.txt /*g:bufExplorerChgWin*
g:bufExplorerDefaultHelp bufexplorer.txt /*g:bufExplorerDefaultHelp*
g:bufExplorerDetailedHelp bufexplorer.txt /*g:bufExplorerDetailedHelp*
g:bufExplorerFindActive bufexplorer.txt /*g:bufExplorerFindActive*
g:bufExplorerFuncRef bufexplorer.txt /*g:bufExplorerFuncRef*
g:bufExplorerReverseSort bufexplorer.txt /*g:bufExplorerReverseSort*
g:bufExplorerShowDirectories bufexplorer.txt /*g:bufExplorerShowDirectories*
g:bufExplorerShowRelativePath bufexplorer.txt /*g:bufExplorerShowRelativePath*
g:bufExplorerShowTabBuffer bufexplorer.txt /*g:bufExplorerShowTabBuffer*
g:bufExplorerShowUnlisted bufexplorer.txt /*g:bufExplorerShowUnlisted*
g:bufExplorerSortBy bufexplorer.txt /*g:bufExplorerSortBy*
g:bufExplorerSplitBelow bufexplorer.txt /*g:bufExplorerSplitBelow*
g:bufExplorerSplitOutPathName bufexplorer.txt /*g:bufExplorerSplitOutPathName*
g:bufExplorerSplitRight bufexplorer.txt /*g:bufExplorerSplitRight*

View file

@ -68,6 +68,7 @@ let [s:pref, s:bpref, s:opts, s:new_opts, s:lc_opts] =
\ 'key_loop': ['s:keyloop', 0], \ 'key_loop': ['s:keyloop', 0],
\ 'lazy_update': ['s:lazy', 0], \ 'lazy_update': ['s:lazy', 0],
\ 'match_func': ['s:matcher', {}], \ 'match_func': ['s:matcher', {}],
\ 'match_window': ['s:mw', ''],
\ 'match_window_bottom': ['s:mwbottom', 1], \ 'match_window_bottom': ['s:mwbottom', 1],
\ 'match_window_reversed': ['s:mwreverse', 1], \ 'match_window_reversed': ['s:mwreverse', 1],
\ 'max_depth': ['s:maxdepth', 40], \ 'max_depth': ['s:maxdepth', 40],
@ -102,7 +103,7 @@ let [s:pref, s:bpref, s:opts, s:new_opts, s:lc_opts] =
" Global options " Global options
let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, 'im': 0, let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, 'im': 0,
\ 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, 'mfd': 200, 'mouse': 'n', \ 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, 'mfd': 200, 'ttimeout': 0,
\ 'gcr': 'a:blinkon0', 'ic': 1, 'lmap': '', 'mousef': 0, 'imd': 1 } \ 'gcr': 'a:blinkon0', 'ic': 1, 'lmap': '', 'mousef': 0, 'imd': 1 }
" Keymaps " Keymaps
@ -181,7 +182,7 @@ let s:hlgrps = {
\ 'PrtText': 'Normal', \ 'PrtText': 'Normal',
\ 'PrtCursor': 'Constant', \ 'PrtCursor': 'Constant',
\ } \ }
" s:opts() {{{2 " Get the options {{{2
fu! s:opts(...) fu! s:opts(...)
unl! s:usrign s:usrcmd s:urprtmaps unl! s:usrign s:usrcmd s:urprtmaps
for each in ['byfname', 'regexp', 'extensions'] | if exists('s:'.each) for each in ['byfname', 'regexp', 'extensions'] | if exists('s:'.each)
@ -201,6 +202,9 @@ fu! s:opts(...)
let {va} = {s:bpref.ke} let {va} = {s:bpref.ke}
en en
endfo endfo
" Match window options
cal s:match_window_opts()
" One-time values
if a:0 && a:1 != {} if a:0 && a:1 != {}
unl va unl va
for [ke, va] in items(a:1) for [ke, va] in items(a:1)
@ -217,7 +221,6 @@ fu! s:opts(...)
en | endfo en | endfo
if !exists('g:ctrlp_newcache') | let g:ctrlp_newcache = 0 | en if !exists('g:ctrlp_newcache') | let g:ctrlp_newcache = 0 | en
let s:maxdepth = min([s:maxdepth, 100]) let s:maxdepth = min([s:maxdepth, 100])
let s:mxheight = max([s:mxheight, 1])
let s:glob = s:showhidden ? '.*\|*' : '*' let s:glob = s:showhidden ? '.*\|*' : '*'
let s:igntype = empty(s:usrign) ? -1 : type(s:usrign) let s:igntype = empty(s:usrign) ? -1 : type(s:usrign)
let s:lash = ctrlp#utils#lash() let s:lash = ctrlp#utils#lash()
@ -238,13 +241,36 @@ fu! s:opts(...)
cal extend(s:prtmaps, s:urprtmaps) cal extend(s:prtmaps, s:urprtmaps)
en en
endf endf
fu! s:match_window_opts()
let s:mw_pos =
\ s:mw =~ 'top\|bottom' ? matchstr(s:mw, 'top\|bottom') :
\ exists('g:ctrlp_match_window_bottom') ? ( s:mwbottom ? 'bottom' : 'top' )
\ : 'bottom'
let s:mw_order =
\ s:mw =~ 'order:[^,]\+' ? matchstr(s:mw, 'order:\zs[^,]\+') :
\ exists('g:ctrlp_match_window_reversed') ? ( s:mwreverse ? 'btt' : 'ttb' )
\ : 'btt'
let s:mw_max =
\ s:mw =~ 'max:[^,]\+' ? str2nr(matchstr(s:mw, 'max:\zs\d\+')) :
\ exists('g:ctrlp_max_height') ? s:mxheight
\ : 10
let s:mw_min =
\ s:mw =~ 'min:[^,]\+' ? str2nr(matchstr(s:mw, 'min:\zs\d\+')) : 1
let [s:mw_max, s:mw_min] = [max([s:mw_max, 1]), max([s:mw_min, 1])]
let s:mw_min = min([s:mw_min, s:mw_max])
let s:mw_res =
\ s:mw =~ 'results:[^,]\+' ? str2nr(matchstr(s:mw, 'results:\zs\d\+'))
\ : min([s:mw_max, &lines])
let s:mw_res = max([s:mw_res, 1])
endf
"}}}1 "}}}1
" * Open & Close {{{1 " * Open & Close {{{1
fu! s:Open() fu! s:Open()
cal s:log(1) cal s:log(1)
cal s:getenv() cal s:getenv()
cal s:execextvar('enter') cal s:execextvar('enter')
sil! exe 'keepa' ( s:mwbottom ? 'bo' : 'to' ) '1new ControlP' sil! exe 'keepa' ( s:mw_pos == 'top' ? 'to' : 'bo' ) '1new ControlP'
cal s:buffunc(1) cal s:buffunc(1)
let [s:bufnr, s:winw] = [bufnr('%'), winwidth(0)] let [s:bufnr, s:winw] = [bufnr('%'), winwidth(0)]
let [s:focus, s:prompt] = [1, ['', '', '']] let [s:focus, s:prompt] = [1, ['', '', '']]
@ -297,7 +323,7 @@ fu! ctrlp#clra()
if isdirectory(cadir) if isdirectory(cadir)
let cafiles = split(s:glbpath(s:fnesc(cadir, 'g', ','), '**', 1), "\n") let cafiles = split(s:glbpath(s:fnesc(cadir, 'g', ','), '**', 1), "\n")
let eval = '!isdirectory(v:val) && v:val !~ ''\v[\/]cache[.a-z]+$|\.log$''' let eval = '!isdirectory(v:val) && v:val !~ ''\v[\/]cache[.a-z]+$|\.log$'''
sil! cal map(filter(cafiles, eval), 'delete(v:val)') sil! cal map(s:ifilter(cafiles, eval), 'delete(v:val)')
en en
cal ctrlp#clr() cal ctrlp#clr()
endf endf
@ -362,7 +388,7 @@ fu! s:UserCmd(lscmd)
let [ssl, &ssl, path] = [&ssl, 0, tr(path, '/', '\')] let [ssl, &ssl, path] = [&ssl, 0, tr(path, '/', '\')]
en en
if has('win32') || has('win64') if has('win32') || has('win64')
let lscmd = substitute(lscmd, '\v(^|&&\s*)\zscd (/d)@!', 'cd /d ', '') let lscmd = substitute(lscmd, '\v(^|\&\&\s*)\zscd (/d)@!', 'cd /d ', '')
en en
let path = exists('*shellescape') ? shellescape(path) : path let path = exists('*shellescape') ? shellescape(path) : path
let g:ctrlp_allfiles = split(system(printf(lscmd, path)), "\n") let g:ctrlp_allfiles = split(system(printf(lscmd, path)), "\n")
@ -433,7 +459,7 @@ endf
fu! s:MatchIt(items, pat, limit, exc) fu! s:MatchIt(items, pat, limit, exc)
let [lines, id] = [[], 0] let [lines, id] = [[], 0]
let pat = let pat =
\ s:byfname ? map(split(a:pat, '^[^;]\+\\\@<!\zs;', 1), 's:martcs.v:val') \ s:byfname() ? map(split(a:pat, '^[^;]\+\\\@<!\zs;', 1), 's:martcs.v:val')
\ : s:martcs.a:pat \ : s:martcs.a:pat
for item in a:items for item in a:items
let id += 1 let id += 1
@ -450,7 +476,16 @@ fu! s:MatchedItems(items, pat, limit)
let exc = exists('s:crfilerel') ? s:crfilerel : '' let exc = exists('s:crfilerel') ? s:crfilerel : ''
let items = s:narrowable() ? s:matched + s:mdata[3] : a:items let items = s:narrowable() ? s:matched + s:mdata[3] : a:items
if s:matcher != {} if s:matcher != {}
let argms = [items, a:pat, a:limit, s:mmode(), s:ispath, exc, s:regexp] let argms =
\ has_key(s:matcher, 'arg_type') && s:matcher['arg_type'] == 'dict' ? [{
\ 'items': items,
\ 'str': a:pat,
\ 'limit': a:limit,
\ 'mmode': s:mmode(),
\ 'ispath': s:ispath,
\ 'crfile': exc,
\ 'regex': s:regexp,
\ }] : [items, a:pat, a:limit, s:mmode(), s:ispath, exc, s:regexp]
let lines = call(s:matcher['match'], argms, s:matcher) let lines = call(s:matcher['match'], argms, s:matcher)
el el
let lines = s:MatchIt(items, a:pat, a:limit, exc) let lines = s:MatchIt(items, a:pat, a:limit, exc)
@ -480,7 +515,7 @@ fu! s:SplitPattern(str)
if exists('lst') if exists('lst')
let pat = '' let pat = ''
if !empty(lst) if !empty(lst)
if s:byfname && index(lst, ';') > 0 if s:byfname() && index(lst, ';') > 0
let fbar = index(lst, ';') let fbar = index(lst, ';')
let lst_1 = s:sublist(lst, 0, fbar - 1) let lst_1 = s:sublist(lst, 0, fbar - 1)
let lst_2 = len(lst) - 1 > fbar ? s:sublist(lst, fbar + 1, -1) : [''] let lst_2 = len(lst) - 1 > fbar ? s:sublist(lst, fbar + 1, -1) : ['']
@ -494,15 +529,19 @@ fu! s:SplitPattern(str)
endf endf
" * BuildPrompt() {{{1 " * BuildPrompt() {{{1
fu! s:Render(lines, pat) fu! s:Render(lines, pat)
let [&ma, lines, s:height] = [1, a:lines, min([len(a:lines), s:winh])] let [&ma, lines, s:res_count] = [1, a:lines, len(a:lines)]
let pat = s:byfname ? split(a:pat, '^[^;]\+\\\@<!\zs;', 1)[0] : a:pat let height = min([max([s:mw_min, s:res_count]), s:winmaxh])
let pat = s:byfname() ? split(a:pat, '^[^;]\+\\\@<!\zs;', 1)[0] : a:pat
let cur_cmd = 'keepj norm! '.( s:mw_order == 'btt' ? 'G' : 'gg' ).'1|'
" Setup the match window " Setup the match window
sil! exe '%d _ | res' s:height sil! exe '%d _ | res' height
" Print the new items " Print the new items
if empty(lines) if empty(lines)
let [s:matched, s:lines] = [[], []] let [s:matched, s:lines] = [[], []]
cal setline(1, ' == NO ENTRIES ==') let lines = [' == NO ENTRIES ==']
cal setline(1, s:offset(lines, height - 1))
setl noma nocul setl noma nocul
exe cur_cmd
cal s:unmarksigns() cal s:unmarksigns()
if s:dohighlight() | cal clearmatches() | en if s:dohighlight() | cal clearmatches() | en
retu retu
@ -514,12 +553,12 @@ fu! s:Render(lines, pat)
cal sort(lines, 's:mixedsort') cal sort(lines, 's:mixedsort')
unl s:compat unl s:compat
en en
if s:mwreverse | cal reverse(lines) | en if s:mw_order == 'btt' | cal reverse(lines) | en
let s:lines = copy(lines) let s:lines = copy(lines)
cal map(lines, 's:formatline(v:val)') cal map(lines, 's:formatline(v:val)')
cal setline(1, lines) cal setline(1, s:offset(lines, height))
setl noma cul setl noma cul
exe 'keepj norm!' ( s:mwreverse ? 'G' : 'gg' ).'1|' exe cur_cmd
cal s:unmarksigns() cal s:unmarksigns()
cal s:remarksigns() cal s:remarksigns()
if exists('s:cline') && s:nolim != 1 if exists('s:cline') && s:nolim != 1
@ -541,7 +580,7 @@ fu! s:Update(str)
let s:martcs = &scs && str =~ '\u' ? '\C' : '' let s:martcs = &scs && str =~ '\u' ? '\C' : ''
let pat = s:matcher == {} ? s:SplitPattern(str) : str let pat = s:matcher == {} ? s:SplitPattern(str) : str
let lines = s:nolim == 1 && empty(str) ? copy(g:ctrlp_lines) let lines = s:nolim == 1 && empty(str) ? copy(g:ctrlp_lines)
\ : s:MatchedItems(g:ctrlp_lines, pat, s:winh) \ : s:MatchedItems(g:ctrlp_lines, pat, s:mw_res)
cal s:Render(lines, pat) cal s:Render(lines, pat)
endf endf
@ -550,7 +589,7 @@ fu! s:ForceUpdate()
endf endf
fu! s:BuildPrompt(upd) fu! s:BuildPrompt(upd)
let base = ( s:regexp ? 'r' : '>' ).( s:byfname ? 'd' : '>' ).'> ' let base = ( s:regexp ? 'r' : '>' ).( s:byfname() ? 'd' : '>' ).'> '
let str = escape(s:getinput(), '\') let str = escape(s:getinput(), '\')
let lazy = str == '' || exists('s:force') || !has('autocmd') ? 0 : s:lazy let lazy = str == '' || exists('s:force') || !has('autocmd') ? 0 : s:lazy
if a:upd && !lazy && ( s:matches || s:regexp || exists('s:did_exp') if a:upd && !lazy && ( s:matches || s:regexp || exists('s:did_exp')
@ -581,11 +620,8 @@ fu! s:SetDefTxt()
if s:deftxt == '0' || ( s:deftxt == 1 && !s:ispath ) | retu | en if s:deftxt == '0' || ( s:deftxt == 1 && !s:ispath ) | retu | en
let txt = s:deftxt let txt = s:deftxt
if !type(txt) if !type(txt)
let txt = txt && !stridx(s:crfpath, s:dyncwd) let path = s:crfpath.s:lash(s:crfpath)
\ ? ctrlp#rmbasedir([s:crfpath])[0] : '' let txt = txt && !stridx(path, s:dyncwd) ? ctrlp#rmbasedir([path])[0] : ''
let txt = txt != '' ? txt.s:lash(s:crfpath) : ''
el
let txt = expand(txt, 1)
en en
let s:prompt[0] = txt let s:prompt[0] = txt
endf endf
@ -735,7 +771,7 @@ endf
fu! s:PrtSelectJump(char) fu! s:PrtSelectJump(char)
let lines = copy(s:lines) let lines = copy(s:lines)
if s:byfname if s:byfname()
cal map(lines, 'split(v:val, ''[\/]\ze[^\/]\+$'')[-1]') cal map(lines, 'split(v:val, ''[\/]\ze[^\/]\+$'')[-1]')
en en
" Cycle through matches, use s:jmpchr to store last jump " Cycle through matches, use s:jmpchr to store last jump
@ -904,6 +940,11 @@ fu! s:ToggleKeyLoop()
en en
endf endf
fu! s:ToggleMRURelative()
cal ctrlp#mrufiles#tgrel()
cal s:PrtClearCache()
endf
fu! s:PrtSwitcher() fu! s:PrtSwitcher()
let [s:force, s:matches] = [1, 1] let [s:force, s:matches] = [1, 1]
cal s:BuildPrompt(1) cal s:BuildPrompt(1)
@ -937,14 +978,21 @@ fu! s:SetWD(args)
en en
endf endf
" * AcceptSelection() {{{1 " * AcceptSelection() {{{1
fu! ctrlp#acceptfile(mode, line, ...) fu! ctrlp#acceptfile(...)
let [md, useb] = [a:mode, 0] let useb = 0
if !type(a:line) if a:0 == 1 && type(a:1) == 4
let [filpath, bufnr, useb] = [a:line, a:line, 1] let [md, line] = [a:1['action'], a:1['line']]
let atl = has_key(a:1, 'tail') ? a:1['tail'] : ''
el el
let filpath = fnamemodify(a:line, ':p') let [md, line] = [a:1, a:2]
if s:nonamecond(a:line, filpath) let atl = a:0 > 2 ? a:3 : ''
let bufnr = str2nr(matchstr(a:line, '[\/]\?\[\zs\d\+\ze\*No Name\]$')) en
if !type(line)
let [filpath, bufnr, useb] = [line, line, 1]
el
let filpath = fnamemodify(line, ':p')
if s:nonamecond(line, filpath)
let bufnr = str2nr(matchstr(line, '[\/]\?\[\zs\d\+\ze\*No Name\]$'))
let [filpath, useb] = [bufnr, 1] let [filpath, useb] = [bufnr, 1]
el el
let bufnr = bufnr('^'.filpath.'$') let bufnr = bufnr('^'.filpath.'$')
@ -952,7 +1000,7 @@ fu! ctrlp#acceptfile(mode, line, ...)
en en
cal s:PrtExit() cal s:PrtExit()
let tail = s:tail() let tail = s:tail()
let j2l = a:0 ? a:1 : matchstr(tail, '^ +\zs\d\+$') let j2l = atl != '' ? atl : matchstr(tail, '^ +\zs\d\+$')
if ( s:jmptobuf =~ md || ( s:jmptobuf && md =~ '[et]' ) ) && bufnr > 0 if ( s:jmptobuf =~ md || ( s:jmptobuf && md =~ '[et]' ) ) && bufnr > 0
\ && !( md == 'e' && bufnr == bufnr('%') ) \ && !( md == 'e' && bufnr == bufnr('%') )
let [jmpb, bufwinnr] = [1, bufwinnr(bufnr)] let [jmpb, bufwinnr] = [1, bufwinnr(bufnr)]
@ -980,7 +1028,7 @@ fu! ctrlp#acceptfile(mode, line, ...)
" Reset &switchbuf option " Reset &switchbuf option
let [swb, &swb] = [&swb, ''] let [swb, &swb] = [&swb, '']
" Open new window/buffer " Open new window/buffer
let [fid, tail] = [( useb ? bufnr : filpath ), ( a:0 ? ' +'.a:1 : tail )] let [fid, tail] = [( useb ? bufnr : filpath ), ( atl != '' ? ' +'.atl : tail )]
let args = [cmd, fid, tail, 1, [useb, j2l]] let args = [cmd, fid, tail, 1, [useb, j2l]]
cal call('s:openfile', args) cal call('s:openfile', args)
let &swb = swb let &swb = swb
@ -1011,24 +1059,34 @@ fu! s:SpecInputs(str)
retu 0 retu 0
endf endf
fu! s:AcceptSelection(mode) fu! s:AcceptSelection(action)
if a:mode != 'e' && s:OpenMulti(a:mode) != -1 | retu | en let [md, icr] = [a:action[0], match(a:action, 'r') >= 0]
let subm = icr || ( !icr && md == 'e' )
if !subm && s:OpenMulti(md) != -1 | retu | en
let str = s:getinput() let str = s:getinput()
if a:mode == 'e' | if s:SpecInputs(str) | retu | en | en if subm | if s:SpecInputs(str) | retu | en | en
" Get the selected line " Get the selected line
let line = ctrlp#getcline() let line = ctrlp#getcline()
if a:mode != 'e' && !s:itemtype && line == '' if !subm && !s:itemtype && line == '' && line('.') > s:offset
\ && str !~ '\v^(\.\.([\/]\.\.)*[\/]?[.\/]*|/|\\|\?|\@.+)$' \ && str !~ '\v^(\.\.([\/]\.\.)*[\/]?[.\/]*|/|\\|\?|\@.+)$'
cal s:CreateNewFile(a:mode) | retu cal s:CreateNewFile(md) | retu
en en
if empty(line) | retu | en if empty(line) | retu | en
" Do something with it " Do something with it
if s:openfunc != {} && has_key(s:openfunc, s:ctype) if s:openfunc != {} && has_key(s:openfunc, s:ctype)
let actfunc = s:openfunc[s:ctype] let actfunc = s:openfunc[s:ctype]
let type = has_key(s:openfunc, 'arg_type') ? s:openfunc['arg_type'] : 'list'
el el
let actfunc = s:itemtype < 3 ? 'ctrlp#acceptfile' : s:getextvar('accept') if s:itemtype < 3
let [actfunc, type] = ['ctrlp#acceptfile', 'dict']
el
let [actfunc, exttype] = [s:getextvar('accept'), s:getextvar('act_farg')]
let type = exttype == 'dict' ? exttype : 'list'
en en
cal call(actfunc, [a:mode, line]) en
let actargs = type == 'dict' ? [{ 'action': md, 'line': line, 'icr': icr }]
\ : [md, line]
cal call(actfunc, actargs)
endf endf
" - CreateNewFile() {{{1 " - CreateNewFile() {{{1
fu! s:CreateNewFile(...) fu! s:CreateNewFile(...)
@ -1187,7 +1245,10 @@ fu! s:OpenNoMarks(md, line)
cal s:remarksigns() cal s:remarksigns()
cal s:BuildPrompt(0) cal s:BuildPrompt(0)
elsei a:md == 'x' elsei a:md == 'x'
cal call(s:openfunc[s:ctype], [a:md, a:line], s:openfunc) let type = has_key(s:openfunc, 'arg_type') ? s:openfunc['arg_type'] : 'dict'
let argms = type == 'dict' ? [{ 'action': a:md, 'line': a:line }]
\ : [a:md, a:line]
cal call(s:openfunc[s:ctype], argms, s:openfunc)
elsei a:md == 'd' elsei a:md == 'd'
let dir = fnamemodify(a:line, ':h') let dir = fnamemodify(a:line, ':h')
if isdirectory(dir) if isdirectory(dir)
@ -1278,7 +1339,7 @@ fu! s:mixedsort(...)
let [cln, cml] = [ctrlp#complen(a:1, a:2), s:compmatlen(a:1, a:2)] let [cln, cml] = [ctrlp#complen(a:1, a:2), s:compmatlen(a:1, a:2)]
if s:ispath if s:ispath
let ms = [] let ms = []
if s:height < 21 if s:res_count < 21
let ms += [s:compfnlen(a:1, a:2)] let ms += [s:compfnlen(a:1, a:2)]
if s:itemtype !~ '^[12]$' | let ms += [s:comptime(a:1, a:2)] | en if s:itemtype !~ '^[12]$' | let ms += [s:comptime(a:1, a:2)] | en
if !s:itemtype | let ms += [s:comparent(a:1, a:2)] | en if !s:itemtype | let ms += [s:comparent(a:1, a:2)] | en
@ -1324,12 +1385,21 @@ fu! ctrlp#statusline()
let prv = tps[s:walker(max, s:itemtype, -1)][1] let prv = tps[s:walker(max, s:itemtype, -1)][1]
let s:ctype = tps[s:itemtype][0] let s:ctype = tps[s:itemtype][0]
let focus = s:focus ? 'prt' : 'win' let focus = s:focus ? 'prt' : 'win'
let byfname = s:byfname ? 'file' : 'path' let byfname = s:ispath ? s:byfname ? 'file' : 'path' : 'line'
let marked = s:opmul != '0' ? let marked = s:opmul != '0' ?
\ exists('s:marked') ? ' <'.s:dismrk().'>' : ' <->' : '' \ exists('s:marked') ? ' <'.s:dismrk().'>' : ' <->' : ''
if s:status != {} if s:status != {}
let args = [focus, byfname, s:regexp, prv, s:ctype, nxt, marked] let argms =
let &l:stl = call(s:status['main'], args, s:status) \ has_key(s:status, 'arg_type') && s:status['arg_type'] == 'dict' ? [{
\ 'focus': focus,
\ 'byfname': byfname,
\ 'regex': s:regexp,
\ 'prev': prv,
\ 'item': s:ctype,
\ 'next': nxt,
\ 'marked': marked,
\ }] : [focus, byfname, s:regexp, prv, s:ctype, nxt, marked]
let &l:stl = call(s:status['main'], argms, s:status)
el el
let item = '%#CtrlPMode1# '.s:ctype.' %*' let item = '%#CtrlPMode1# '.s:ctype.' %*'
let focus = '%#CtrlPMode2# '.focus.' %*' let focus = '%#CtrlPMode2# '.focus.' %*'
@ -1349,8 +1419,13 @@ endf
fu! ctrlp#progress(enum, ...) fu! ctrlp#progress(enum, ...)
if has('macunix') || has('mac') | sl 1m | en if has('macunix') || has('mac') | sl 1m | en
let txt = a:0 ? '(press ctrl-c to abort)' : '' let txt = a:0 ? '(press ctrl-c to abort)' : ''
let &l:stl = s:status != {} ? call(s:status['prog'], [a:enum], s:status) if s:status != {}
\ : '%#CtrlPStats# '.a:enum.' %* '.txt.'%=%<%#CtrlPMode2# %{getcwd()} %*' let argms = has_key(s:status, 'arg_type') && s:status['arg_type'] == 'dict'
\ ? [{ 'str': a:enum }] : [a:enum]
let &l:stl = call(s:status['prog'], argms, s:status)
el
let &l:stl = '%#CtrlPStats# '.a:enum.' %* '.txt.'%=%<%#CtrlPMode2# %{getcwd()} %*'
en
redraws redraws
endf endf
" *** Paths {{{2 " *** Paths {{{2
@ -1376,6 +1451,11 @@ fu! s:pathshorten(str)
retu matchstr(a:str, '^.\{9}').'...' retu matchstr(a:str, '^.\{9}').'...'
\ .matchstr(a:str, '.\{'.( s:winw - 16 ).'}$') \ .matchstr(a:str, '.\{'.( s:winw - 16 ).'}$')
endf endf
fu! s:offset(lines, height)
let s:offset = s:mw_order == 'btt' ? ( a:height - s:res_count ) : 0
retu s:offset > 0 ? ( repeat([''], s:offset) + a:lines ) : a:lines
endf
" Directory completion {{{3 " Directory completion {{{3
fu! s:dircompl(be, sd) fu! s:dircompl(be, sd)
if a:sd == '' | retu [] | en if a:sd == '' | retu [] | en
@ -1464,7 +1544,7 @@ fu! s:samerootsyml(each, isfile, cwd)
endf endf
fu! ctrlp#rmbasedir(items) fu! ctrlp#rmbasedir(items)
let cwd = s:dyncwd.( s:dyncwd !~ '[\/]$' ? s:lash : '' ) let cwd = s:dyncwd.s:lash()
if a:items != [] && !stridx(a:items[0], cwd) if a:items != [] && !stridx(a:items[0], cwd)
let idx = strlen(cwd) let idx = strlen(cwd)
retu map(a:items, 'strpart(v:val, idx)') retu map(a:items, 'strpart(v:val, idx)')
@ -1529,8 +1609,7 @@ endf
fu! ctrlp#syntax() fu! ctrlp#syntax()
if ctrlp#nosy() | retu | en if ctrlp#nosy() | retu | en
for [ke, va] in items(s:hlgrps) | cal ctrlp#hicheck('CtrlP'.ke, va) | endfo for [ke, va] in items(s:hlgrps) | cal ctrlp#hicheck('CtrlP'.ke, va) | endfo
if !hlexists('CtrlPLinePre') if synIDattr(synIDtrans(hlID('Normal')), 'bg') !~ '^-1$\|^$'
\ && synIDattr(synIDtrans(hlID('Normal')), 'bg') !~ '^-1$\|^$'
sil! exe 'hi CtrlPLinePre '.( has("gui_running") ? 'gui' : 'cterm' ).'fg=bg' sil! exe 'hi CtrlPLinePre '.( has("gui_running") ? 'gui' : 'cterm' ).'fg=bg'
en en
sy match CtrlPNoEntries '^ == NO ENTRIES ==$' sy match CtrlPNoEntries '^ == NO ENTRIES ==$'
@ -1599,6 +1678,18 @@ fu! s:dosigns()
retu exists('s:marked') && s:bufnr > 0 && s:opmul != '0' && has('signs') retu exists('s:marked') && s:bufnr > 0 && s:opmul != '0' && has('signs')
endf endf
" Lists & Dictionaries {{{2 " Lists & Dictionaries {{{2
fu! s:ifilter(list, str)
let [rlist, estr] = [[], substitute(a:str, 'v:val', 'each', 'g')]
for each in a:list
try
if eval(estr)
cal add(rlist, each)
en
cat | con | endt
endfo
retu rlist
endf
fu! s:dictindex(dict, expr) fu! s:dictindex(dict, expr)
for key in keys(a:dict) for key in keys(a:dict)
if a:dict[key] == a:expr | retu key | en if a:dict[key] == a:expr | retu key | en
@ -1808,7 +1899,6 @@ endf
fu! s:modevar() fu! s:modevar()
let s:matchtype = s:mtype() let s:matchtype = s:mtype()
let s:ispath = s:ispathitem() let s:ispath = s:ispathitem()
if !s:ispath | let s:byfname = 0 | en
let s:mfunc = s:mfunc() let s:mfunc = s:mfunc()
let s:nolim = s:getextvar('nolim') let s:nolim = s:getextvar('nolim')
let s:dosort = s:getextvar('sort') let s:dosort = s:getextvar('sort')
@ -1820,6 +1910,10 @@ fu! s:nosort()
\ || ( s:itemtype =~ '\v^(1|2)$' && s:prompt == ['', '', ''] ) || !s:dosort \ || ( s:itemtype =~ '\v^(1|2)$' && s:prompt == ['', '', ''] ) || !s:dosort
endf endf
fu! s:byfname()
retu s:ispath && s:byfname
endf
fu! s:narrowable() fu! s:narrowable()
retu exists('s:act_add') && exists('s:matched') && s:matched != [] retu exists('s:act_add') && exists('s:matched') && s:matched != []
\ && exists('s:mdata') && s:mdata[:2] == [s:dyncwd, s:itemtype, s:regexp] \ && exists('s:mdata') && s:mdata[:2] == [s:dyncwd, s:itemtype, s:regexp]
@ -1834,7 +1928,7 @@ fu! s:getinput(...)
if gmd =~ 't' && gmd =~ 'k' && !a:0 && matchstr(str, '.$') =~ '\k' if gmd =~ 't' && gmd =~ 'k' && !a:0 && matchstr(str, '.$') =~ '\k'
retu join(prt, '') retu join(prt, '')
en en
let [pf, rz] = [( s:byfname ? 'f' : 'p' ), ( s:regexp ? 'r' : 'z' )] let [pf, rz] = [( s:byfname() ? 'f' : 'p' ), ( s:regexp ? 'r' : 'z' )]
for dict in s:abbrev['abbrevs'] for dict in s:abbrev['abbrevs']
let dmd = has_key(dict, 'mode') ? dict['mode'] : '' let dmd = has_key(dict, 'mode') ? dict['mode'] : ''
let pat = escape(dict['pattern'], '~') let pat = escape(dict['pattern'], '~')
@ -1916,7 +2010,7 @@ fu! s:getenv()
let [s:cwd, s:winres] = [getcwd(), [winrestcmd(), &lines, winnr('$')]] let [s:cwd, s:winres] = [getcwd(), [winrestcmd(), &lines, winnr('$')]]
let [s:crword, s:crnbword] = [expand('<cword>', 1), expand('<cWORD>', 1)] let [s:crword, s:crnbword] = [expand('<cword>', 1), expand('<cWORD>', 1)]
let [s:crgfile, s:crline] = [expand('<cfile>', 1), getline('.')] let [s:crgfile, s:crline] = [expand('<cfile>', 1), getline('.')]
let [s:winh, s:crcursor] = [min([s:mxheight, &lines]), getpos('.')] let [s:winmaxh, s:crcursor] = [min([s:mw_max, &lines]), getpos('.')]
let [s:crbufnr, s:crvisual] = [bufnr('%'), s:lastvisual()] let [s:crbufnr, s:crvisual] = [bufnr('%'), s:lastvisual()]
let s:crfile = bufname('%') == '' let s:crfile = bufname('%') == ''
\ ? '['.s:crbufnr.'*No Name]' : expand('%:p', 1) \ ? '['.s:crbufnr.'*No Name]' : expand('%:p', 1)
@ -1939,7 +2033,8 @@ endf
fu! s:log(m) fu! s:log(m)
if exists('g:ctrlp_log') && g:ctrlp_log | if a:m if exists('g:ctrlp_log') && g:ctrlp_log | if a:m
let cadir = ctrlp#utils#cachedir() let cadir = ctrlp#utils#cachedir()
sil! exe 'redi! >' cadir.s:lash(cadir).'ctrlp.log' let apd = g:ctrlp_log > 1 ? '>' : ''
sil! exe 'redi! >'.apd cadir.s:lash(cadir).'ctrlp.log'
el el
sil! redi END sil! redi END
en | en en | en
@ -2023,7 +2118,7 @@ endf
fu! s:mfunc() fu! s:mfunc()
let mfunc = 'match' let mfunc = 'match'
if s:byfname && s:ispath if s:byfname()
let mfunc = 's:matchfname' let mfunc = 's:matchfname'
elsei s:itemtype > 2 elsei s:itemtype > 2
let matchtypes = { 'tabs': 's:matchtabs', 'tabe': 's:matchtabe' } let matchtypes = { 'tabs': 's:matchtabs', 'tabe': 's:matchtabe' }
@ -2102,7 +2197,9 @@ fu! s:getextvar(key)
endf endf
fu! ctrlp#getcline() fu! ctrlp#getcline()
retu !empty(s:lines) ? s:lines[line('.') - 1] : '' let [linenr, offset] = [line('.'), ( s:offset > 0 ? s:offset : 0 )]
retu !empty(s:lines) && !( offset && linenr <= offset )
\ ? s:lines[linenr - 1 - offset] : ''
endf endf
fu! ctrlp#getmarkedlist() fu! ctrlp#getmarkedlist()
@ -2134,6 +2231,10 @@ endf
fu! ctrlp#call(func, ...) fu! ctrlp#call(func, ...)
retu call(a:func, a:000) retu call(a:func, a:000)
endf endf
fu! ctrlp#getvar(var)
retu {a:var}
endf
"}}}1 "}}}1
" * Initialization {{{1 " * Initialization {{{1
fu! ctrlp#setlines(...) fu! ctrlp#setlines(...)

View file

@ -112,12 +112,12 @@ fu! ctrlp#bookmarkdir#accept(mode, str)
en en
endf endf
fu! ctrlp#bookmarkdir#add(dir) fu! ctrlp#bookmarkdir#add(dir, ...)
let str = 'Directory to bookmark: ' let str = 'Directory to bookmark: '
let cwd = a:dir != '' ? a:dir : s:getinput(str, getcwd(), 'dir') let cwd = a:dir != '' ? a:dir : s:getinput(str, getcwd(), 'dir')
if cwd == '' | retu | en if cwd == '' | retu | en
let cwd = fnamemodify(cwd, ':p') let cwd = fnamemodify(cwd, ':p')
let name = s:getinput('Bookmark as: ', cwd) let name = a:0 && a:1 != '' ? a:1 : s:getinput('Bookmark as: ', cwd)
if name == '' | retu | en if name == '' | retu | en
let name = tr(name, ' ', ' ') let name = tr(name, ' ', ' ')
cal s:savebookmark(name, cwd) cal s:savebookmark(name, cwd)

View file

@ -62,6 +62,7 @@ let s:types = {
\ 'lisp' : '%slisp%slisp%sf', \ 'lisp' : '%slisp%slisp%sf',
\ 'lua' : '%slua%slua%sf', \ 'lua' : '%slua%slua%sf',
\ 'make' : '%smake%smake%sm', \ 'make' : '%smake%smake%sm',
\ 'ocaml' : '%socaml%socaml%scmMvtfCre',
\ 'pascal' : '%spascal%spascal%sfp', \ 'pascal' : '%spascal%spascal%sfp',
\ 'perl' : '%sperl%sperl%sclps', \ 'perl' : '%sperl%sperl%sclps',
\ 'php' : '%sphp%sphp%scdvf', \ 'php' : '%sphp%sphp%scdvf',
@ -248,7 +249,9 @@ endf
fu! ctrlp#buffertag#cmd(mode, ...) fu! ctrlp#buffertag#cmd(mode, ...)
let s:btmode = a:mode let s:btmode = a:mode
if a:0 && !empty(a:1) if a:0 && !empty(a:1)
let s:bufname = fnamemodify(a:1, ':p') let s:btmode = 0
let bname = a:1 =~# '^%$\|^#\d*$' ? expand(a:1) : a:1
let s:bufname = fnamemodify(bname, ':p')
en en
retu s:id retu s:id
endf endf

View file

@ -83,7 +83,9 @@ endf
fu! ctrlp#changes#cmd(mode, ...) fu! ctrlp#changes#cmd(mode, ...)
let s:clmode = a:mode let s:clmode = a:mode
if a:0 && !empty(a:1) if a:0 && !empty(a:1)
let s:bufnr = bufnr('^'.fnamemodify(a:1, ':p').'$') let s:clmode = 0
let bname = a:1 =~# '^%$\|^#\d*$' ? expand(a:1) : a:1
let s:bufnr = bufnr('^'.fnamemodify(bname, ':p').'$')
en en
retu s:id retu s:id
endf endf

View file

@ -74,7 +74,7 @@ fu! ctrlp#dir#init(...)
endf endf
fu! ctrlp#dir#accept(mode, str) fu! ctrlp#dir#accept(mode, str)
let path = a:mode == 'h' ? getcwd() : s:cwd.ctrlp#utils#lash().a:str let path = a:mode == 'h' ? getcwd() : s:cwd.ctrlp#call('s:lash', s:cwd).a:str
if a:mode =~ 't\|v\|h' if a:mode =~ 't\|v\|h'
cal ctrlp#exit() cal ctrlp#exit()
en en

View file

@ -11,7 +11,7 @@ en
let g:loaded_ctrlp_line = 1 let g:loaded_ctrlp_line = 1
cal add(g:ctrlp_ext_vars, { cal add(g:ctrlp_ext_vars, {
\ 'init': 'ctrlp#line#init()', \ 'init': 'ctrlp#line#init(s:crbufnr)',
\ 'accept': 'ctrlp#line#accept', \ 'accept': 'ctrlp#line#accept',
\ 'lname': 'lines', \ 'lname': 'lines',
\ 'sname': 'lns', \ 'sname': 'lns',
@ -29,8 +29,9 @@ fu! s:syntax()
en en
endf endf
" Public {{{1 " Public {{{1
fu! ctrlp#line#init() fu! ctrlp#line#init(bufnr)
let [bufs, lines] = [ctrlp#buffers('id'), []] let [lines, bufnr] = [[], exists('s:bufnr') ? s:bufnr : a:bufnr]
let bufs = exists('s:lnmode') && s:lnmode ? ctrlp#buffers('id') : [bufnr]
for bufnr in bufs for bufnr in bufs
let [lfb, bufn] = [getbufline(bufnr, 1, '$'), bufname(bufnr)] let [lfb, bufn] = [getbufline(bufnr, 1, '$'), bufname(bufnr)]
if lfb == [] && bufn != '' if lfb == [] && bufn != ''
@ -57,7 +58,13 @@ fu! ctrlp#line#accept(mode, str)
en en
endf endf
fu! ctrlp#line#id() fu! ctrlp#line#cmd(mode, ...)
let s:lnmode = a:mode
if a:0 && !empty(a:1)
let s:lnmode = 0
let bname = a:1 =~# '^%$\|^#\d*$' ? expand(a:1) : a:1
let s:bufnr = bufnr('^'.fnamemodify(bname, ':p').'$')
en
retu s:id retu s:id
endf endf
"}}} "}}}

View file

@ -126,6 +126,10 @@ fu! ctrlp#mrufiles#bufs()
retu s:mrbs retu s:mrbs
endf endf
fu! ctrlp#mrufiles#tgrel()
let {s:re} = !{s:re}
endf
fu! ctrlp#mrufiles#cachefile() fu! ctrlp#mrufiles#cachefile()
if !exists('s:cadir') || !exists('s:cafile') if !exists('s:cadir') || !exists('s:cafile')
let s:cadir = ctrlp#utils#cachedir().ctrlp#utils#lash().'mru' let s:cadir = ctrlp#utils#cachedir().ctrlp#utils#lash().'mru'

View file

@ -22,32 +22,36 @@ cal add(g:ctrlp_ext_vars, {
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars) let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
" Utilities {{{1 " Utilities {{{1
fu! s:findcount(str) fu! s:findcount(str)
let [tg, fname] = split(a:str, '\t\+\ze[^\t]\+$') let [tg, ofname] = split(a:str, '\t\+\ze[^\t]\+$')
let tgs = taglist('^'.tg.'$') let tgs = taglist('^'.tg.'$')
if len(tgs) < 2 if len(tgs) < 2
retu [1, 1] retu [0, 0, 0, 0]
en en
let bname = fnamemodify(bufname('%'), ':p') let bname = fnamemodify(bufname('%'), ':p')
let fname = expand(fnamemodify(simplify(fname), ':s?^[.\/]\+??:p:.'), 1) let fname = expand(fnamemodify(simplify(ofname), ':s?^[.\/]\+??:p:.'), 1)
let [fnd, ct, pos, idx] = [0, 0, 0, 0] let [fnd, cnt, pos, ctgs, otgs] = [0, 0, 0, [], []]
wh idx < len(tgs) for tgi in tgs
if bname == fnamemodify(tgs[idx]["filename"], ':p') let lst = bname == fnamemodify(tgi["filename"], ':p') ? 'ctgs' : 'otgs'
cal insert(tgs, remove(tgs, idx)) cal call('add', [{lst}, tgi])
brea endfo
en let ntgs = ctgs + otgs
let idx += 1 for tgi in ntgs
endw let cnt += 1
for each in tgs let fulname = fnamemodify(tgi["filename"], ':p')
let ct += 1
let fulname = fnamemodify(each["filename"], ':p')
if stridx(fulname, fname) >= 0 if stridx(fulname, fname) >= 0
\ && strlen(fname) + stridx(fulname, fname) == strlen(fulname) \ && strlen(fname) + stridx(fulname, fname) == strlen(fulname)
let fnd += 1 let fnd += 1
let pos = ct let pos = cnt
en en
if fnd > 1 | brea | en
endfo endfo
retu [fnd, pos] let cnt = 0
for tgi in ntgs
let cnt += 1
if tgi["filename"] == ofname
let [fnd, pos] = [0, cnt]
en
endfo
retu [1, fnd, pos, len(ctgs)]
endf endf
fu! s:filter(tags) fu! s:filter(tags)
@ -89,27 +93,33 @@ endf
fu! ctrlp#tag#accept(mode, str) fu! ctrlp#tag#accept(mode, str)
cal ctrlp#exit() cal ctrlp#exit()
let str = matchstr(a:str, '^[^\t]\+\t\+[^\t]\+\ze\t') let str = matchstr(a:str, '^[^\t]\+\t\+[^\t]\+\ze\t')
let [tg, fnd] = [split(str, '^[^\t]\+\zs\t')[0], s:findcount(str)] let [tg, fdcnt] = [split(str, '^[^\t]\+\zs\t')[0], s:findcount(str)]
let cmds = { let cmds = {
\ 't': ['tab sp', 'tab stj'], \ 't': ['tab sp', 'tab stj'],
\ 'h': ['sp', 'stj'], \ 'h': ['sp', 'stj'],
\ 'v': ['vs', 'vert stj'], \ 'v': ['vs', 'vert stj'],
\ 'e': ['', 'tj'], \ 'e': ['', 'tj'],
\ } \ }
let cmd = fnd[0] == 1 ? cmds[a:mode][0] : cmds[a:mode][1] let utg = fdcnt[3] < 2 && fdcnt[0] == 1 && fdcnt[1] == 1
let cmd = !fdcnt[0] || utg ? cmds[a:mode][0] : cmds[a:mode][1]
let cmd = a:mode == 'e' && ctrlp#modfilecond(!&aw) let cmd = a:mode == 'e' && ctrlp#modfilecond(!&aw)
\ ? ( cmd == 'tj' ? 'stj' : 'sp' ) : cmd \ ? ( cmd == 'tj' ? 'stj' : 'sp' ) : cmd
let cmd = a:mode == 't' ? ctrlp#tabcount().cmd : cmd let cmd = a:mode == 't' ? ctrlp#tabcount().cmd : cmd
if fnd[0] == 1 if !fdcnt[0] || utg
if cmd != '' if cmd != ''
exe cmd exe cmd
en en
let save_cst = &cst let save_cst = &cst
set cst& set cst&
cal feedkeys(":".fnd[1]."ta ".tg."\r", 'nt') cal feedkeys(":".( utg ? fdcnt[2] : "" )."ta ".tg."\r", 'nt')
let &cst = save_cst let &cst = save_cst
el el
cal feedkeys(":".cmd." ".tg."\r", 'nt') let ext = ""
if fdcnt[1] < 2 && fdcnt[2]
let [sav_more, &more] = [&more, 0]
let ext = fdcnt[2]."\r".":let &more = ".sav_more."\r"
en
cal feedkeys(":".cmd." ".tg."\r".ext, 'nt')
en en
cal ctrlp#setlcdir() cal ctrlp#setlcdir()
endf endf

View file

@ -40,9 +40,7 @@ Overview:~
|ctrlp_cmd|...................Default command used for the default mapping. |ctrlp_cmd|...................Default command used for the default mapping.
|ctrlp_by_filename|...........Default to filename mode or not. |ctrlp_by_filename|...........Default to filename mode or not.
|ctrlp_regexp|................Default to regexp mode or not. |ctrlp_regexp|................Default to regexp mode or not.
|ctrlp_match_window_bottom|...Where to show the match window. |ctrlp_match_window|..........Order, height and position of the match window.
|ctrlp_match_window_reversed|.Sort order in the match window.
|ctrlp_max_height|............Max height of the match window.
|ctrlp_switch_buffer|.........Jump to an open buffer if already opened. |ctrlp_switch_buffer|.........Jump to an open buffer if already opened.
|ctrlp_reuse_window|..........Reuse special windows (help, quickfix, etc). |ctrlp_reuse_window|..........Reuse special windows (help, quickfix, etc).
|ctrlp_tabpage_position|......Where to put the new tab page. |ctrlp_tabpage_position|......Where to put the new tab page.
@ -77,6 +75,11 @@ Overview:~
|ctrlp_mruf_case_sensitive|...MRU files are case sensitive or not. |ctrlp_mruf_case_sensitive|...MRU files are case sensitive or not.
|ctrlp_mruf_save_on_update|...Save to disk whenever a new entry is added. |ctrlp_mruf_save_on_update|...Save to disk whenever a new entry is added.
BufferTag mode: (to enable, see |ctrlp-extensions|)
|g:ctrlp_buftag_ctags_bin|....The location of the ctags-compatible binary.
|g:ctrlp_buftag_systemenc|....The encoding used for the ctags command.
|g:ctrlp_buftag_types|........Add new filetypes and set the cmd arguments.
Advanced options: Advanced options:
|ctrlp_open_func|.............Use custom file opening functions. |ctrlp_open_func|.............Use custom file opening functions.
|ctrlp_status_func|...........Change CtrlP's two statuslines. |ctrlp_status_func|...........Change CtrlP's two statuslines.
@ -114,21 +117,30 @@ Set this to 1 to set regexp search as the default: >
< <
Can be toggled on/off by pressing <c-r> inside the prompt. Can be toggled on/off by pressing <c-r> inside the prompt.
*'g:ctrlp_match_window_bottom'* *'g:ctrlp_match_window'*
Set this to 0 to show the match window at the top of the screen: > Change the postion, the listing order of results, the minimum and the maximum
let g:ctrlp_match_window_bottom = 1 heights of the match window: >
let g:ctrlp_match_window = ''
< <
Example: >
let g:ctrlp_match_window = 'bottom,order:btt,min:1,max:10,results:10'
<
The position: (default: bottom)
top - show the match window at the top of the screen.
bottom - show the match window at the bottom of the screen.
*'g:ctrlp_match_window_reversed'* The listing order of results: (default: btt)
Change the listing order of the files in the match window. The default setting order:ttb - from top to bottom.
(1) is from bottom to top: > order:btt - from bottom to top.
let g:ctrlp_match_window_reversed = 1
<
*'g:ctrlp_max_height'* The minimum and maximum heights:
Set the maximum height of the match window: > min:{n} - show minimum {n} lines (default: 1).
let g:ctrlp_max_height = 10 max:{n} - show maximum {n} lines (default: 10).
<
The maximum number of results:
results:{n} - list maximum {n} results (default: sync with max height).
Note: When a setting isn't set, its default value will be used.
*'g:ctrlp_switch_buffer'* *'g:ctrlp_switch_buffer'*
When opening a file, if it's already open in a window somewhere, CtrlP will try When opening a file, if it's already open in a window somewhere, CtrlP will try
@ -323,18 +335,21 @@ Some examples: >
let g:ctrlp_user_command = ['.hg', 'for /f "tokens=1" %%a in (''hg root'') ' let g:ctrlp_user_command = ['.hg', 'for /f "tokens=1" %%a in (''hg root'') '
\ . 'do hg --cwd %s status -numac -I . %%a'] " Windows \ . 'do hg --cwd %s status -numac -I . %%a'] " Windows
< <
Note #1: if the fallback_command is empty or the 'fallback' key is not defined, Note #1: in the |Dictionary| format, 'fallback' and 'ignore' are optional. In
the |List| format, fallback_command is optional.
Note #2: if the fallback_command is empty or the 'fallback' key is not defined,
|globpath()| will then be used when scanning outside of a repository. |globpath()| will then be used when scanning outside of a repository.
Note #2: unless the |Dictionary| format is used and 'ignore' is defined and set Note #3: unless the |Dictionary| format is used and 'ignore' is defined and set
to 1, the |wildignore| and |g:ctrlp_custom_ignore| options do not apply when to 1, the |wildignore| and |g:ctrlp_custom_ignore| options do not apply when
these custom commands are being used. When not present, 'ignore' is set to 0 by these custom commands are being used. When not present, 'ignore' is set to 0 by
default to retain the performance advantage of using external commands. default to retain the performance advantage of using external commands.
Note #3: when changing the option's variable type, remember to |:unlet| it Note #4: when changing the option's variable type, remember to |:unlet| it
first or restart Vim to avoid the "E706: Variable type mismatch" error. first or restart Vim to avoid the "E706: Variable type mismatch" error.
Note #4: you can use a |b:var| to set this option on a per buffer basis. Note #5: you can use a |b:var| to set this option on a per buffer basis.
*'g:ctrlp_max_history'* *'g:ctrlp_max_history'*
The maximum number of input strings you want CtrlP to remember. The default The maximum number of input strings you want CtrlP to remember. The default
@ -563,6 +578,9 @@ Example: >
Set this to 1 to show only MRU files in the current working directory: > Set this to 1 to show only MRU files in the current working directory: >
let g:ctrlp_mruf_relative = 0 let g:ctrlp_mruf_relative = 0
< <
Note: you can use a custom mapping to toggle this option inside the prompt: >
let g:ctrlp_prompt_mappings = { 'ToggleMRURelative()': ['<F2>'] }
<
*'g:ctrlp_mruf_default_order'* *'g:ctrlp_mruf_default_order'*
Set this to 1 to disable sorting when searching in MRU mode: > Set this to 1 to disable sorting when searching in MRU mode: >
@ -734,6 +752,27 @@ Structure of the function: >
endfunction endfunction
< <
Note: you can extend any of the above options with { 'arg_type': 'dict' } to
enable passing all the function arguments in a single Dictionary argument. Use
the existing argument names as keys in this Dictionary.
Example: >
let g:ctrlp_status_func = {
\ 'arg_type' : 'dict',
\ 'enter': 'Function_Name_1',
\ 'exit': 'Function_Name_2',
\ }
function! Function_Name_1(dict)
" where dict == {
" \ 'focus': value,
" \ 'byfname': value,
" \ 'regex': value,
" \ ...
" }
endfunction
<
=============================================================================== ===============================================================================
COMMANDS *ctrlp-commands* COMMANDS *ctrlp-commands*
@ -1076,8 +1115,8 @@ Available extensions:~
*:CtrlPLine* *:CtrlPLine*
* Line mode:~ * Line mode:~
- Name: 'line' - Name: 'line'
- Command: ":CtrlPLine" - Command: ":CtrlPLine [buffer]"
- Search for a line in all listed buffers. - Search for a line in all listed buffers or in the specified [buffer].
*:CtrlPChange* *:CtrlPChange*
*:CtrlPChangeAll* *:CtrlPChangeAll*
@ -1164,7 +1203,7 @@ Highlighting:~
Statuslines:~ Statuslines:~
* Highlight groups: * Highlight groups:
CtrlPMode1 : 'file' or 'path', and the current mode (Character) CtrlPMode1 : 'file' or 'path' or 'line', and the current mode (Character)
CtrlPMode2 : 'prt' or 'win', 'regex', the working directory (|hl-LineNr|) CtrlPMode2 : 'prt' or 'win', 'regex', the working directory (|hl-LineNr|)
CtrlPStats : the scanning status (Function) CtrlPStats : the scanning status (Function)
@ -1249,10 +1288,16 @@ Special thanks:~
* Christopher Fredén <github.com/icetan> * Christopher Fredén <github.com/icetan>
* Zahary Karadjov <github.com/zah> * Zahary Karadjov <github.com/zah>
* Jo De Boeck <github.com/grimpy> * Jo De Boeck <github.com/grimpy>
* Rudi Grinberg <github.com/rgrinberg>
* Timothy Mellor <github.com/mellort>
=============================================================================== ===============================================================================
CHANGELOG *ctrlp-changelog* CHANGELOG *ctrlp-changelog*
+ Combine *g:ctrlp_match_window_bottom* *g:ctrlp_match_window_reversed* and
*g:ctrlp_max_height* into |g:ctrlp_match_window|.
+ New option: |g:ctrlp_match_window|.
Before 2012/11/30~ Before 2012/11/30~
+ New options: |g:ctrlp_abbrev|, + New options: |g:ctrlp_abbrev|,

View file

@ -51,7 +51,9 @@ com! -n=? -com=buffer CtrlPBufTag
com! -bar CtrlPBufTagAll cal ctrlp#init(ctrlp#buffertag#cmd(1)) com! -bar CtrlPBufTagAll cal ctrlp#init(ctrlp#buffertag#cmd(1))
com! -bar CtrlPRTS cal ctrlp#init(ctrlp#rtscript#id()) com! -bar CtrlPRTS cal ctrlp#init(ctrlp#rtscript#id())
com! -bar CtrlPUndo cal ctrlp#init(ctrlp#undo#id()) com! -bar CtrlPUndo cal ctrlp#init(ctrlp#undo#id())
com! -bar CtrlPLine cal ctrlp#init(ctrlp#line#id())
com! -n=? -com=buffer CtrlPLine
\ cal ctrlp#init(ctrlp#line#cmd(1, <q-args>))
com! -n=? -com=buffer CtrlPChange com! -n=? -com=buffer CtrlPChange
\ cal ctrlp#init(ctrlp#changes#cmd(0, <q-args>)) \ cal ctrlp#init(ctrlp#changes#cmd(0, <q-args>))

View file

@ -0,0 +1,384 @@
" Copyright (c) 2015 Junegunn Choi
"
" MIT License
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the
" "Software"), to deal in the Software without restriction, including
" without limitation the rights to use, copy, modify, merge, publish,
" distribute, sublicense, and/or sell copies of the Software, and to
" permit persons to whom the Software is furnished to do so, subject to
" the following conditions:
"
" The above copyright notice and this permission notice shall be
" included in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let s:cpo_save = &cpo
set cpo&vim
function! s:get_color(group, attr)
return synIDattr(synIDtrans(hlID(a:group)), a:attr)
endfunction
function! s:set_color(group, attr, color)
let gui = has('gui_running')
execute printf("hi %s %s%s=%s", a:group, gui ? 'gui' : 'cterm', a:attr, a:color)
endfunction
function! s:blank(repel)
if bufwinnr(t:goyo_pads.r) <= bufwinnr(t:goyo_pads.l) + 1
\ || bufwinnr(t:goyo_pads.b) <= bufwinnr(t:goyo_pads.t) + 3
call s:goyo_off()
endif
execute 'wincmd' a:repel
endfunction
function! s:init_pad(command)
execute a:command
setlocal buftype=nofile bufhidden=wipe nomodifiable nobuflisted noswapfile
\ nonu nocursorline nocursorcolumn winfixwidth winfixheight statusline=\
if exists('&rnu')
setlocal nornu
endif
if exists('&colorcolumn')
setlocal colorcolumn=
endif
let bufnr = winbufnr(0)
execute winnr('#') . 'wincmd w'
return bufnr
endfunction
function! s:setup_pad(bufnr, vert, size, repel)
let win = bufwinnr(a:bufnr)
execute win . 'wincmd w'
execute (a:vert ? 'vertical ' : '') . 'resize ' . max([0, a:size])
augroup goyop
execute 'autocmd WinEnter,CursorMoved <buffer> nested call s:blank("'.a:repel.'")'
autocmd WinLeave <buffer> call s:hide_statusline()
augroup END
" To hide scrollbars of pad windows in GVim
let diff = winheight(0) - line('$') - (has('gui_running') ? 2 : 0)
if diff > 0
setlocal modifiable
call append(0, map(range(1, diff), '""'))
normal! gg
setlocal nomodifiable
endif
execute winnr('#') . 'wincmd w'
endfunction
function! s:hmargin()
let nwidth = max([len(string(line('$'))) + 1, &numberwidth])
let width = t:goyo_width + (&number ? nwidth : 0)
return (&columns - width)
endfunction
function! s:resize_pads()
let t:goyo_width = max([2, t:goyo_width])
let t:goyo_margin_top = min([max([2, t:goyo_margin_top]), &lines / 2 - 1])
let t:goyo_margin_bottom = min([max([2, t:goyo_margin_bottom]), &lines / 2 - 1])
let hmargin = s:hmargin()
augroup goyop
autocmd!
augroup END
call s:setup_pad(t:goyo_pads.t, 0, t:goyo_margin_top - 1, 'j')
call s:setup_pad(t:goyo_pads.b, 0, t:goyo_margin_bottom - 2, 'k')
call s:setup_pad(t:goyo_pads.l, 1, hmargin / 2 - 1, 'l')
call s:setup_pad(t:goyo_pads.r, 1, hmargin / 2 - 1, 'h')
let t:goyo_width = winwidth(0)
endfunction
function! s:tranquilize()
let bg = s:get_color('Normal', 'bg')
for grp in ['NonText', 'FoldColumn', 'ColorColumn', 'VertSplit',
\ 'StatusLine', 'StatusLineNC', 'SignColumn']
" -1 on Vim / '' on GVim
if bg == -1 || empty(bg)
call s:set_color(grp, 'fg', get(g:, 'goyo_bg', 'black'))
call s:set_color(grp, 'bg', 'NONE')
else
call s:set_color(grp, 'fg', bg)
call s:set_color(grp, 'bg', bg)
endif
call s:set_color(grp, '', 'NONE')
endfor
endfunction
function! s:hide_statusline()
let &l:statusline = repeat(' ', winwidth(0))
endfunction
function! s:hide_linenr()
if !get(g:, 'goyo_linenr', 0)
setlocal nonu
if exists('&rnu')
setlocal nornu
endif
endif
if exists('&colorcolumn')
setlocal colorcolumn=
endif
endfunction
function! s:maps_nop()
let mapped = filter(['R', 'H', 'J', 'K', 'L', '|', '_'],
\ "empty(maparg(\"\<c-w>\".v:val, 'n'))")
for c in mapped
execute 'nnoremap <c-w>'.escape(c, '|').' <nop>'
endfor
return mapped
endfunction
function! s:maps_resize()
let commands = {
\ '=': ':<c-u>let [t:goyo_width, t:goyo_margin_top, t:goyo_margin_bottom] = t:goyo_initial_dim <bar> call <sid>resize_pads()<cr>',
\ '>': ':<c-u>let t:goyo_width = winwidth(0) + 2 * v:count1 <bar> call <sid>resize_pads()<cr>',
\ '<': ':<c-u>let t:goyo_width = winwidth(0) - 2 * v:count1 <bar> call <sid>resize_pads()<cr>',
\ '+': ':<c-u>let t:goyo_margin_top -= v:count1 <bar> let t:goyo_margin_bottom -= v:count1 <bar> call <sid>resize_pads()<cr>',
\ '-': ':<c-u>let t:goyo_margin_top += v:count1 <bar> let t:goyo_margin_bottom += v:count1 <bar> call <sid>resize_pads()<cr>'
\ }
let mapped = filter(keys(commands), "empty(maparg(\"\<c-w>\".v:val, 'n'))")
for c in mapped
execute 'nnoremap <silent> <c-w>'.c.' '.commands[c]
endfor
return mapped
endfunction
function! s:goyo_on(width)
let s:orig_tab = tabpagenr()
let settings =
\ { 'laststatus': &laststatus,
\ 'showtabline': &showtabline,
\ 'fillchars': &fillchars,
\ 'winminwidth': &winminwidth,
\ 'winwidth': &winwidth,
\ 'winminheight': &winminheight,
\ 'winheight': &winheight,
\ 'ruler': &ruler,
\ 'sidescroll': &sidescroll,
\ 'sidescrolloff': &sidescrolloff
\ }
" New tab
tab split
let t:goyo_master = winbufnr(0)
let t:goyo_width = a:width
let t:goyo_margin_top = get(g:, 'goyo_margin_top', 4)
let t:goyo_margin_bottom = get(g:, 'goyo_margin_bottom', 4)
let t:goyo_initial_dim = [t:goyo_width, t:goyo_margin_top, t:goyo_margin_bottom]
let t:goyo_pads = {}
let t:goyo_revert = settings
let t:goyo_maps = extend(s:maps_nop(), s:maps_resize())
if has('gui_running')
let t:goyo_revert.guioptions = &guioptions
endif
" vim-gitgutter
let t:goyo_disabled_gitgutter = get(g:, 'gitgutter_enabled', 0)
if t:goyo_disabled_gitgutter
silent! GitGutterDisable
endif
" vim-signify
let t:goyo_disabled_signify = exists('b:sy') && b:sy.active
if t:goyo_disabled_signify
SignifyToggle
endif
" vim-airline
let t:goyo_disabled_airline = exists("#airline")
if t:goyo_disabled_airline
AirlineToggle
endif
" vim-powerline
let t:goyo_disabled_powerline = exists("#PowerlineMain")
if t:goyo_disabled_powerline
augroup PowerlineMain
autocmd!
augroup END
augroup! PowerlineMain
endif
" lightline.vim
let t:goyo_disabled_lightline = exists('#LightLine')
if t:goyo_disabled_lightline
silent! call lightline#disable()
endif
call s:hide_linenr()
" Global options
let &winheight = max([&winminheight, 1])
set winminheight=1
set winheight=1
set winminwidth=1 winwidth=1
set laststatus=0
set showtabline=0
set noruler
set fillchars+=vert:\
set fillchars+=stl:.
set fillchars+=stlnc:\
set sidescroll=1
set sidescrolloff=0
" Hide left-hand scrollbars
if has('gui_running')
set guioptions-=l
set guioptions-=L
endif
let t:goyo_pads.l = s:init_pad('vertical topleft new')
let t:goyo_pads.r = s:init_pad('vertical botright new')
let t:goyo_pads.t = s:init_pad('topleft new')
let t:goyo_pads.b = s:init_pad('botright new')
call s:resize_pads()
call s:tranquilize()
augroup goyo
autocmd!
autocmd TabLeave * call s:goyo_off()
autocmd VimResized * call s:resize_pads()
autocmd ColorScheme * call s:tranquilize()
autocmd BufWinEnter * call s:hide_linenr() | call s:hide_statusline()
autocmd WinEnter,WinLeave * call s:hide_statusline()
augroup END
call s:hide_statusline()
if exists('g:goyo_callbacks[0]')
call g:goyo_callbacks[0]()
endif
silent! doautocmd User GoyoEnter
endfunction
function! s:goyo_off()
if !exists('#goyo')
return
endif
" Oops, not this tab
if !exists('t:goyo_revert')
return
endif
" Clear auto commands
augroup goyo
autocmd!
augroup END
augroup! goyo
augroup goyop
autocmd!
augroup END
augroup! goyop
for c in t:goyo_maps
execute 'nunmap <c-w>'.escape(c, '|')
endfor
let goyo_revert = t:goyo_revert
let goyo_disabled_gitgutter = t:goyo_disabled_gitgutter
let goyo_disabled_signify = t:goyo_disabled_signify
let goyo_disabled_airline = t:goyo_disabled_airline
let goyo_disabled_powerline = t:goyo_disabled_powerline
let goyo_disabled_lightline = t:goyo_disabled_lightline
let goyo_orig_buffer = t:goyo_master
let [line, col] = [line('.'), col('.')]
if tabpagenr() == 1
tabnew
normal! gt
bd
endif
tabclose
execute 'normal! '.s:orig_tab.'gt'
if winbufnr(0) == goyo_orig_buffer
" Doesn't work if window closed with `q`
execute printf('normal! %dG%d|', line, col)
endif
let wmw = remove(goyo_revert, 'winminwidth')
let ww = remove(goyo_revert, 'winwidth')
let &winwidth = ww
let &winminwidth = wmw
let wmh = remove(goyo_revert, 'winminheight')
let wh = remove(goyo_revert, 'winheight')
let &winheight = max([wmh, 1])
let &winminheight = wmh
let &winheight = wh
for [k, v] in items(goyo_revert)
execute printf("let &%s = %s", k, string(v))
endfor
execute 'colo '. get(g:, 'colors_name', 'default')
if goyo_disabled_gitgutter
silent! GitGutterEnable
endif
if goyo_disabled_signify
silent! if !b:sy.active
SignifyToggle
endif
endif
if goyo_disabled_airline && !exists("#airline")
AirlineToggle
silent! AirlineRefresh
endif
if goyo_disabled_powerline && !exists("#PowerlineMain")
doautocmd PowerlineStartup VimEnter
silent! PowerlineReloadColorscheme
endif
if goyo_disabled_lightline
silent! call lightline#enable()
endif
if exists('#Powerline')
doautocmd Powerline ColorScheme
endif
if exists('g:goyo_callbacks[1]')
call g:goyo_callbacks[1]()
endif
silent! doautocmd User GoyoLeave
endfunction
function! goyo#execute(bang, ...)
let width = a:0 > 0 ? a:1 : get(g:, 'goyo_width', 80)
if a:bang
if exists('#goyo')
call s:goyo_off()
endif
else
if exists('#goyo') == 0
call s:goyo_on(width)
elseif a:0 > 0
let t:goyo_width = width
call s:resize_pads()
else
call s:goyo_off()
end
end
endfunction
let &cpo = s:cpo_save
unlet s:cpo_save

View file

@ -0,0 +1,24 @@
" Copyright (c) 2015 Junegunn Choi
"
" MIT License
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the
" "Software"), to deal in the Software without restriction, including
" without limitation the rights to use, copy, modify, merge, publish,
" distribute, sublicense, and/or sell copies of the Software, and to
" permit persons to whom the Software is furnished to do so, subject to
" the following conditions:
"
" The above copyright notice and this permission notice shall be
" included in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
command! -nargs=? -bar -bang Goyo call goyo#execute(<bang>0, <args>)

View file

@ -60,7 +60,7 @@ Installation
cd ~/.vim/bundle cd ~/.vim/bundle
git clone https://github.com/scrooloose/nerdtree.git git clone https://github.com/scrooloose/nerdtree.git
Then reload vim, run `:helptags`, and check out `:help NERD_tree.txt`. Then reload vim, run `:Helptags`, and check out `:help NERD_tree.txt`.
Faq Faq
@ -80,11 +80,16 @@ A. Stick this in your vimrc: `autocmd vimenter * NERDTree`
__Q. How can I open a NERDTree automatically when vim starts up if no files were specified?__ __Q. How can I open a NERDTree automatically when vim starts up if no files were specified?__
A. Stick this in your vimrc `autocmd vimenter * if !argc() | NERDTree | endif` A. Stick this in your vimrc
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
__Q. How can I map a specific key or shortcut to open NERDTree?__ __Q. How can I map a specific key or shortcut to open NERDTree?__
A. Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want): `map <C-n> :NERDTreeToggle<CR>` A. Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want):
`map <C-n> :NERDTreeToggle<CR>`
__Q. How can I close vim if the only window left open is a NERDTree?__ __Q. How can I close vim if the only window left open is a NERDTree?__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,644 @@
if exists("g:loaded_nerdtree_ui_glue_autoload")
finish
endif
let g:loaded_nerdtree_ui_glue_autoload = 1
" FUNCTION: nerdtree#ui_glue#createDefaultBindings() {{{1
function! nerdtree#ui_glue#createDefaultBindings()
let s = '<SNR>' . s:SID() . '_'
call NERDTreeAddKeyMap({ 'key': '<MiddleRelease>', 'scope': "all", 'callback': s."handleMiddleMouse" })
call NERDTreeAddKeyMap({ 'key': '<LeftRelease>', 'scope': "all", 'callback': s."handleLeftClick" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "FileNode", 'callback': s."activateFileNode" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "Bookmark", 'callback': s."activateBookmark" })
call NERDTreeAddKeyMap({ 'key': '<2-LeftMouse>', 'scope': "all", 'callback': s."activateAll" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "DirNode", 'callback': s."activateDirNode" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "FileNode", 'callback': s."activateFileNode" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "Bookmark", 'callback': s."activateBookmark" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapActivateNode, 'scope': "all", 'callback': s."activateAll" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': "Node", 'callback': s."openHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': "Node", 'callback': s."openVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenSplit, 'scope': "Bookmark", 'callback': s."openHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenVSplit, 'scope': "Bookmark", 'callback': s."openVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': "Node", 'callback': s."previewNodeCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': "Node", 'callback': s."previewNodeVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': "Node", 'callback': s."previewNodeHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreview, 'scope': "Bookmark", 'callback': s."previewNodeCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewVSplit, 'scope': "Bookmark", 'callback': s."previewNodeVSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapPreviewSplit, 'scope': "Bookmark", 'callback': s."previewNodeHSplit" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenRecursively, 'scope': "DirNode", 'callback': s."openNodeRecursively" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdir, 'scope': "all", 'callback': s."upDirCurrentRootClosed" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapUpdirKeepOpen, 'scope': "all", 'callback': s."upDirCurrentRootOpen" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChangeRoot, 'scope': "Node", 'callback': s."chRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapChdir, 'scope': "Node", 'callback': s."chCwd" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapQuit, 'scope': "all", 'callback': s."closeTreeWindow" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCWD, 'scope': "all", 'callback': "nerdtree#ui_glue#chRootCwd" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefreshRoot, 'scope': "all", 'callback': s."refreshRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapRefresh, 'scope': "Node", 'callback': s."refreshCurrent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapHelp, 'scope': "all", 'callback': s."displayHelp" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleZoom, 'scope': "all", 'callback': s."toggleZoom" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleHidden, 'scope': "all", 'callback': s."toggleShowHidden" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFilters, 'scope': "all", 'callback': s."toggleIgnoreFilter" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleFiles, 'scope': "all", 'callback': s."toggleShowFiles" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapToggleBookmarks, 'scope': "all", 'callback': s."toggleShowBookmarks" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseDir, 'scope': "Node", 'callback': s."closeCurrentDir" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapCloseChildren, 'scope': "DirNode", 'callback': s."closeChildren" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapMenu, 'scope': "Node", 'callback': s."showMenu" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpParent, 'scope': "Node", 'callback': s."jumpToParent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpFirstChild, 'scope': "Node", 'callback': s."jumpToFirstChild" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpLastChild, 'scope': "Node", 'callback': s."jumpToLastChild" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpRoot, 'scope': "all", 'callback': s."jumpToRoot" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpNextSibling, 'scope': "Node", 'callback': s."jumpToNextSibling" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapJumpPrevSibling, 'scope': "Node", 'callback': s."jumpToPrevSibling" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Node", 'callback': s."openInNewTab" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Node", 'callback': s."openInNewTabSilent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTab, 'scope': "Bookmark", 'callback': s."openInNewTab" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenInTabSilent, 'scope': "Bookmark", 'callback': s."openInNewTabSilent" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapOpenExpl, 'scope': "DirNode", 'callback': s."openExplorer" })
call NERDTreeAddKeyMap({ 'key': g:NERDTreeMapDeleteBookmark, 'scope': "Bookmark", 'callback': s."deleteBookmark" })
endfunction
"SECTION: Interface bindings {{{1
"============================================================
"FUNCTION: s:activateAll() {{{1
"handle the user activating the updir line
function! s:activateAll()
if getline(".") ==# nerdtree#treeUpDirLine()
return nerdtree#ui_glue#upDir(0)
endif
endfunction
"FUNCTION: s:activateDirNode() {{{1
"handle the user activating a tree node
function! s:activateDirNode(node)
call a:node.activate({'reuse': 1})
endfunction
"FUNCTION: s:activateFileNode() {{{1
"handle the user activating a tree node
function! s:activateFileNode(node)
call a:node.activate({'reuse': 1, 'where': 'p'})
endfunction
"FUNCTION: s:activateBookmark() {{{1
"handle the user activating a bookmark
function! s:activateBookmark(bm)
call a:bm.activate(!a:bm.path.isDirectory ? {'where': 'p'} : {})
endfunction
" FUNCTION: nerdtree#ui_glue#bookmarkNode(name) {{{1
" Associate the current node with the given name
function! nerdtree#ui_glue#bookmarkNode(...)
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
let name = a:1
if empty(name)
let name = currentNode.path.getLastPathComponent(0)
endif
try
call currentNode.bookmark(name)
call b:NERDTree.render()
catch /^NERDTree.IllegalBookmarkNameError/
call nerdtree#echo("bookmark names must not contain spaces")
endtry
else
call nerdtree#echo("select a node first")
endif
endfunction
" FUNCTION: s:chCwd(node) {{{1
function! s:chCwd(node)
try
call a:node.path.changeToDir()
catch /^NERDTree.PathChangeError/
call nerdtree#echoWarning("could not change cwd")
endtry
endfunction
" FUNCTION: s:chRoot(node) {{{1
" changes the current root to the selected one
function! s:chRoot(node)
call a:node.makeRoot()
call b:NERDTree.render()
call b:NERDTreeRoot.putCursorHere(0, 0)
endfunction
" FUNCTION: s:nerdtree#ui_glue#chRootCwd() {{{1
" changes the current root to CWD
function! nerdtree#ui_glue#chRootCwd()
try
let cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("current directory does not exist.")
return
endtry
if cwd.str() == g:NERDTreeFileNode.GetRootForTab().path.str()
return
endif
call s:chRoot(g:NERDTreeDirNode.New(cwd))
endfunction
" FUNCTION: nnerdtree#ui_glue#clearBookmarks(bookmarks) {{{1
function! nerdtree#ui_glue#clearBookmarks(bookmarks)
if a:bookmarks ==# ''
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
call currentNode.clearBookmarks()
endif
else
for name in split(a:bookmarks, ' ')
let bookmark = g:NERDTreeBookmark.BookmarkFor(name)
call bookmark.delete()
endfor
endif
call b:NERDTree.render()
endfunction
" FUNCTION: s:closeChildren(node) {{{1
" closes all childnodes of the current node
function! s:closeChildren(node)
call a:node.closeChildren()
call b:NERDTree.render()
call a:node.putCursorHere(0, 0)
endfunction
" FUNCTION: s:closeCurrentDir(node) {{{1
" closes the parent dir of the current node
function! s:closeCurrentDir(node)
let parent = a:node.parent
if parent ==# {} || parent.isRoot()
call nerdtree#echo("cannot close tree root")
else
while g:NERDTreeCascadeOpenSingleChildDir && !parent.parent.isRoot()
if parent.parent.getVisibleChildCount() == 1
call parent.close()
let parent = parent.parent
else
break
endif
endwhile
call parent.close()
call b:NERDTree.render()
call parent.putCursorHere(0, 0)
endif
endfunction
" FUNCTION: s:closeTreeWindow() {{{1
" close the tree window
function! s:closeTreeWindow()
if b:NERDTreeType ==# "secondary" && b:NERDTreePreviousBuf != -1
exec "buffer " . b:NERDTreePreviousBuf
else
if winnr("$") > 1
call nerdtree#closeTree()
else
call nerdtree#echo("Cannot close last window")
endif
endif
endfunction
" FUNCTION: s:deleteBookmark(bm) {{{1
" if the cursor is on a bookmark, prompt to delete
function! s:deleteBookmark(bm)
echo "Are you sure you wish to delete the bookmark:\n\"" . a:bm.name . "\" (yN):"
if nr2char(getchar()) ==# 'y'
try
call a:bm.delete()
call b:NERDTree.render()
redraw
catch /^NERDTree/
call nerdtree#echoWarning("Could not remove bookmark")
endtry
else
call nerdtree#echo("delete aborted" )
endif
endfunction
" FUNCTION: s:displayHelp() {{{1
" toggles the help display
function! s:displayHelp()
let b:treeShowHelp = b:treeShowHelp ? 0 : 1
call b:NERDTree.render()
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:findAndRevealPath() {{{1
function! s:findAndRevealPath()
try
let p = g:NERDTreePath.New(expand("%:p"))
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("no file for the current buffer")
return
endtry
if p.isUnixHiddenPath()
let showhidden=g:NERDTreeShowHidden
let g:NERDTreeShowHidden = 1
endif
if !g:NERDTree.ExistsForTab()
try
let cwd = g:NERDTreePath.New(getcwd())
catch /^NERDTree.InvalidArgumentsError/
call nerdtree#echo("current directory does not exist.")
let cwd = p.getParent()
endtry
if p.isUnder(cwd)
call g:NERDTreeCreator.CreatePrimary(cwd.str())
else
call g:NERDTreeCreator.CreatePrimary(p.getParent().str())
endif
else
if !p.isUnder(g:NERDTreeFileNode.GetRootForTab().path)
if !nerdtree#isTreeOpen()
call g:NERDTreeCreator.TogglePrimary('')
else
call nerdtree#putCursorInTreeWin()
endif
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
call s:chRoot(g:NERDTreeDirNode.New(p.getParent()))
else
if !nerdtree#isTreeOpen()
call g:NERDTreeCreator.TogglePrimary("")
endif
endif
endif
call nerdtree#putCursorInTreeWin()
call b:NERDTreeRoot.reveal(p)
if p.isUnixHiddenFile()
let g:NERDTreeShowHidden = showhidden
endif
endfunction
"FUNCTION: s:handleLeftClick() {{{1
"Checks if the click should open the current node
function! s:handleLeftClick()
let currentNode = g:NERDTreeFileNode.GetSelected()
if currentNode != {}
"the dir arrows are multibyte chars, and vim's string functions only
"deal with single bytes - so split the line up with the hack below and
"take the line substring manually
let line = split(getline(line(".")), '\zs')
let startToCur = ""
for i in range(0,len(line)-1)
let startToCur .= line[i]
endfor
if currentNode.path.isDirectory
if startToCur =~# nerdtree#treeMarkupReg() && startToCur =~# '[+~▾▸] \?$'
call currentNode.activate()
return
endif
endif
if (g:NERDTreeMouseMode ==# 2 && currentNode.path.isDirectory) || g:NERDTreeMouseMode ==# 3
let char = strpart(startToCur, strlen(startToCur)-1, 1)
if char !~# nerdtree#treeMarkupReg()
if currentNode.path.isDirectory
call currentNode.activate()
else
call currentNode.activate({'reuse': 1, 'where': 'p'})
endif
return
endif
endif
endif
endfunction
" FUNCTION: s:handleMiddleMouse() {{{1
function! s:handleMiddleMouse()
let curNode = g:NERDTreeFileNode.GetSelected()
if curNode ==# {}
call nerdtree#echo("Put the cursor on a node first" )
return
endif
if curNode.path.isDirectory
call nerdtree#openExplorer(curNode)
else
call curNode.open({'where': 'h'})
endif
endfunction
" FUNCTION: s:jumpToChild(direction) {{{2
" Args:
" direction: 0 if going to first child, 1 if going to last
function! s:jumpToChild(currentNode, direction)
if a:currentNode.isRoot()
return nerdtree#echo("cannot jump to " . (a:direction ? "last" : "first") . " child")
end
let dirNode = a:currentNode.parent
let childNodes = dirNode.getVisibleChildren()
let targetNode = childNodes[0]
if a:direction
let targetNode = childNodes[len(childNodes) - 1]
endif
if targetNode.equals(a:currentNode)
let siblingDir = a:currentNode.parent.findOpenDirSiblingWithVisibleChildren(a:direction)
if siblingDir != {}
let indx = a:direction ? siblingDir.getVisibleChildCount()-1 : 0
let targetNode = siblingDir.getChildByIndex(indx, 1)
endif
endif
call targetNode.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: nerdtree#ui_glue#invokeKeyMap(key) {{{1
"this is needed since I cant figure out how to invoke dict functions from a
"key map
function! nerdtree#ui_glue#invokeKeyMap(key)
call g:NERDTreeKeyMap.Invoke(a:key)
endfunction
" FUNCTION: s:jumpToFirstChild() {{{1
" wrapper for the jump to child method
function! s:jumpToFirstChild(node)
call s:jumpToChild(a:node, 0)
endfunction
" FUNCTION: s:jumpToLastChild() {{{1
" wrapper for the jump to child method
function! s:jumpToLastChild(node)
call s:jumpToChild(a:node, 1)
endfunction
" FUNCTION: s:jumpToParent(node) {{{1
" moves the cursor to the parent of the current node
function! s:jumpToParent(node)
if !empty(a:node.parent)
call a:node.parent.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
else
call nerdtree#echo("cannot jump to parent")
endif
endfunction
" FUNCTION: s:jumpToRoot() {{{1
" moves the cursor to the root node
function! s:jumpToRoot()
call b:NERDTreeRoot.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:jumpToNextSibling(node) {{{1
function! s:jumpToNextSibling(node)
call s:jumpToSibling(a:node, 1)
endfunction
" FUNCTION: s:jumpToPrevSibling(node) {{{1
function! s:jumpToPrevSibling(node)
call s:jumpToSibling(a:node, 0)
endfunction
" FUNCTION: s:jumpToSibling(currentNode, forward) {{{2
" moves the cursor to the sibling of the current node in the given direction
"
" Args:
" forward: 1 if the cursor should move to the next sibling, 0 if it should
" move back to the previous sibling
function! s:jumpToSibling(currentNode, forward)
let sibling = a:currentNode.findSibling(a:forward)
if !empty(sibling)
call sibling.putCursorHere(1, 0)
call b:NERDTree.ui.centerView()
endif
endfunction
" FUNCTION: nerdtree#ui_glue#openBookmark(name) {{{1
" put the cursor on the given bookmark and, if its a file, open it
function! nerdtree#ui_glue#openBookmark(name)
try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0)
call targetNode.putCursorHere(0, 1)
redraw!
catch /^NERDTree.BookmarkedNodeNotFoundError/
call nerdtree#echo("note - target node is not cached")
let bookmark = g:NERDTreeBookmark.BookmarkFor(a:name)
let targetNode = g:NERDTreeFileNode.New(bookmark.path)
endtry
if targetNode.path.isDirectory
call targetNode.openExplorer()
else
call targetNode.open({'where': 'p'})
endif
endfunction
" FUNCTION: s:openHSplit(target) {{{1
function! s:openHSplit(target)
call a:target.activate({'where': 'h'})
endfunction
" FUNCTION: s:openVSplit(target) {{{1
function! s:openVSplit(target)
call a:target.activate({'where': 'v'})
endfunction
" FUNCTION: s:openExplorer(node) {{{1
function! s:openExplorer(node)
call a:node.openExplorer()
endfunction
" FUNCTION: s:openInNewTab(target) {{{1
function! s:openInNewTab(target)
call a:target.activate({'where': 't'})
endfunction
" FUNCTION: s:openInNewTabSilent(target) {{{1
function! s:openInNewTabSilent(target)
call a:target.activate({'where': 't', 'stay': 1})
endfunction
" FUNCTION: s:openNodeRecursively(node) {{{1
function! s:openNodeRecursively(node)
call nerdtree#echo("Recursively opening node. Please wait...")
call a:node.openRecursively()
call b:NERDTree.render()
redraw
call nerdtree#echo("Recursively opening node. Please wait... DONE")
endfunction
"FUNCTION: s:previewNodeCurrent(node) {{{1
function! s:previewNodeCurrent(node)
call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeHSplit(node) {{{1
function! s:previewNodeHSplit(node)
call a:node.open({'stay': 1, 'where': 'h', 'keepopen': 1})
endfunction
"FUNCTION: s:previewNodeVSplit(node) {{{1
function! s:previewNodeVSplit(node)
call a:node.open({'stay': 1, 'where': 'v', 'keepopen': 1})
endfunction
" FUNCTION: nerdtree#ui_glue#revealBookmark(name) {{{1
" put the cursor on the node associate with the given name
function! nerdtree#ui_glue#revealBookmark(name)
try
let targetNode = g:NERDTreeBookmark.GetNodeForName(a:name, 0)
call targetNode.putCursorHere(0, 1)
catch /^NERDTree.BookmarkNotFoundError/
call nerdtree#echo("Bookmark isnt cached under the current root")
endtry
endfunction
" FUNCTION: s:refreshRoot() {{{1
" Reloads the current root. All nodes below this will be lost and the root dir
" will be reloaded.
function! s:refreshRoot()
call nerdtree#echo("Refreshing the root node. This could take a while...")
call b:NERDTreeRoot.refresh()
call b:NERDTree.render()
redraw
call nerdtree#echo("Refreshing the root node. This could take a while... DONE")
endfunction
" FUNCTION: s:refreshCurrent(node) {{{1
" refreshes the root for the current node
function! s:refreshCurrent(node)
let node = a:node
if !node.path.isDirectory
let node = node.parent
endif
call nerdtree#echo("Refreshing node. This could take a while...")
call node.refresh()
call b:NERDTree.render()
redraw
call nerdtree#echo("Refreshing node. This could take a while... DONE")
endfunction
" FUNCTION: nerdtree#ui_glue#setupCommands() {{{1
function! nerdtree#ui_glue#setupCommands()
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.TogglePrimary('<args>')
command! -n=0 -bar NERDTreeClose :call nerdtree#closeTreeIfOpen()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=0 -bar NERDTreeFind call s:findAndRevealPath()
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
endfunction
" Function: s:SID() {{{1
function s:SID()
if !exists("s:sid")
let s:sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endif
return s:sid
endfun
" FUNCTION: s:showMenu(node) {{{1
function! s:showMenu(node)
let mc = g:NERDTreeMenuController.New(g:NERDTreeMenuItem.AllEnabled())
call mc.showMenu()
endfunction
" FUNCTION: s:toggleIgnoreFilter() {{{1
function! s:toggleIgnoreFilter()
call b:NERDTree.ui.toggleIgnoreFilter()
endfunction
" FUNCTION: s:toggleShowBookmarks() {{{1
function! s:toggleShowBookmarks()
call b:NERDTree.ui.toggleShowBookmarks()
endfunction
" FUNCTION: s:toggleShowFiles() {{{1
function! s:toggleShowFiles()
call b:NERDTree.ui.toggleShowFiles()
endfunction
" FUNCTION: s:toggleShowHidden() {{{1
" toggles the display of hidden files
function! s:toggleShowHidden()
call b:NERDTree.ui.toggleShowHidden()
endfunction
" FUNCTION: s:toggleZoom() {{{1
function! s:toggleZoom()
call b:NERDTree.ui.toggleZoom()
endfunction
"FUNCTION: nerdtree#ui_glue#upDir(keepState) {{{1
"moves the tree up a level
"
"Args:
"keepState: 1 if the current root should be left open when the tree is
"re-rendered
function! nerdtree#ui_glue#upDir(keepState)
let cwd = b:NERDTreeRoot.path.str({'format': 'UI'})
if cwd ==# "/" || cwd =~# '^[^/]..$'
call nerdtree#echo("already at top dir")
else
if !a:keepState
call b:NERDTreeRoot.close()
endif
let oldRoot = b:NERDTreeRoot
if empty(b:NERDTreeRoot.parent)
let path = b:NERDTreeRoot.path.getParent()
let newRoot = g:NERDTreeDirNode.New(path)
call newRoot.open()
call newRoot.transplantChild(b:NERDTreeRoot)
let b:NERDTreeRoot = newRoot
else
let b:NERDTreeRoot = b:NERDTreeRoot.parent
endif
if g:NERDTreeChDirMode ==# 2
call b:NERDTreeRoot.path.changeToDir()
endif
call b:NERDTree.render()
call oldRoot.putCursorHere(0, 0)
endif
endfunction
" FUNCTION: s:upDirCurrentRootOpen() {{{1
function! s:upDirCurrentRootOpen()
call nerdtree#ui_glue#upDir(1)
endfunction
" FUNCTION: s:upDirCurrentRootClosed() {{{1
function! s:upDirCurrentRootClosed()
call nerdtree#ui_glue#upDir(0)
endfunction
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -109,7 +109,7 @@ The following features and functionality are provided by the NERD tree:
< <
:NERDTreeFromBookmark <bookmark> *:NERDTreeFromBookmark* :NERDTreeFromBookmark <bookmark> *:NERDTreeFromBookmark*
Opens a fresh NERD tree with the root initialized to the dir for Opens a fresh NERD tree with the root initialized to the dir for
<bookmark>. This only reason to use this command over :NERDTree is for <bookmark>. The only reason to use this command over :NERDTree is for
the completion (which is for bookmarks rather than directories). the completion (which is for bookmarks rather than directories).
:NERDTreeToggle [<start-directory> | <bookmark>] *:NERDTreeToggle* :NERDTreeToggle [<start-directory> | <bookmark>] *:NERDTreeToggle*
@ -160,7 +160,7 @@ click bookmarks or use the |NERDTree-o| mapping to activate them. See also,
Note that the following commands are only available in the NERD tree buffer. Note that the following commands are only available in the NERD tree buffer.
:Bookmark <name> :Bookmark [<name>]
Bookmark the current node as <name>. If there is already a <name> Bookmark the current node as <name>. If there is already a <name>
bookmark, it is overwritten. <name> must not contain spaces. bookmark, it is overwritten. <name> must not contain spaces.
If <name> is not provided, it defaults to the file or directory name. If <name> is not provided, it defaults to the file or directory name.
@ -358,7 +358,7 @@ Default key: O
Map option: NERDTreeMapOpenRecursively Map option: NERDTreeMapOpenRecursively
Applies to: directories. Applies to: directories.
Recursively opens the selelected directory. Recursively opens the selected directory.
All files and directories are cached, but if a directory would not be All files and directories are cached, but if a directory would not be
displayed due to file filters (see |'NERDTreeIgnore'| |NERDTree-f|) or the displayed due to file filters (see |'NERDTreeIgnore'| |NERDTree-f|) or the
@ -462,8 +462,8 @@ Jump to the previous sibling of the selected node.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*NERDTree-C* *NERDTree-C*
Default key: C Default key: C
Map option: NERDTreeMapChdir Map option: NERDTreeMapChangeRoot
Applies to: directories. Applies to: files and directories.
Make the selected directory node the new tree root. If a file is selected, its Make the selected directory node the new tree root. If a file is selected, its
parent is used. parent is used.
@ -609,17 +609,19 @@ NERD tree. These options should be set in your vimrc.
|'loaded_nerd_tree'| Turns off the script. |'loaded_nerd_tree'| Turns off the script.
|'NERDChristmasTree'| Tells the NERD tree to make itself colourful
and pretty.
|'NERDTreeAutoCenter'| Controls whether the NERD tree window centers |'NERDTreeAutoCenter'| Controls whether the NERD tree window centers
when the cursor moves within a specified when the cursor moves within a specified
distance to the top/bottom of the window. distance to the top/bottom of the window.
|'NERDTreeAutoCenterThreshold'| Controls the sensitivity of autocentering. |'NERDTreeAutoCenterThreshold'| Controls the sensitivity of autocentering.
|'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case |'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case
sensitive or not when sorting nodes. sensitive or not when sorting nodes.
|'NERDTreeSortHiddenFirst'| Tells the NERD tree whether to take the dot
at the beginning of the hidden file names
into account when sorting nodes.
|'NERDTreeChDirMode'| Tells the NERD tree if/when it should change |'NERDTreeChDirMode'| Tells the NERD tree if/when it should change
vim's current working directory. vim's current working directory.
@ -631,8 +633,13 @@ NERD tree. These options should be set in your vimrc.
|'NERDTreeIgnore'| Tells the NERD tree which files to ignore. |'NERDTreeIgnore'| Tells the NERD tree which files to ignore.
|'NERDTreeRespectWildIgnore'| Tells the NERD tree to respect |'wildignore'|.
|'NERDTreeBookmarksFile'| Where the bookmarks are stored. |'NERDTreeBookmarksFile'| Where the bookmarks are stored.
|'NERDTreeBookmarksSort'| Whether the bookmarks list is sorted on
display.
|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse |'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse
clicks. clicks.
@ -667,8 +674,8 @@ NERD tree. These options should be set in your vimrc.
|'NERDTreeDirArrows'| Tells the NERD tree to use arrows instead of |'NERDTreeDirArrows'| Tells the NERD tree to use arrows instead of
+ ~ chars when displaying directories. + ~ chars when displaying directories.
|'NERDTreeCasadeOpenSingleChildDir'| |'NERDTreeCascadeOpenSingleChildDir'|
Casade open while selected directory has only Cascade open while selected directory has only
one child that also is a directory. one child that also is a directory.
|'NERDTreeAutoDeleteBuffer'| Tells the NERD tree to automatically remove |'NERDTreeAutoDeleteBuffer'| Tells the NERD tree to automatically remove
@ -686,15 +693,6 @@ If this plugin is making you feel homicidal, it may be a good idea to turn it
off with this line in your vimrc: > off with this line in your vimrc: >
let loaded_nerd_tree=1 let loaded_nerd_tree=1
< <
------------------------------------------------------------------------------
*'NERDChristmasTree'*
Values: 0 or 1.
Default: 1.
If this option is set to 1 then some extra syntax highlighting elements are
added to the nerd tree to make it more colourful.
Set it to 0 for a more vanilla looking tree.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*'NERDTreeAutoCenter'* *'NERDTreeAutoCenter'*
@ -817,6 +815,13 @@ line: >
The file filters can be turned on and off dynamically with the |NERDTree-f| The file filters can be turned on and off dynamically with the |NERDTree-f|
mapping. mapping.
------------------------------------------------------------------------------
*'NERDTreeRespectWildIgnore'*
Values: 0 or 1.
Default: 0.
If set to 1, the |'wildignore'| setting is respected.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*'NERDTreeBookmarksFile'* *'NERDTreeBookmarksFile'*
Values: a path Values: a path
@ -824,6 +829,14 @@ Default: $HOME/.NERDTreeBookmarks
This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. This is where bookmarks are saved. See |NERDTreeBookmarkCommands|.
------------------------------------------------------------------------------
*'NERDTreeBookmarksSort'*
Values: 0 or 1
Default: 1
If set to 0 then the bookmarks list is not sorted.
If set to 1 the bookmarks list is sorted.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*'NERDTreeMouseMode'* *'NERDTreeMouseMode'*
Values: 1, 2 or 3. Values: 1, 2 or 3.
@ -987,16 +1000,17 @@ option: >
< <
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*'NERDTreeCasadeOpenSingleChildDir'* *'NERDTreeCascadeOpenSingleChildDir'*
Values: 0 or 1 Values: 0 or 1
Default: 1. Default: 1.
When opening dir nodes, this option tells NERDTree to recursively open dirs When opening dir nodes, this option tells NERDTree to recursively open dirs
that have only one child which is also a dir. NERDTree will stop when it finds that have only one child which is also a dir. NERDTree will stop when it finds
a dir that contains anything but another single dir. This option may be useful a dir that contains anything but another single dir. This option also causes
for Java projects. Use one of the follow lines to set this option: > the |NERDTree-x| mapping to close dirs in the same manner. This option may be
let NERDTreeCasadeOpenSingleChildDir=0 useful for Java projects. Use one of the follow lines to set this option: >
let NERDTreeCasadeOpenSingleChildDir=1 let NERDTreeCascadeOpenSingleChildDir=0
let NERDTreeCascadeOpenSingleChildDir=1
< <
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -1046,6 +1060,9 @@ NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()*
"callback" - the function the new mapping will be bound to "callback" - the function the new mapping will be bound to
"quickhelpText" - the text that will appear in the quickhelp (see "quickhelpText" - the text that will appear in the quickhelp (see
|NERDTree-?|) |NERDTree-?|)
"override" - if 1 then this new mapping will override whatever previous
mapping was defined for the key/scope combo. Useful for overriding the
default mappings.
Additionally, a "scope" argument may be supplied. This constrains the Additionally, a "scope" argument may be supplied. This constrains the
mapping so that it is only activated if the cursor is on a certain object. mapping so that it is only activated if the cursor is on a certain object.
@ -1062,8 +1079,8 @@ NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()*
call NERDTreeAddKeyMap({ call NERDTreeAddKeyMap({
\ 'key': 'foo', \ 'key': 'foo',
\ 'callback': 'NERDTreeCDHandler', \ 'callback': 'NERDTreeCDHandler',
\ 'quickhelpText': 'echo full path of current node' }) \ 'quickhelpText': 'echo full path of current node',
\ 'scope': 'DirNode' \ 'scope': 'DirNode' })
function! NERDTreeCDHandler(dirnode) function! NERDTreeCDHandler(dirnode)
call a:dirnode.changeToDir() call a:dirnode.changeToDir()

View file

@ -19,7 +19,9 @@ function! s:Bookmark.AddBookmark(name, path)
endif endif
endfor endfor
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path)) call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort() call s:Bookmark.Sort()
endif
endfunction endfunction
" FUNCTION: Bookmark.Bookmarks() {{{1 " FUNCTION: Bookmark.Bookmarks() {{{1
@ -101,8 +103,10 @@ function! s:Bookmark.CacheBookmarks(silent)
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.") call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
endif endif
endif endif
if g:NERDTreeBookmarksSort ==# 1
call s:Bookmark.Sort() call s:Bookmark.Sort()
endif endif
endif
endfunction endfunction
" FUNCTION: Bookmark.compareTo(otherbookmark) {{{1 " FUNCTION: Bookmark.compareTo(otherbookmark) {{{1
@ -271,7 +275,7 @@ function! s:Bookmark.toRoot()
let targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path) let targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path)
endtry endtry
call targetNode.makeRoot() call targetNode.makeRoot()
call nerdtree#renderView() call b:NERDTree.render()
call targetNode.putCursorHere(0, 0) call targetNode.putCursorHere(0, 0)
endif endif
endfunction endfunction
@ -289,7 +293,7 @@ function! s:Bookmark.validate()
return 1 return 1
else else
call s:Bookmark.CacheBookmarks(1) call s:Bookmark.CacheBookmarks(1)
call nerdtree#renderView() call b:NERDTree.render()
call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.") call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
return 0 return 0
endif endif

View file

@ -7,18 +7,18 @@ let g:NERDTreeCreator = s:Creator
"FUNCTION: s:Creator._bindMappings() {{{1 "FUNCTION: s:Creator._bindMappings() {{{1
function! s:Creator._bindMappings() function! s:Creator._bindMappings()
"make <cr> do the same as the default 'o' mapping "make <cr> do the same as the activate node mapping
exec "nnoremap <silent> <buffer> <cr> :call nerdtree#invokeKeyMap('". g:NERDTreeMapActivateNode ."')<cr>" nnoremap <silent> <buffer> <cr> :call nerdtree#ui_glue#invokeKeyMap(g:NERDTreeMapActivateNode)<cr>
call g:NERDTreeKeyMap.BindAll() call g:NERDTreeKeyMap.BindAll()
command! -buffer -nargs=? Bookmark :call nerdtree#bookmarkNode('<args>') command! -buffer -nargs=? Bookmark :call nerdtree#ui_glue#bookmarkNode('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#revealBookmark('<args>') command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#ui_glue#revealBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark :call nerdtree#openBookmark('<args>') command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark :call nerdtree#ui_glue#openBookmark('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#clearBookmarks('<args>') command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#ui_glue#clearBookmarks('<args>')
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>') command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>')
command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call nerdtree#renderView() command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call b:NERDTree.render()
command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call nerdtree#renderView() command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call b:NERDTree.render()
command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write() command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write()
endfunction endfunction
@ -49,26 +49,23 @@ function! s:Creator.createPrimary(name)
call path.changeToDir() call path.changeToDir()
endif endif
if nerdtree#treeExistsForTab() if g:NERDTree.ExistsForTab()
if nerdtree#isTreeOpen() if nerdtree#isTreeOpen()
call nerdtree#closeTree() call nerdtree#closeTree()
endif endif
unlet t:NERDTreeBufName unlet t:NERDTreeBufName
endif endif
let newRoot = g:NERDTreeDirNode.New(path)
call newRoot.open()
call self._createTreeWin() call self._createTreeWin()
call self._createNERDTree(path)
let b:NERDTreeType = "primary"
let b:treeShowHelp = 0 let b:treeShowHelp = 0
let b:NERDTreeIgnoreEnabled = 1 let b:NERDTreeIgnoreEnabled = 1
let b:NERDTreeShowFiles = g:NERDTreeShowFiles let b:NERDTreeShowFiles = g:NERDTreeShowFiles
let b:NERDTreeShowHidden = g:NERDTreeShowHidden let b:NERDTreeShowHidden = g:NERDTreeShowHidden
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
let b:NERDTreeRoot = newRoot
let b:NERDTreeType = "primary"
call nerdtree#renderView() call b:NERDTree.render()
call b:NERDTreeRoot.putCursorHere(0, 0) call b:NERDTreeRoot.putCursorHere(0, 0)
call self._broadcastInitEvent() call self._broadcastInitEvent()
@ -99,18 +96,26 @@ function! s:Creator.createSecondary(dir)
exec "silent edit " . self._nextBufferName() exec "silent edit " . self._nextBufferName()
let b:NERDTreePreviousBuf = bufnr(previousBuf) let b:NERDTreePreviousBuf = bufnr(previousBuf)
call self._createNERDTree(path)
let b:NERDTreeRoot = g:NERDTreeDirNode.New(path)
call b:NERDTreeRoot.open()
call self._setCommonBufOptions() call self._setCommonBufOptions()
let b:NERDTreeType = "secondary" let b:NERDTreeType = "secondary"
call nerdtree#renderView() call b:NERDTree.render()
call self._broadcastInitEvent() call self._broadcastInitEvent()
endfunction endfunction
" FUNCTION: s:Creator._createNERDTree(path) {{{1
function! s:Creator._createNERDTree(path)
let b:NERDTree = g:NERDTree.New(a:path)
"TODO: This is kept for compatability only since many things use
"b:NERDTreeRoot instead of the new NERDTree.root
"Remove this one day
let b:NERDTreeRoot = b:NERDTree.root
call b:NERDTree.root.open()
endfunction
" FUNCTION: s:Creator.CreateMirror() {{{1 " FUNCTION: s:Creator.CreateMirror() {{{1
function! s:Creator.CreateMirror() function! s:Creator.CreateMirror()
let creator = s:Creator.New() let creator = s:Creator.New()
@ -122,12 +127,12 @@ function! s:Creator.createMirror()
"get the names off all the nerd tree buffers "get the names off all the nerd tree buffers
let treeBufNames = [] let treeBufNames = []
for i in range(1, tabpagenr("$")) for i in range(1, tabpagenr("$"))
let nextName = nerdtree#tabpagevar(i, 'NERDTreeBufName') let nextName = self._tabpagevar(i, 'NERDTreeBufName')
if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName) if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName)
call add(treeBufNames, nextName) call add(treeBufNames, nextName)
endif endif
endfor endfor
let treeBufNames = nerdtree#unique(treeBufNames) let treeBufNames = self._uniq(treeBufNames)
"map the option names (that the user will be prompted with) to the nerd "map the option names (that the user will be prompted with) to the nerd
"tree buffer names "tree buffer names
@ -158,7 +163,7 @@ function! s:Creator.createMirror()
return return
endif endif
if nerdtree#treeExistsForTab() && nerdtree#isTreeOpen() if g:NERDTree.ExistsForTab() && nerdtree#isTreeOpen()
call nerdtree#closeTree() call nerdtree#closeTree()
endif endif
@ -166,7 +171,7 @@ function! s:Creator.createMirror()
call self._createTreeWin() call self._createTreeWin()
exec 'buffer ' . bufferName exec 'buffer ' . bufferName
if !&hidden if !&hidden
call nerdtree#renderView() call b:NERDTree.render()
endif endif
endfunction endfunction
@ -279,8 +284,8 @@ function! s:Creator._setCommonBufOptions()
let b:NERDTreeShowFiles = g:NERDTreeShowFiles let b:NERDTreeShowFiles = g:NERDTreeShowFiles
let b:NERDTreeShowHidden = g:NERDTreeShowHidden let b:NERDTreeShowHidden = g:NERDTreeShowHidden
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
setfiletype nerdtree
call self._bindMappings() call self._bindMappings()
setlocal filetype=nerdtree
endfunction endfunction
"FUNCTION: s:Creator._setupStatusline() {{{1 "FUNCTION: s:Creator._setupStatusline() {{{1
@ -290,6 +295,24 @@ function! s:Creator._setupStatusline()
endif endif
endfunction endfunction
" FUNCTION: s:Creator._tabpagevar(tabnr, var) {{{1
function! s:Creator._tabpagevar(tabnr, var)
let currentTab = tabpagenr()
let old_ei = &ei
set ei=all
exec "tabnext " . a:tabnr
let v = -1
if exists('t:' . a:var)
exec 'let v = t:' . a:var
endif
exec "tabnext " . currentTab
let &ei = old_ei
return v
endfunction
"FUNCTION: s:Creator.TogglePrimary(dir) {{{1 "FUNCTION: s:Creator.TogglePrimary(dir) {{{1
function! s:Creator.TogglePrimary(dir) function! s:Creator.TogglePrimary(dir)
let creator = s:Creator.New() let creator = s:Creator.New()
@ -304,13 +327,13 @@ endfunction
"dir: the full path for the root node (is only used if the NERD tree is being "dir: the full path for the root node (is only used if the NERD tree is being
"initialized. "initialized.
function! s:Creator.togglePrimary(dir) function! s:Creator.togglePrimary(dir)
if nerdtree#treeExistsForTab() if g:NERDTree.ExistsForTab()
if !nerdtree#isTreeOpen() if !nerdtree#isTreeOpen()
call self._createTreeWin() call self._createTreeWin()
if !&hidden if !&hidden
call nerdtree#renderView() call b:NERDTree.render()
endif endif
call nerdtree#restoreScreenState() call b:NERDTree.ui.restoreScreenState()
else else
call nerdtree#closeTree() call nerdtree#closeTree()
endif endif
@ -319,4 +342,16 @@ function! s:Creator.togglePrimary(dir)
endif endif
endfunction endfunction
" Function: s:Creator._uniq(list) {{{1
" returns a:list without duplicates
function! s:Creator._uniq(list)
let uniqlist = []
for elem in a:list
if index(uniqlist, elem) ==# -1
let uniqlist += [elem]
endif
endfor
return uniqlist
endfunction
" vim: set sw=4 sts=4 et fdm=marker: " vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,13 @@
"CLASS: Event
"============================================================
let s:Event = {}
let g:NERDTreeEvent = s:Event
function! s:Event.New(nerdtree, subject, action, params) abort
let newObj = copy(self)
let newObj.nerdtree = a:nerdtree
let newObj.subject = a:subject
let newObj.action = a:action
let newObj.params = a:params
return newObj
endfunction

View file

@ -0,0 +1,56 @@
"CLASS: FlagSet
"============================================================
let s:FlagSet = {}
let g:NERDTreeFlagSet = s:FlagSet
"FUNCTION: FlagSet.addFlag(scope, flag) {{{1
function! s:FlagSet.addFlag(scope, flag)
let flags = self._flagsForScope(a:scope)
if index(flags, a:flag) == -1
call add(flags, a:flag)
end
endfunction
"FUNCTION: FlagSet.clearFlags(scope) {{{1
function! s:FlagSet.clearFlags(scope)
let self._flags[a:scope] = []
endfunction
"FUNCTION: FlagSet._flagsForScope(scope) {{{1
function! s:FlagSet._flagsForScope(scope)
if !has_key(self._flags, a:scope)
let self._flags[a:scope] = []
endif
return self._flags[a:scope]
endfunction
"FUNCTION: FlagSet.New() {{{1
function! s:FlagSet.New()
let newObj = copy(self)
let newObj._flags = {}
return newObj
endfunction
"FUNCTION: FlagSet.removeFlag(scope, flag) {{{1
function! s:FlagSet.removeFlag(scope, flag)
let flags = self._flagsForScope(a:scope)
let i = index(flags, a:flag)
if i >= 0
call remove(flags, i)
endif
endfunction
"FUNCTION: FlagSet.renderToString() {{{1
function! s:FlagSet.renderToString()
let flagstring = ""
for i in values(self._flags)
let flagstring .= join(i)
endfor
if len(flagstring) == 0
return ""
endif
return '[' . flagstring . ']'
endfunction

View file

@ -44,7 +44,7 @@ function! s:KeyMap.bind()
let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " " let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " "
exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#invokeKeyMap("'. keymapInvokeString .'")<cr>' exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#ui_glue#invokeKeyMap("'. keymapInvokeString .'")<cr>'
endfunction endfunction
"FUNCTION: KeyMap.Remove(key, scope) {{{1 "FUNCTION: KeyMap.Remove(key, scope) {{{1
@ -79,6 +79,16 @@ endfunction
"If a keymap has the scope of "all" then it will be called if no other keymap "If a keymap has the scope of "all" then it will be called if no other keymap
"is found for a:key and the scope. "is found for a:key and the scope.
function! s:KeyMap.Invoke(key) function! s:KeyMap.Invoke(key)
"required because clicking the command window below another window still
"invokes the <LeftRelease> mapping - but changes the window cursor
"is in first
"
"TODO: remove this check when the vim bug is fixed
if !g:NERDTree.ExistsForBuf()
return {}
endif
let node = g:NERDTreeFileNode.GetSelected() let node = g:NERDTreeFileNode.GetSelected()
if !empty(node) if !empty(node)
@ -124,8 +134,14 @@ endfunction
"FUNCTION: KeyMap.Create(options) {{{1 "FUNCTION: KeyMap.Create(options) {{{1
function! s:KeyMap.Create(options) function! s:KeyMap.Create(options)
let newKeyMap = copy(self)
let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options)) let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options))
"dont override other mappings unless the 'override' option is given
if get(opts, 'override', 0) == 0 && !empty(s:KeyMap.FindFor(opts['key'], opts['scope']))
return
end
let newKeyMap = copy(self)
let newKeyMap.key = opts['key'] let newKeyMap.key = opts['key']
let newKeyMap.quickhelpText = opts['quickhelpText'] let newKeyMap.quickhelpText = opts['quickhelpText']
let newKeyMap.callback = opts['callback'] let newKeyMap.callback = opts['callback']

View file

@ -90,7 +90,7 @@ endfunction
"callback "callback
function! s:MenuItem.execute() function! s:MenuItem.execute()
if len(self.children) if len(self.children)
let mc = s:MenuController.New(self.children) let mc = g:NERDTreeMenuController.New(self.children)
call mc.showMenu() call mc.showMenu()
else else
if self.callback != -1 if self.callback != -1

View file

@ -0,0 +1,39 @@
"CLASS: NERDTree
"============================================================
let s:NERDTree = {}
let g:NERDTree = s:NERDTree
" Function: s:NERDTree.ExistsForBuffer() {{{1
" Returns 1 if a nerd tree root exists in the current buffer
function! s:NERDTree.ExistsForBuf()
return exists("b:NERDTreeRoot")
endfunction
" Function: s:NERDTree.ExistsForTab() {{{1
" Returns 1 if a nerd tree root exists in the current tab
function! s:NERDTree.ExistsForTab()
return exists("t:NERDTreeBufName")
endfunction
function! s:NERDTree.ForCurrentBuf()
if s:NERDTree.ExistsForBuf()
return b:NERDTree
else
return {}
endif
endfunction
function! s:NERDTree.New(path)
let newObj = copy(self)
let newObj.ui = g:NERDTreeUI.New(newObj)
let newObj.root = g:NERDTreeDirNode.New(a:path)
return newObj
endfunction
"FUNCTION: s:NERDTree.render() {{{1
"A convenience function - since this is called often
function! s:NERDTree.render()
call self.ui.render()
endfunction

View file

@ -0,0 +1,35 @@
"CLASS: Notifier
"============================================================
let s:Notifier = {}
function! s:Notifier.AddListener(event, funcname)
let listeners = s:Notifier.GetListenersForEvent(a:event)
if listeners == []
let listenersMap = s:Notifier.GetListenersMap()
let listenersMap[a:event] = listeners
endif
call add(listeners, a:funcname)
endfunction
function! s:Notifier.NotifyListeners(event, path, params)
let event = g:NERDTreeEvent.New(b:NERDTree, a:path, a:event, a:params)
for listener in s:Notifier.GetListenersForEvent(a:event)
call {listener}(event)
endfor
endfunction
function! s:Notifier.GetListenersMap()
if !exists("s:refreshListenersMap")
let s:refreshListenersMap = {}
endif
return s:refreshListenersMap
endfunction
function! s:Notifier.GetListenersForEvent(name)
let listenersMap = s:Notifier.GetListenersMap()
return get(listenersMap, a:name, [])
endfunction
let g:NERDTreePathNotifier = deepcopy(s:Notifier)

View file

@ -3,6 +3,29 @@
let s:Opener = {} let s:Opener = {}
let g:NERDTreeOpener = s:Opener let g:NERDTreeOpener = s:Opener
"FUNCTION: s:Opener._bufInWindows(bnum){{{1
"[[STOLEN FROM VTREEEXPLORER.VIM]]
"Determine the number of windows open to this buffer number.
"Care of Yegappan Lakshman. Thanks!
"
"Args:
"bnum: the subject buffers buffer number
function! s:Opener._bufInWindows(bnum)
let cnt = 0
let winnum = 1
while 1
let bufnum = winbufnr(winnum)
if bufnum < 0
break
endif
if bufnum ==# a:bnum
let cnt = cnt + 1
endif
let winnum = winnum + 1
endwhile
return cnt
endfunction
"FUNCTION: Opener._checkToCloseTree(newtab) {{{1 "FUNCTION: Opener._checkToCloseTree(newtab) {{{1
"Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see "Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see
"if the tree should be closed now. "if the tree should be closed now.
@ -21,6 +44,24 @@ function! s:Opener._checkToCloseTree(newtab)
endif endif
endfunction endfunction
"FUNCTION: s:Opener._firstUsableWindow(){{{1
"find the window number of the first normal window
function! s:Opener._firstUsableWindow()
let i = 1
while i <= winnr("$")
let bnum = winbufnr(i)
if bnum != -1 && getbufvar(bnum, '&buftype') ==# ''
\ && !getwinvar(i, '&previewwindow')
\ && (!getbufvar(bnum, '&modified') || &hidden)
return i
endif
let i += 1
endwhile
return -1
endfunction
"FUNCTION: Opener._gotoTargetWin() {{{1 "FUNCTION: Opener._gotoTargetWin() {{{1
function! s:Opener._gotoTargetWin() function! s:Opener._gotoTargetWin()
if b:NERDTreeType ==# "secondary" if b:NERDTreeType ==# "secondary"
@ -48,6 +89,37 @@ function! s:Opener._gotoTargetWin()
endif endif
endfunction endfunction
"FUNCTION: s:Opener._isWindowUsable(winnumber) {{{1
"Returns 0 if opening a file from the tree in the given window requires it to
"be split, 1 otherwise
"
"Args:
"winnumber: the number of the window in question
function! s:Opener._isWindowUsable(winnumber)
"gotta split if theres only one window (i.e. the NERD tree)
if winnr("$") ==# 1
return 0
endif
let oldwinnr = winnr()
call nerdtree#exec(a:winnumber . "wincmd p")
let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow')
let modified = &modified
call nerdtree#exec(oldwinnr . "wincmd p")
"if its a special window e.g. quickfix or another explorer plugin then we
"have to split
if specialWindow
return 0
endif
if &hidden
return 1
endif
return !modified || self._bufInWindows(winbufnr(a:winnumber)) >= 2
endfunction
"FUNCTION: Opener.New(path, opts) {{{1 "FUNCTION: Opener.New(path, opts) {{{1
"Args: "Args:
" "
@ -190,7 +262,7 @@ function! s:Opener._openDirectory(node)
call self._gotoTargetWin() call self._gotoTargetWin()
if empty(self._where) if empty(self._where)
call a:node.makeRoot() call a:node.makeRoot()
call nerdtree#renderView() call b:NERDTree.render()
call a:node.putCursorHere(0, 0) call a:node.putCursorHere(0, 0)
elseif self._where == 't' elseif self._where == 't'
call g:NERDTreeCreator.CreatePrimary(a:node.path.str()) call g:NERDTreeCreator.CreatePrimary(a:node.path.str())
@ -206,12 +278,12 @@ endfunction
"FUNCTION: Opener._previousWindow() {{{1 "FUNCTION: Opener._previousWindow() {{{1
function! s:Opener._previousWindow() function! s:Opener._previousWindow()
if !nerdtree#isWindowUsable(winnr("#")) && nerdtree#firstUsableWindow() ==# -1 if !self._isWindowUsable(winnr("#")) && self._firstUsableWindow() ==# -1
call self._newSplit() call self._newSplit()
else else
try try
if !nerdtree#isWindowUsable(winnr("#")) if !self._isWindowUsable(winnr("#"))
call nerdtree#exec(nerdtree#firstUsableWindow() . "wincmd w") call nerdtree#exec(self._firstUsableWindow() . "wincmd w")
else else
call nerdtree#exec('wincmd p') call nerdtree#exec('wincmd p')
endif endif

View file

@ -33,8 +33,10 @@ function! s:Path.bookmarkNames()
endfunction endfunction
"FUNCTION: Path.cacheDisplayString() {{{1 "FUNCTION: Path.cacheDisplayString() {{{1
function! s:Path.cacheDisplayString() function! s:Path.cacheDisplayString() abort
let self.cachedDisplayString = self.getLastPathComponent(1) let self.cachedDisplayString = self.flagSet.renderToString()
let self.cachedDisplayString .= self.getLastPathComponent(1)
if self.isExecutable if self.isExecutable
let self.cachedDisplayString = self.cachedDisplayString . '*' let self.cachedDisplayString = self.cachedDisplayString . '*'
@ -103,6 +105,10 @@ function! s:Path.compareTo(path)
elseif thisSS > thatSS elseif thisSS > thatSS
return 1 return 1
else else
if !g:NERDTreeSortHiddenFirst
let thisPath = substitute(thisPath, '^[._]', '', '')
let thatPath = substitute(thatPath, '^[._]', '', '')
endif
"if the sort sequences are the same then compare the paths "if the sort sequences are the same then compare the paths
"alphabetically "alphabetically
let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
@ -141,6 +147,7 @@ function! s:Path.Create(fullpath)
"assume its a file and create "assume its a file and create
else else
call s:Path.createParentDirectories(a:fullpath)
call writefile([], a:fullpath) call writefile([], a:fullpath)
endif endif
catch catch
@ -161,9 +168,11 @@ function! s:Path.copy(dest)
throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS" throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS"
endif endif
call s:Path.createParentDirectories(a:dest)
let dest = s:Path.WinToUnixPath(a:dest) let dest = s:Path.WinToUnixPath(a:dest)
let cmd = g:NERDTreeCopyCmd . " " . escape(self.str(), nerdtree#escChars()) . " " . escape(dest, nerdtree#escChars()) let cmd = g:NERDTreeCopyCmd . " " . escape(self.str(), self._escChars()) . " " . escape(dest, self._escChars())
let success = system(cmd) let success = system(cmd)
if success != 0 if success != 0
throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'" throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'"
@ -197,6 +206,20 @@ function! s:Path.copyingWillOverwrite(dest)
endif endif
endfunction endfunction
"FUNCTION: Path.createParentDirectories(path) {{{1
"
"create parent directories for this path if needed
"without throwing any errors is those directories already exist
"
"Args:
"path: full path of the node whose parent directories may need to be created
function! s:Path.createParentDirectories(path)
let dir_path = fnamemodify(a:path, ':h')
if !isdirectory(dir_path)
call mkdir(dir_path, 'p')
endif
endfunction
"FUNCTION: Path.delete() {{{1 "FUNCTION: Path.delete() {{{1
" "
"Deletes the file represented by this path. "Deletes the file represented by this path.
@ -268,6 +291,15 @@ function! s:Path.exists()
return filereadable(p) || isdirectory(p) return filereadable(p) || isdirectory(p)
endfunction endfunction
"FUNCTION: Path._escChars() {{{1
function! s:Path._escChars()
if nerdtree#runningWindows()
return " `\|\"#%&,?()\*^<>"
endif
return " \\`\|\"#%&,?()\*^<>[]"
endfunction
"FUNCTION: Path.getDir() {{{1 "FUNCTION: Path.getDir() {{{1
" "
"Returns this path if it is a directory, else this paths parent. "Returns this path if it is a directory, else this paths parent.
@ -439,6 +471,7 @@ function! s:Path.New(path)
call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path)) call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path))
let newPath.cachedDisplayString = "" let newPath.cachedDisplayString = ""
let newPath.flagSet = g:NERDTreeFlagSet.New()
return newPath return newPath
endfunction endfunction
@ -516,6 +549,13 @@ endfunction
"FUNCTION: Path.refresh() {{{1 "FUNCTION: Path.refresh() {{{1
function! s:Path.refresh() function! s:Path.refresh()
call self.readInfoFromDisk(self.str()) call self.readInfoFromDisk(self.str())
call g:NERDTreePathNotifier.NotifyListeners('refresh', self, {})
call self.cacheDisplayString()
endfunction
"FUNCTION: Path.refreshFlags() {{{1
function! s:Path.refreshFlags()
call g:NERDTreePathNotifier.NotifyListeners('refreshFlags', self, {})
call self.cacheDisplayString() call self.cacheDisplayString()
endfunction endfunction
@ -583,8 +623,13 @@ function! s:Path.str(...)
if has_key(options, 'truncateTo') if has_key(options, 'truncateTo')
let limit = options['truncateTo'] let limit = options['truncateTo']
if len(toReturn) > limit if len(toReturn) > limit-1
let toReturn = "<" . strpart(toReturn, len(toReturn) - limit + 1) let toReturn = toReturn[(len(toReturn)-limit+1):]
if len(split(toReturn, '/')) > 1
let toReturn = '</' . join(split(toReturn, '/')[1:], '/') . '/'
else
let toReturn = '<' . toReturn
endif
endif endif
endif endif
@ -604,7 +649,7 @@ endfunction
" "
" returns a string that can be used with :cd " returns a string that can be used with :cd
function! s:Path._strForCd() function! s:Path._strForCd()
return escape(self.str(), nerdtree#escChars()) return escape(self.str(), self._escChars())
endfunction endfunction
"FUNCTION: Path._strForEdit() {{{1 "FUNCTION: Path._strForEdit() {{{1
@ -612,26 +657,16 @@ endfunction
"Return: the string for this path that is suitable to be used with the :edit "Return: the string for this path that is suitable to be used with the :edit
"command "command
function! s:Path._strForEdit() function! s:Path._strForEdit()
let p = escape(self.str({'format': 'UI'}), nerdtree#escChars()) let p = escape(self.str(), self._escChars())
let cwd = getcwd() . s:Path.Slash()
"return a relative path if we can "make it relative
let isRelative = 0 let p = fnamemodify(p, ':.')
if nerdtree#runningWindows()
let isRelative = stridx(tolower(p), tolower(cwd)) == 0
else
let isRelative = stridx(p, cwd) == 0
endif
if isRelative
let p = strpart(p, strlen(cwd))
"handle the edge case where the file begins with a + (vim interprets "handle the edge case where the file begins with a + (vim interprets
"the +foo in `:e +foo` as an option to :edit) "the +foo in `:e +foo` as an option to :edit)
if p[0] == "+" if p[0] == "+"
let p = '\' . p let p = '\' . p
endif endif
endif
if p ==# '' if p ==# ''
let p = '.' let p = '.'
@ -652,7 +687,7 @@ function! s:Path._strForGlob()
let toReturn = lead . join(self.pathSegments, s:Path.Slash()) let toReturn = lead . join(self.pathSegments, s:Path.Slash())
if !nerdtree#runningWindows() if !nerdtree#runningWindows()
let toReturn = escape(toReturn, nerdtree#escChars()) let toReturn = escape(toReturn, self._escChars())
endif endif
return toReturn return toReturn
endfunction endfunction

View file

@ -21,7 +21,7 @@ unlet s:TreeDirNode.activate
function! s:TreeDirNode.activate(...) function! s:TreeDirNode.activate(...)
let opts = a:0 ? a:1 : {} let opts = a:0 ? a:1 : {}
call self.toggleOpen(opts) call self.toggleOpen(opts)
call nerdtree#renderView() call b:NERDTree.render()
call self.putCursorHere(0, 0) call self.putCursorHere(0, 0)
endfunction endfunction
@ -229,7 +229,7 @@ function! s:TreeDirNode._initChildren(silent)
let globDir = dir.str({'format': 'Glob'}) let globDir = dir.str({'format': 'Glob'})
if version >= 703 if version >= 703
let filesStr = globpath(globDir, '*', 1) . "\n" . globpath(globDir, '.*', 1) let filesStr = globpath(globDir, '*', !g:NERDTreeRespectWildIgnore) . "\n" . globpath(globDir, '.*', !g:NERDTreeRespectWildIgnore)
else else
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*') let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
endif endif
@ -252,6 +252,7 @@ function! s:TreeDirNode._initChildren(silent)
try try
let path = g:NERDTreePath.New(i) let path = g:NERDTreePath.New(i)
call self.createChild(path, 0) call self.createChild(path, 0)
call g:NERDTreePathNotifier.NotifyListeners('init', path, {})
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/ catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
let invalidFilesFound += 1 let invalidFilesFound += 1
endtry endtry
@ -438,6 +439,20 @@ function! s:TreeDirNode.refresh()
endif endif
endfunction endfunction
"FUNCTION: TreeDirNode.refreshFlags() {{{1
unlet s:TreeDirNode.refreshFlags
function! s:TreeDirNode.refreshFlags()
call self.path.refreshFlags()
for i in self.children
call i.refreshFlags()
endfor
endfunction
"FUNCTION: TreeDirNode.refreshDirFlags() {{{1
function! s:TreeDirNode.refreshDirFlags()
call self.path.refreshFlags()
endfunction
"FUNCTION: TreeDirNode.reveal(path) {{{1 "FUNCTION: TreeDirNode.reveal(path) {{{1
"reveal the given path, i.e. cache and open all treenodes needed to display it "reveal the given path, i.e. cache and open all treenodes needed to display it
"in the UI "in the UI
@ -450,7 +465,7 @@ function! s:TreeDirNode.reveal(path)
if self.path.equals(a:path.getParent()) if self.path.equals(a:path.getParent())
let n = self.findNode(a:path) let n = self.findNode(a:path)
call nerdtree#renderView() call b:NERDTree.render()
call n.putCursorHere(1,0) call n.putCursorHere(1,0)
return return
endif endif
@ -500,7 +515,7 @@ function! s:TreeDirNode.toggleOpen(...)
if self.isOpen ==# 1 if self.isOpen ==# 1
call self.close() call self.close()
else else
if g:NERDTreeCasadeOpenSingleChildDir == 0 if g:NERDTreeCascadeOpenSingleChildDir == 0
call self.open(opts) call self.open(opts)
else else
call self.openAlong(opts) call self.openAlong(opts)

View file

@ -178,79 +178,20 @@ function! s:TreeFileNode.findSibling(direction)
return {} return {}
endfunction endfunction
"FUNCTION: TreeFileNode.getLineNum(){{{1
"returns the line number this node is rendered on, or -1 if it isnt rendered
function! s:TreeFileNode.getLineNum()
"if the node is the root then return the root line no.
if self.isRoot()
return s:TreeFileNode.GetRootLineNum()
endif
let totalLines = line("$")
"the path components we have matched so far
let pathcomponents = [substitute(b:NERDTreeRoot.path.str({'format': 'UI'}), '/ *$', '', '')]
"the index of the component we are searching for
let curPathComponent = 1
let fullpath = self.path.str({'format': 'UI'})
let lnum = s:TreeFileNode.GetRootLineNum()
while lnum > 0
let lnum = lnum + 1
"have we reached the bottom of the tree?
if lnum ==# totalLines+1
return -1
endif
let curLine = getline(lnum)
let indent = nerdtree#indentLevelFor(curLine)
if indent ==# curPathComponent
let curLine = nerdtree#stripMarkupFromLine(curLine, 1)
let curPath = join(pathcomponents, '/') . '/' . curLine
if stridx(fullpath, curPath, 0) ==# 0
if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/'
let curLine = substitute(curLine, '/ *$', '', '')
call add(pathcomponents, curLine)
let curPathComponent = curPathComponent + 1
if fullpath ==# curPath
return lnum
endif
endif
endif
endif
endwhile
return -1
endfunction
"FUNCTION: TreeFileNode.GetRootForTab(){{{1 "FUNCTION: TreeFileNode.GetRootForTab(){{{1
"get the root node for this tab "get the root node for this tab
function! s:TreeFileNode.GetRootForTab() function! s:TreeFileNode.GetRootForTab()
if nerdtree#treeExistsForTab() if g:NERDTree.ExistsForTab()
return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot') return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot')
end end
return {} return {}
endfunction endfunction
"FUNCTION: TreeFileNode.GetRootLineNum(){{{1
"gets the line number of the root node
function! s:TreeFileNode.GetRootLineNum()
let rootLine = 1
while getline(rootLine) !~# '^\(/\|<\)'
let rootLine = rootLine + 1
endwhile
return rootLine
endfunction
"FUNCTION: TreeFileNode.GetSelected() {{{1 "FUNCTION: TreeFileNode.GetSelected() {{{1
"gets the treenode that the cursor is currently over "gets the treenode that the cursor is currently over
function! s:TreeFileNode.GetSelected() function! s:TreeFileNode.GetSelected()
try try
let path = nerdtree#getPath(line(".")) let path = b:NERDTree.ui.getPath(line("."))
if path ==# {} if path ==# {}
return {} return {}
endif endif
@ -270,7 +211,7 @@ endfunction
"FUNCTION: TreeFileNode.isRoot() {{{1 "FUNCTION: TreeFileNode.isRoot() {{{1
"returns 1 if this node is b:NERDTreeRoot "returns 1 if this node is b:NERDTreeRoot
function! s:TreeFileNode.isRoot() function! s:TreeFileNode.isRoot()
if !nerdtree#treeExistsForBuf() if !g:NERDTree.ExistsForBuf()
throw "NERDTree.NoTreeError: No tree exists for the current buffer" throw "NERDTree.NoTreeError: No tree exists for the current buffer"
endif endif
@ -348,7 +289,7 @@ endfunction
"recurseUpward: try to put the cursor on the parent if the this node isnt "recurseUpward: try to put the cursor on the parent if the this node isnt
"visible "visible
function! s:TreeFileNode.putCursorHere(isJump, recurseUpward) function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
let ln = self.getLineNum() let ln = b:NERDTree.ui.getLineNum(self)
if ln != -1 if ln != -1
if a:isJump if a:isJump
mark ' mark '
@ -357,11 +298,11 @@ function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
else else
if a:recurseUpward if a:recurseUpward
let node = self let node = self
while node != {} && node.getLineNum() ==# -1 while node != {} && b:NERDTree.ui.getLineNum(node) ==# -1
let node = node.parent let node = node.parent
call node.open() call node.open()
endwhile endwhile
call nerdtree#renderView() call b:NERDTree.render()
call node.putCursorHere(a:isJump, 0) call node.putCursorHere(a:isJump, 0)
endif endif
endif endif
@ -372,6 +313,11 @@ function! s:TreeFileNode.refresh()
call self.path.refresh() call self.path.refresh()
endfunction endfunction
"FUNCTION: TreeFileNode.refreshFlags() {{{1
function! s:TreeFileNode.refreshFlags()
call self.path.refreshFlags()
endfunction
"FUNCTION: TreeFileNode.rename() {{{1 "FUNCTION: TreeFileNode.rename() {{{1
"Calls the rename method for this nodes path obj "Calls the rename method for this nodes path obj
function! s:TreeFileNode.rename(newName) function! s:TreeFileNode.rename(newName)

View file

@ -0,0 +1,332 @@
"CLASS: UI
"============================================================
let s:UI = {}
let g:NERDTreeUI = s:UI
function! s:UI.lolcats()
echomsg "lolcats"
endfunction
"FUNCTION: s:UI.centerView() {{{2
"centers the nerd tree window around the cursor (provided the nerd tree
"options permit)
function! s:UI.centerView()
if g:NERDTreeAutoCenter
let current_line = winline()
let lines_to_top = current_line
let lines_to_bottom = winheight(nerdtree#getTreeWinNum()) - current_line
if lines_to_top < g:NERDTreeAutoCenterThreshold || lines_to_bottom < g:NERDTreeAutoCenterThreshold
normal! zz
endif
endif
endfunction
"FUNCTION: s:UI.new(nerdtree) {{{1
function! s:UI.New(nerdtree)
let newObj = copy(self)
let newObj.nerdtree = a:nerdtree
return newObj
endfunction
"FUNCTION: s:UI.getPath(ln) {{{1
"Gets the full path to the node that is rendered on the given line number
"
"Args:
"ln: the line number to get the path for
"
"Return:
"A path if a node was selected, {} if nothing is selected.
"If the 'up a dir' line was selected then the path to the parent of the
"current root is returned
function! s:UI.getPath(ln)
let line = getline(a:ln)
let rootLine = self.getRootLineNum()
"check to see if we have the root node
if a:ln == rootLine
return b:NERDTreeRoot.path
endif
if !g:NERDTreeDirArrows
" in case called from outside the tree
if line !~# '^ *[|`▸▾ ]' || line =~# '^$'
return {}
endif
endif
if line ==# nerdtree#treeUpDirLine()
return b:NERDTreeRoot.path.getParent()
endif
let indent = self._indentLevelFor(line)
"remove the tree parts and the leading space
let curFile = nerdtree#stripMarkupFromLine(line, 0)
let wasdir = 0
if curFile =~# '/$'
let wasdir = 1
let curFile = substitute(curFile, '/\?$', '/', "")
endif
let dir = ""
let lnum = a:ln
while lnum > 0
let lnum = lnum - 1
let curLine = getline(lnum)
let curLineStripped = nerdtree#stripMarkupFromLine(curLine, 1)
"have we reached the top of the tree?
if lnum == rootLine
let dir = b:NERDTreeRoot.path.str({'format': 'UI'}) . dir
break
endif
if curLineStripped =~# '/$'
let lpindent = self._indentLevelFor(curLine)
if lpindent < indent
let indent = indent - 1
let dir = substitute (curLineStripped,'^\\', "", "") . dir
continue
endif
endif
endwhile
let curFile = b:NERDTreeRoot.path.drive . dir . curFile
let toReturn = g:NERDTreePath.New(curFile)
return toReturn
endfunction
"FUNCTION: s:UI.getLineNum(file_node){{{1
"returns the line number this node is rendered on, or -1 if it isnt rendered
function! s:UI.getLineNum(file_node)
"if the node is the root then return the root line no.
if a:file_node.isRoot()
return b:NERDTree.ui.getRootLineNum()
endif
let totalLines = line("$")
"the path components we have matched so far
let pathcomponents = [substitute(b:NERDTreeRoot.path.str({'format': 'UI'}), '/ *$', '', '')]
"the index of the component we are searching for
let curPathComponent = 1
let fullpath = a:file_node.path.str({'format': 'UI'})
let lnum = b:NERDTree.ui.getRootLineNum()
while lnum > 0
let lnum = lnum + 1
"have we reached the bottom of the tree?
if lnum ==# totalLines+1
return -1
endif
let curLine = getline(lnum)
let indent = self._indentLevelFor(curLine)
if indent ==# curPathComponent
let curLine = nerdtree#stripMarkupFromLine(curLine, 1)
let curPath = join(pathcomponents, '/') . '/' . curLine
if stridx(fullpath, curPath, 0) ==# 0
if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/'
let curLine = substitute(curLine, '/ *$', '', '')
call add(pathcomponents, curLine)
let curPathComponent = curPathComponent + 1
if fullpath ==# curPath
return lnum
endif
endif
endif
endif
endwhile
return -1
endfunction
"FUNCTION: s:UI.getRootLineNum(){{{1
"gets the line number of the root node
function! s:UI.getRootLineNum()
let rootLine = 1
while getline(rootLine) !~# '^\(/\|<\)'
let rootLine = rootLine + 1
endwhile
return rootLine
endfunction
"FUNCTION: s:UI._indentLevelFor(line) {{{2
function! s:UI._indentLevelFor(line)
let level = match(a:line, '[^ \-+~▸▾`|]') / nerdtree#treeWid()
" check if line includes arrows
if match(a:line, '[▸▾]') > -1
" decrement level as arrow uses 3 ascii chars
let level = level - 1
endif
return level
endfunction
"FUNCTION: s:UI.restoreScreenState() {{{2
"
"Sets the screen state back to what it was when nerdtree#saveScreenState was last
"called.
"
"Assumes the cursor is in the NERDTree window
function! s:UI.restoreScreenState()
if !has_key(self, '_screenState')
return
endif
exec("silent vertical resize " . self._screenState['oldWindowSize'])
let old_scrolloff=&scrolloff
let &scrolloff=0
call cursor(self._screenState['oldTopLine'], 0)
normal! zt
call setpos(".", self._screenState['oldPos'])
let &scrolloff=old_scrolloff
endfunction
"FUNCTION: s:UI.saveScreenState() {{{2
"Saves the current cursor position in the current buffer and the window
"scroll position
function! s:UI.saveScreenState()
let win = winnr()
try
call nerdtree#putCursorInTreeWin()
let self._screenState = {}
let self._screenState['oldPos'] = getpos(".")
let self._screenState['oldTopLine'] = line("w0")
let self._screenState['oldWindowSize']= winwidth("")
call nerdtree#exec(win . "wincmd w")
catch /^NERDTree.InvalidOperationError/
endtry
endfunction
"FUNCTION: s:UI.render() {{{2
function! s:UI.render()
setlocal modifiable
"remember the top line of the buffer and the current line so we can
"restore the view exactly how it was
let curLine = line(".")
let curCol = col(".")
let topLine = line("w0")
"delete all lines in the buffer (being careful not to clobber a register)
silent 1,$delete _
call nerdtree#dumpHelp()
"delete the blank line before the help and add one after it
if g:NERDTreeMinimalUI == 0
call setline(line(".")+1, "")
call cursor(line(".")+1, col("."))
endif
if b:NERDTreeShowBookmarks
call nerdtree#renderBookmarks()
endif
"add the 'up a dir' line
if !g:NERDTreeMinimalUI
call setline(line(".")+1, nerdtree#treeUpDirLine())
call cursor(line(".")+1, col("."))
endif
"draw the header line
let header = b:NERDTreeRoot.path.str({'format': 'UI', 'truncateTo': winwidth(0)})
call setline(line(".")+1, header)
call cursor(line(".")+1, col("."))
"draw the tree
let old_o = @o
let @o = b:NERDTreeRoot.renderToString()
silent put o
let @o = old_o
"delete the blank line at the top of the buffer
silent 1,1delete _
"restore the view
let old_scrolloff=&scrolloff
let &scrolloff=0
call cursor(topLine, 1)
normal! zt
call cursor(curLine, curCol)
let &scrolloff = old_scrolloff
setlocal nomodifiable
endfunction
"FUNCTION: UI.renderViewSavingPosition {{{1
"Renders the tree and ensures the cursor stays on the current node or the
"current nodes parent if it is no longer available upon re-rendering
function! s:UI.renderViewSavingPosition()
let currentNode = g:NERDTreeFileNode.GetSelected()
"go up the tree till we find a node that will be visible or till we run
"out of nodes
while currentNode != {} && !currentNode.isVisible() && !currentNode.isRoot()
let currentNode = currentNode.parent
endwhile
call b:NERDTree.render()
if currentNode != {}
call currentNode.putCursorHere(0, 0)
endif
endfunction
" FUNCTION: s:UI.toggleIgnoreFilter() {{{1
" toggles the use of the NERDTreeIgnore option
function! s:UI.toggleIgnoreFilter()
let b:NERDTreeIgnoreEnabled = !b:NERDTreeIgnoreEnabled
call b:NERDTree.ui.renderViewSavingPosition()
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:UI.toggleShowBookmarks() {{{1
" toggles the display of bookmarks
function! s:UI.toggleShowBookmarks()
let b:NERDTreeShowBookmarks = !b:NERDTreeShowBookmarks
if b:NERDTreeShowBookmarks
call b:NERDTree.render()
call nerdtree#putCursorOnBookmarkTable()
else
call b:NERDTree.ui.renderViewSavingPosition()
endif
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:UI.toggleShowFiles() {{{1
" toggles the display of hidden files
function! s:UI.toggleShowFiles()
let b:NERDTreeShowFiles = !b:NERDTreeShowFiles
call b:NERDTree.ui.renderViewSavingPosition()
call b:NERDTree.ui.centerView()
endfunction
" FUNCTION: s:UI.toggleShowHidden() {{{1
" toggles the display of hidden files
function! s:UI.toggleShowHidden()
let b:NERDTreeShowHidden = !b:NERDTreeShowHidden
call b:NERDTree.ui.renderViewSavingPosition()
call self.centerView()
endfunction
" FUNCTION: s:UI.toggleZoom() {{{1
" zoom (maximize/minimize) the NERDTree window
function! s:UI.toggleZoom()
if exists("b:NERDTreeZoomed") && b:NERDTreeZoomed
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
exec "silent vertical resize ". size
let b:NERDTreeZoomed = 0
else
exec "vertical resize"
let b:NERDTreeZoomed = 1
endif
endfunction

View file

@ -82,13 +82,15 @@ endfunction
function! s:promptToRenameBuffer(bufnum, msg, newFileName) function! s:promptToRenameBuffer(bufnum, msg, newFileName)
echo a:msg echo a:msg
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y' if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
let quotedFileName = "'" . a:newFileName . "'"
" 1. ensure that a new buffer is loaded " 1. ensure that a new buffer is loaded
exec "badd " . a:newFileName exec "badd " . quotedFileName
" 2. ensure that all windows which display the just deleted filename " 2. ensure that all windows which display the just deleted filename
" display a buffer for a new filename. " display a buffer for a new filename.
let s:originalTabNumber = tabpagenr() let s:originalTabNumber = tabpagenr()
let s:originalWindowNumber = winnr() let s:originalWindowNumber = winnr()
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':e! " . a:newFileName . "' | endif" let editStr = g:NERDTreePath.New(a:newFileName).str({'format': 'Edit'})
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':e! " . editStr . "' | endif"
exec "tabnext " . s:originalTabNumber exec "tabnext " . s:originalTabNumber
exec s:originalWindowNumber . "wincmd w" exec s:originalWindowNumber . "wincmd w"
" 3. We don't need a previous buffer anymore " 3. We don't need a previous buffer anymore
@ -114,7 +116,10 @@ function! NERDTreeAddNode()
let parentNode = b:NERDTreeRoot.findNode(newPath.getParent()) let parentNode = b:NERDTreeRoot.findNode(newPath.getParent())
let newTreeNode = g:NERDTreeFileNode.New(newPath) let newTreeNode = g:NERDTreeFileNode.New(newPath)
if parentNode.isOpen || !empty(parentNode.children) if empty(parentNode)
call b:NERDTreeRoot.refresh()
call b:NERDTree.render()
elseif parentNode.isOpen || !empty(parentNode.children)
call parentNode.addChild(newTreeNode, 1) call parentNode.addChild(newTreeNode, 1)
call NERDTreeRender() call NERDTreeRender()
call newTreeNode.putCursorHere(1, 0) call newTreeNode.putCursorHere(1, 0)
@ -138,7 +143,7 @@ function! NERDTreeMoveNode()
endif endif
try try
let bufnum = bufnr(curNode.path.str()) let bufnum = bufnr("^".curNode.path.str()."$")
call curNode.rename(newNodePath) call curNode.rename(newNodePath)
call NERDTreeRender() call NERDTreeRender()
@ -186,7 +191,7 @@ function! NERDTreeDeleteNode()
"if the node is open in a buffer, ask the user if they want to "if the node is open in a buffer, ask the user if they want to
"close that buffer "close that buffer
let bufnum = bufnr(currentNode.path.str()) let bufnum = bufnr("^".currentNode.path.str()."$")
if buflisted(bufnum) if buflisted(bufnum)
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
call s:promptToDelBuffer(bufnum, prompt) call s:promptToDelBuffer(bufnum, prompt)
@ -224,7 +229,10 @@ function! NERDTreeCopyNode()
if confirmed if confirmed
try try
let newNode = currentNode.copy(newNodePath) let newNode = currentNode.copy(newNodePath)
if !empty(newNode) if empty(newNode)
call b:NERDTreeRoot.refresh()
call b:NERDTree.render()
else
call NERDTreeRender() call NERDTreeRender()
call newNode.putCursorHere(0, 0) call newNode.putCursorHere(0, 0)
endif endif

View file

@ -45,28 +45,30 @@ function! s:initVariable(var, value)
endfunction endfunction
"SECTION: Init variable calls and other random constants {{{2 "SECTION: Init variable calls and other random constants {{{2
call s:initVariable("g:NERDChristmasTree", 1)
call s:initVariable("g:NERDTreeAutoCenter", 1) call s:initVariable("g:NERDTreeAutoCenter", 1)
call s:initVariable("g:NERDTreeAutoCenterThreshold", 3) call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
call s:initVariable("g:NERDTreeCaseSensitiveSort", 0) call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
call s:initVariable("g:NERDTreeSortHiddenFirst", 1)
call s:initVariable("g:NERDTreeChDirMode", 0) call s:initVariable("g:NERDTreeChDirMode", 0)
call s:initVariable("g:NERDTreeMinimalUI", 0) call s:initVariable("g:NERDTreeMinimalUI", 0)
if !exists("g:NERDTreeIgnore") if !exists("g:NERDTreeIgnore")
let g:NERDTreeIgnore = ['\~$'] let g:NERDTreeIgnore = ['\~$']
endif endif
call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks') call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks')
call s:initVariable("g:NERDTreeBookmarksSort", 1)
call s:initVariable("g:NERDTreeHighlightCursorline", 1) call s:initVariable("g:NERDTreeHighlightCursorline", 1)
call s:initVariable("g:NERDTreeHijackNetrw", 1) call s:initVariable("g:NERDTreeHijackNetrw", 1)
call s:initVariable("g:NERDTreeMouseMode", 1) call s:initVariable("g:NERDTreeMouseMode", 1)
call s:initVariable("g:NERDTreeNotificationThreshold", 100) call s:initVariable("g:NERDTreeNotificationThreshold", 100)
call s:initVariable("g:NERDTreeQuitOnOpen", 0) call s:initVariable("g:NERDTreeQuitOnOpen", 0)
call s:initVariable("g:NERDTreeRespectWildIgnore", 0)
call s:initVariable("g:NERDTreeShowBookmarks", 0) call s:initVariable("g:NERDTreeShowBookmarks", 0)
call s:initVariable("g:NERDTreeShowFiles", 1) call s:initVariable("g:NERDTreeShowFiles", 1)
call s:initVariable("g:NERDTreeShowHidden", 0) call s:initVariable("g:NERDTreeShowHidden", 0)
call s:initVariable("g:NERDTreeShowLineNumbers", 0) call s:initVariable("g:NERDTreeShowLineNumbers", 0)
call s:initVariable("g:NERDTreeSortDirs", 1) call s:initVariable("g:NERDTreeSortDirs", 1)
call s:initVariable("g:NERDTreeDirArrows", !nerdtree#runningWindows()) call s:initVariable("g:NERDTreeDirArrows", !nerdtree#runningWindows())
call s:initVariable("g:NERDTreeCasadeOpenSingleChildDir", 1) call s:initVariable("g:NERDTreeCascadeOpenSingleChildDir", 1)
if !exists("g:NERDTreeSortOrder") if !exists("g:NERDTreeSortOrder")
let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$'] let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
@ -140,20 +142,13 @@ call nerdtree#loadClassFiles()
" SECTION: Commands {{{1 " SECTION: Commands {{{1
"============================================================ "============================================================
"init the command that users start the nerd tree with call nerdtree#ui_glue#setupCommands()
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.TogglePrimary('<args>')
command! -n=0 -bar NERDTreeClose :call nerdtree#closeTreeIfOpen()
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('<args>')
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
command! -n=0 -bar NERDTreeFind call nerdtree#findAndRevealPath()
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
" SECTION: Auto commands {{{1 " SECTION: Auto commands {{{1
"============================================================ "============================================================
augroup NERDTree augroup NERDTree
"Save the cursor position whenever we close the nerd tree "Save the cursor position whenever we close the nerd tree
exec "autocmd BufWinLeave ". g:NERDTreeCreator.BufNamePrefix() ."* call nerdtree#saveScreenState()" exec "autocmd BufLeave ". g:NERDTreeCreator.BufNamePrefix() ."* call b:NERDTree.ui.saveScreenState()"
"disallow insert mode in the NERDTree "disallow insert mode in the NERDTree
exec "autocmd BufEnter ". g:NERDTreeCreator.BufNamePrefix() ."* stopinsert" exec "autocmd BufEnter ". g:NERDTreeCreator.BufNamePrefix() ."* stopinsert"
@ -199,7 +194,7 @@ endfunction
function! NERDTreeCWD() function! NERDTreeCWD()
call NERDTreeFocus() call NERDTreeFocus()
call nerdtree#chRootCwd() call nerdtree#ui_glue#chRootCwd()
endfunction endfunction
" SECTION: Post Source Actions {{{1 " SECTION: Post Source Actions {{{1
call nerdtree#postSourceActions() call nerdtree#postSourceActions()

View file

@ -1,44 +1,64 @@
let s:tree_up_dir_line = '.. (up a dir)' let s:tree_up_dir_line = '.. (up a dir)'
"NERDTreeFlags are syntax items that should be invisible, but give clues as to syn match NERDTreeIgnore #\~#
"how things should be highlighted syn match NERDTreeIgnore #\[RO\]#
syn match NERDTreeFlag #\~#
syn match NERDTreeFlag #\[RO\]#
"highlighting for the .. (up dir) line at the top of the tree "highlighting for the .. (up dir) line at the top of the tree
execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#" execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#"
"highlighting for the ~/+ symbols for the directory nodes
syn match NERDTreeClosable #\~\<#
syn match NERDTreeClosable #\~\.#
syn match NERDTreeOpenable #+\<#
syn match NERDTreeOpenable #+\.#he=e-1
"highlighting for the tree structural parts
syn match NERDTreePart #|#
syn match NERDTreePart #`#
syn match NERDTreePartFile #[|`]-#hs=s+1 contains=NERDTreePart
"quickhelp syntax elements "quickhelp syntax elements
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1 syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#ms=s+2,me=e-1
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1 syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#ms=s+2,me=e-1
syn match NERDTreeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=NERDTreeFlag syn match NERDTreeHelpTitle #" .*\~#ms=s+2,me=e-1
syn match NERDTreeToggleOn #".*(on)#hs=e-2,he=e-1 contains=NERDTreeHelpKey syn match NERDTreeToggleOn #(on)#ms=s+1,he=e-1
syn match NERDTreeToggleOff #".*(off)#hs=e-3,he=e-1 contains=NERDTreeHelpKey syn match NERDTreeToggleOff #(off)#ms=e-3,me=e-1
syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3 syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3
syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeFlag,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeIgnore,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand
"highlighting for readonly files
syn match NERDTreeRO #.*\[RO\]#hs=s+2 contains=NERDTreeFlag,NERDTreeBookmark,NERDTreePart,NERDTreePartFile
"highlighting for sym links "highlighting for sym links
syn match NERDTreeLink #[^-| `].* -> # contains=NERDTreeBookmark,NERDTreeOpenable,NERDTreeClosable,NERDTreeDirSlash syn match NERDTreeLinkTarget #->.*# containedin=NERDTreeDir,NERDTreeFile
syn match NERDTreeLinkFile #.* ->#me=e-3 containedin=NERDTreeFile
syn match NERDTreeLinkDir #.*/ ->#me=e-3 containedin=NERDTreeDir
"highlighing for directory nodes and file nodes "highlighing for directory nodes and file nodes
syn match NERDTreeDirSlash #/# syn match NERDTreeDirSlash #/# containedin=NERDTreeDir
syn match NERDTreeDir #[^-| `].*/# contains=NERDTreeLink,NERDTreeDirSlash,NERDTreeOpenable,NERDTreeClosable
syn match NERDTreeExecFile #[|` ].*\*\($\| \)# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark if g:NERDTreeDirArrows
syn match NERDTreeFile #|-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile syn match NERDTreeClosable #▾# containedin=NERDTreeDir,NERDTreeFile
syn match NERDTreeFile #`-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile syn match NERDTreeOpenable #▸# containedin=NERDTreeDir,NERDTreeFile
syn match NERDTreeDir #[^▾▸ ].*/#
syn match NERDTreeExecFile #^ .*\*\($\| \)# contains=NERDTreeRO,NERDTreeBookmark
syn match NERDTreeFile #^[^"\.▾▸] *[^▾▸]*# contains=NERDTreeLink,NERDTreeRO,NERDTreeBookmark,NERDTreeExecFile
"highlighting for readonly files
syn match NERDTreeRO # *\zs.*\ze \[RO\]# contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreeFile
syn match NERDTreeFlags #^ *\zs\[.\]# containedin=NERDTreeFile
syn match NERDTreeFlags #\[.\]# containedin=NERDTreeDir
else
"highlighting for the ~/+ symbols for the directory nodes
syn match NERDTreeClosable #\~\<#
syn match NERDTreeClosable #\~\.#
syn match NERDTreeOpenable #+\<#
syn match NERDTreeOpenable #+\.#he=e-1
"highlighting for the tree structural parts
syn match NERDTreePart #|#
syn match NERDTreePart #`#
syn match NERDTreePartFile #[|`]-#hs=s+1 contains=NERDTreePart
syn match NERDTreeDir #[^-| `].*/# contains=NERDTreeLink,NERDTreeOpenable,NERDTreeClosable
syn match NERDTreeExecFile #[|` ].*\*\($\| \)# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark
syn match NERDTreeFile #|-.*# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
syn match NERDTreeFile #`-.*# contains=NERDTreeLink,NERDTreePart,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
"highlighting for readonly files
syn match NERDTreeRO #|-.*\[RO\]#he=e-5 contains=NERDTreeIgnore,NERDTreeBookmark,NERDTreePart,NERDTreePartFile
syn match NERDTreeFlags #-\[.\]# containedin=NERDTreeFile,NERDTreePartFile
syn match NERDTreeFlags #[+~]\zs\[.\]# containedin=NERDTreeDir
endif
syn match NERDTreeCWD #^[</].*$# syn match NERDTreeCWD #^[</].*$#
"highlighting for bookmarks "highlighting for bookmarks
@ -50,19 +70,10 @@ syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmark
syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader
syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader
if exists("g:NERDChristmasTree") && g:NERDChristmasTree hi def link NERDTreePart Special
hi def link NERDTreePart Special hi def link NERDTreePartFile Type
hi def link NERDTreePartFile Type hi def link NERDTreeExecFile Title
hi def link NERDTreeFile Normal hi def link NERDTreeDirSlash Identifier
hi def link NERDTreeExecFile Title
hi def link NERDTreeDirSlash Identifier
hi def link NERDTreeClosable Type
else
hi def link NERDTreePart Normal
hi def link NERDTreePartFile Normal
hi def link NERDTreeFile Normal
hi def link NERDTreeClosable Title
endif
hi def link NERDTreeBookmarksHeader statement hi def link NERDTreeBookmarksHeader statement
hi def link NERDTreeBookmarksLeader ignore hi def link NERDTreeBookmarksLeader ignore
@ -76,13 +87,19 @@ hi def link NERDTreeHelpTitle Macro
hi def link NERDTreeToggleOn Question hi def link NERDTreeToggleOn Question
hi def link NERDTreeToggleOff WarningMsg hi def link NERDTreeToggleOff WarningMsg
hi def link NERDTreeLinkTarget Type
hi def link NERDTreeLinkFile Macro
hi def link NERDTreeLinkDir Macro
hi def link NERDTreeDir Directory hi def link NERDTreeDir Directory
hi def link NERDTreeUp Directory hi def link NERDTreeUp Directory
hi def link NERDTreeFile Normal
hi def link NERDTreeCWD Statement hi def link NERDTreeCWD Statement
hi def link NERDTreeLink Macro
hi def link NERDTreeOpenable Title hi def link NERDTreeOpenable Title
hi def link NERDTreeFlag ignore hi def link NERDTreeClosable Title
hi def link NERDTreeIgnore ignore
hi def link NERDTreeRO WarningMsg hi def link NERDTreeRO WarningMsg
hi def link NERDTreeBookmark Statement hi def link NERDTreeBookmark Statement
hi def link NERDTreeFlags Number
hi def link NERDTreeCurrentNode Search hi def link NERDTreeCurrentNode Search

View file

@ -12,6 +12,19 @@ function! GotoFile(w)
let pos = "" let pos = ""
let fname = curword let fname = curword
endif endif
" check exists file.
if filereadable(fname)
let fullname = fname
else
" try find file with prefix by working directory
let fullname = getcwd() . '/' . fname
if ! filereadable(fullname)
" the last try, using current directory based on file opened.
let fullname = expand('%:h') . '/' . fname
endif
endif
" Open new window if requested " Open new window if requested
if a:w == "new" if a:w == "new"
new new

View file

@ -0,0 +1,4 @@
*~
*.swp
tags
.DS_Store

View file

@ -0,0 +1,105 @@
# CONTRIBUTING
- - -
1\. [Bug reports / GitHub issues](#bugreps)
2\. [Submitting a patch](#patches)
3\. [General style notes](#generalstyle)
4\. [Syntax checker notes](#checkerstyle)
- - -
<a name="bugreps"></a>
## 1. Bug reports / GitHub issues
Please note that the preferred channel for posting bug reports is the
[issue tracker at GitHub][0]. Reports posted elsewhere are less likely
to be seen by the core team.
When reporting a bug make sure you search the existing GitHub issues
for the same/similar issues. If you find one, feel free to add a `+1`
comment with any additional information that may help us solve the
issue.
When creating a new issue be sure to state the following:
* steps to reproduce the bug;
* the version of Vim you are using (run `:ver` to find out);
* the version of syntastic you are using (see `:SyntasticInfo`).
For syntax checker bugs also state the version of the checker executable
that you are using. Adding debugging information is typically useful
too:
* open a file handled by your checker;
* set `g:syntastic_debug` to 1 or 3;
* run the checker;
* copy the output of `:mes`.
<a name="patches"></a>
## 2. Submitting a patch
Before you consider adding features to syntastic, _please_ spend a few
minutes (re-)reading the latest version of the [manual][1]. Syntastic
is changing rapidly at times, and it's quite possible that some of the
features you want to add exist already.
To submit a patch:
* fork the [repo][2] on GitHub;
* make a [topic branch][3] and start hacking;
* submit a pull request based off your topic branch.
Small, focused patches are preferred.
Large changes to the code should be discussed with the core team first.
Create an issue and explain your plan and see what we say.
Also make sure to update the manual whenever applicable. Nobody can use
features that aren't documented.
<a name="generalstyle"></a>
## 3. General style notes
Follow the coding conventions/styles used in the syntastic core:
* use 4 space indents;
* don't use abbreviated keywords - e.g. use `endfunction`, not `endfun`
(there's always room for more fun!);
* don't use `l:` prefixes for variables unless actually required (i.e.
almost never);
* code for maintainability; we would rather a function be a couple of
lines longer and have (for example) some [explaining variables][4] to
aid readability.
<a name="checkerstyle"></a>
## 4. Syntax checker notes
Make sure to read the [guide][5] if you plan to add new syntax checkers.
Use the existing checkers as templates, rather than writing everything
from scratch.
The preferred style for error format strings is one "clause" per line.
E.g. (from the `coffee` checker):
```vim
let errorformat =
\ '%E%f:%l:%c: %trror: %m,' .
\ 'Syntax%trror: In %f\, %m on line %l,' .
\ '%EError: In %f\, Parse error on line %l: %m,' .
\ '%EError: In %f\, %m on line %l,' .
\ '%W%f(%l): lint warning: %m,' .
\ '%W%f(%l): warning: %m,' .
\ '%E%f(%l): SyntaxError: %m,' .
\ '%-Z%p^,' .
\ '%-G%.%#'
```
[0]: https://github.com/scrooloose/syntastic/issues
[1]: https://github.com/scrooloose/syntastic/blob/master/doc/syntastic.txt
[2]: https://github.com/scrooloose/syntastic
[3]: https://github.com/dchelimsky/rspec/wiki/Topic-Branches#using-topic-branches-when-contributing-patches
[4]: http://www.refactoring.com/catalog/extractVariable.html
[5]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide

View file

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View file

@ -0,0 +1,462 @@
,
/ \,,_ .'|
,{{| /}}}}/_.' _____________________________________________
}}}}` '{{' '. / \
{{{{{ _ ;, \ / Ladies and Gentlemen, \
,}}}}}} /o`\ ` ;) | |
{{{{{{ / ( | this is ... |
}}}}}} | \ | |
{{{{{{{{ \ \ | |
}}}}}}}}} '.__ _ | | _____ __ __ _ |
{{{{{{{{ /`._ (_\ / | / ___/__ ______ / /_____ ______/ /_(_)____ |
}}}}}}' | //___/ --=: \__ \/ / / / __ \/ __/ __ `/ ___/ __/ / ___/ |
jgs `{{{{` | '--' | ___/ / /_/ / / / / /_/ /_/ (__ ) /_/ / /__ |
}}}` | /____/\__, /_/ /_/\__/\__,_/____/\__/_/\___/ |
| /____/ |
| /
\_____________________________________________/
- - -
1. [Introduction](#introduction)
2. [Installation](#installation)
2.1. [Requirements](#requirements)
2.2. [Installing syntastic with Pathogen](#installpathogen)
3. [Recommended settings](#settings)
4. [FAQ](#faq)
4.1. [I installed syntastic but it isn't reporting any errors...](#faqinfo)
4.2. [The `python` checker complains about syntactically valid Python 3 constructs...](#faqpython3)
4.3. [Are there any local checkers for HTML5 that I can use with syntastic?](#faqhtml5)
4.4. [The `perl` checker has stopped working...](#faqperl)
4.5. [What happened to the `rustc` checker?](#faqrust)
4.6. [What happened to the `xcrun` checker?](#faqxcrun)
4.7. [I run a checker and the location list is not updated...](#faqloclist)
4.7. [I run`:lopen` or `:lwindow` and the error window is empty...](#faqloclist)
4.8. [How can I pass additional arguments to a checker?](#faqargs)
4.9. [Syntastic supports several checkers for my filetype - how do I tell which one(s) to use?](#faqcheckers)
4.10. [What is the difference between syntax checkers and style checkers?](#faqstyle)
4.11. [I have enabled multiple checkers for the current filetype. How can I display all of the errors from all of the checkers together?](#faqaggregate)
4.12. [How can I jump between the different errors without using the location list at the bottom of the window?](#faqlnext)
4.13. [The error window is closed automatically when I :quit the current buffer but not when I :bdelete it?](#faqbdelete)
5. [Resources](#otherresources)
- - -
<a name="introduction"></a>
## 1\. Introduction
Syntastic is a syntax checking plugin for [Vim][13] that runs files through
external syntax checkers and displays any resulting errors to the user. This
can be done on demand, or automatically as files are saved. If syntax errors
are detected, the user is notified and is happy because they didn't have to
compile their code or execute their script to find them.
At the time of this writing, syntastic has checking plugins for ActionScript,
Ada, API Blueprint, AppleScript, AsciiDoc, ASM, BEMHTML, Bro, Bourne shell,
C, C++, C#, Cabal, Chef, CoffeeScript, Coco, Coq, CSS, Cucumber, CUDA, D,
Dart, DocBook, Dust, Elixir, Erlang, eRuby, Fortran, Gentoo metadata, GLSL,
Go, Haml, Haskell, Haxe, Handlebars, HSS, HTML, Java, JavaScript, JSON, JSX,
LESS, Lex, Limbo, LISP, LLVM intermediate language, Lua, Markdown, MATLAB,
NASM, Objective-C, Objective-C++, OCaml, Perl, Perl POD, PHP, gettext Portable
Object, OS X and iOS property lists, Puppet, Python, R, Racket, Relax NG,
reStructuredText, RPM spec, Ruby, SASS/SCSS, Scala, Slim, SML, Tcl, TeX,
Texinfo, Twig, TypeScript, Vala, Verilog, VHDL, VimL, xHtml, XML, XSLT, YACC,
YAML, z80, Zope page templates, and zsh. See the [wiki][3] for details about
the corresponding supported checkers.
A number of third-party Vim plugins also provide checkers for syntastic,
for example: [omnisharp-vim][25], [rust.vim][12], [syntastic-extras][26],
[syntastic-more][27], and [vim-swift][24].
Below is a screenshot showing the methods that Syntastic uses to display syntax
errors. Note that, in practise, you will only have a subset of these methods
enabled.
![Screenshot 1][0]
1. Errors are loaded into the location list for the corresponding window.
2. When the cursor is on a line containing an error, the error message is echoed in the command window.
3. Signs are placed beside lines with errors - note that warnings are displayed in a different color.
4. There is a configurable statusline flag you can include in your statusline config.
5. Hover the mouse over a line containing an error and the error message is displayed as a balloon.
6. (not shown) Highlighting errors with syntax highlighting. Erroneous parts of lines can be highlighted.
<a name="installation"></a>
## 2\. Installation
<a name="requirements"></a>
### 2.1\. Requirements
Syntastic itself has rather relaxed requirements: it doesn't have any external
dependencies, and it needs a version of [Vim][13] compiled with a few common
features: `autocmd`, `eval`, `file_in_path`, `modify_fname`, `quickfix`,
`reltime`, and `user_commands`. Not all possible combinations of features that
include the ones above make equal sense on all operating systems, but Vim
version 7 or later with the "normal", "big", or "huge" feature sets should be
fine.
Syntastic should work with any modern plugin managers for Vim, such as
[NeoBundle][14], [Pathogen][1], [Vim-Addon-Manager][15], [Vim-Plug][16], or
[Vundle][17]. Instructions for installing syntastic with [Pathogen][1] are
included below for completeness.
Last but not least: syntastic doesn't know how to do any syntax checks by
itself. In order to get meaningful results you need to install external
checkers corresponding to the types of files you use. Please consult the
[wiki][3] for a list of supported checkers.
<a name="installpathogen"></a>
### 2.2\. Installing syntastic with Pathogen
If you already have [Pathogen][1] working then skip [Step 1](#step1) and go to
[Step 2](#step2).
<a name="step1"></a>
#### 2.2.1\. Step 1: Install pathogen.vim
First I'll show you how to install Tim Pope's [Pathogen][1] so that it's easy to
install syntastic. Do this in your terminal so that you get the `pathogen.vim`
file and the directories it needs:
```sh
mkdir -p ~/.vim/autoload ~/.vim/bundle && \
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
```
Next you *need* to add this to your `~/.vimrc`:
```vim
execute pathogen#infect()
```
<a name="step2"></a>
#### 2.2.2\. Step 2: Install syntastic as a Pathogen bundle
You now have pathogen installed and can put syntastic into `~/.vim/bundle` like
this:
```sh
cd ~/.vim/bundle && \
git clone https://github.com/scrooloose/syntastic.git
```
Quit vim and start it back up to reload it, then type:
```vim
:Helptags
```
If you get an error when you do this, then you probably didn't install
[Pathogen][1] right. Go back to [Step 1](#step1) and make sure you did the
following:
1. Created both the `~/.vim/autoload` and `~/.vim/bundle` directories.
2. Added the `execute pathogen#infect()` line to your `~/.vimrc` file
3. Did the `git clone` of syntastic inside `~/.vim/bundle`
4. Have permissions to access all of these directories.
<a name="settings"></a>
## 3\. Recommended settings
Syntastic has a large number of options that can be configured, and the
defaults are not particularly well suitable for new users. It is recommended
that you start by adding the following lines to your `vimrc` file, and return
to them after reading the manual (see `:help syntastic` in Vim):
```vim
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*
let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 1
let g:syntastic_check_on_open = 1
let g:syntastic_check_on_wq = 0
```
<a name="faq"></a>
## 4\. FAQ
<a name="faqinfo"></a>
__4.1. Q. I installed syntastic but it isn't reporting any errors...__
A. The most likely reason is that none of the syntax checkers that it requires
is installed. For example: by default, python requires either `flake8` or
`pylint` to be installed and in your `$PATH`. To see which executables are
supported, look at the [wiki][3]. Note that aliases do not work; the actual
executables must be available in your `$PATH`. Symbolic links are okay though.
You can see syntastic's idea of available checkers by running `:SyntasticInfo`.
A second probable reason is that none of the available checkers are
enabled. Syntastic comes preconfigured with a default list of enabled checkers
per filetype, but this list is kept short in order to prevent slowing down Vim
or trying to run conflicting checks. The command `:SyntasticInfo` will show you
which checkers are enabled. You can tell syntastic which checkers (among the
available ones) you want to run by setting `g:syntastic_<filetype>_checkers` in
your `vimrc` (see [below](#faqcheckers)).
A third possible reason is that the `$PATH` seen by syntastic might not be same
as the `$PATH` in your login shell. Syntastic runs checkers using the shell
pointed to by Vim's `shell` (or by `g:syntastic_shell`, if set), and that's the
shell you need to configure to set the proper `$PATH` and environment variables
for your checkers. You can see syntastic's idea of `$PATH` by running
```vim
:echo syntastic#util#system('echo "$PATH"')
```
on UNIX and Mac OS-X systems, or
```vim
:echo syntastic#util#system('echo %PATH%')
```
on Windows.
Finally, another reason it could fail is that either the command line options
or the error output for a syntax checker may have changed. In this case, make
sure you have the latest version of the syntax checker installed. If it still
fails then post an [issue][4] - or better yet, create a pull request.
<a name="faqpython3"></a>
__4.2. Q. The `python` checker complains about syntactically valid Python 3 constructs...__
A. Configure the `python` checker to call a Python 3 interpreter rather than
Python 2, e.g:
```vim
let g:syntastic_python_python_exec = '/path/to/python3'
```
<a name="faqhtml5"></a>
__4.3. Q. Are there any local checkers for HTML5 that I can use with syntastic?__
[HTML Tidy][18] has a fork named [HTML Tidy for HTML5][19]. It's a drop
in replacement, and syntastic can use it without changes. Just install it
somewhere and point `g:syntastic_html_tidy_exec` to its executable:
```vim
let g:syntastic_html_tidy_exec = 'tidy5'
```
Alternatively, you can install [vnu.jar][21] from the [validator.nu][20]
project and run it as a [HTTP server][23]:
```sh
$ java -Xss512k -cp /path/to/vnu.jar nu.validator.servlet.Main 8888
```
Then you can [configure][22] syntastic to use it:
```vim
let g:syntastic_html_validator_api = 'http://localhost:8888/'
```
<a name="faqperl"></a>
__4.4. Q. The `perl` checker has stopped working...__
A. The `perl` checker runs `perl -c` against your file, which in turn
__executes__ any `BEGIN`, `UNITCHECK`, and `CHECK` blocks, and any `use`
statements in your file (cf. [perlrun][10]). This is probably fine if you
wrote the file yourself, but it's a security problem if you're checking third
party files. Since there is currently no way to disable this behaviour while
still producing useful results, the checker is now disabled by default. To
(re-)enable it, make sure the `g:syntastic_perl_checkers` list includes `perl`,
and set `g:syntastic_enable_perl_checker` to 1 in your `vimrc`:
```vim
let g:syntastic_enable_perl_checker = 1
```
<a name="faqrust"></a>
__4.5. Q. What happened to the `rustc` checker?__
A. It is now part of the [rust.vim][12] plugin. If you install this plugin the
checker should be picked up automatically by syntastic.
<a name="faqxcrun"></a>
__4.6. Q. What happened to the `xcrun` checker?__
A. The `xcrun` checker used to have a security problem and it has been removed.
A better checker for __Swift__ is part of the [vim-swift][24] plugin. If you
install this plugin the checker should be picked up automatically by syntastic.
<a name="faqloclist"></a>
__4.7. Q. I run a checker and the location list is not updated...__
__4.7. Q. I run`:lopen` or `:lwindow` and the error window is empty...__
A. By default the location list is changed only when you run the `:Errors`
command, in order to minimise conflicts with other plugins. If you want the
location list to always be updated when you run the checkers, add this line to
your `vimrc`:
```vim
let g:syntastic_always_populate_loc_list = 1
```
<a name="faqargs"></a>
__4.8. Q. How can I pass additional arguments to a checker?__
A. Almost all syntax checkers use the `makeprgBuild()` function. Those checkers
that do can be configured using global variables. The general form of the
global `args` variables is `syntastic_<filetype>_<checker>_args`.
So, If you wanted to pass `--my --args --here` to the ruby mri checker you
would add this line to your `vimrc`:
```vim
let g:syntastic_ruby_mri_args = "--my --args --here"
```
See `:help syntastic-checker-options` for more information.
<a name="faqcheckers"></a>
__4.9. Q. Syntastic supports several checkers for my filetype - how do I tell it
which one(s) to use?__
A. Stick a line like this in your `vimrc`:
```vim
let g:syntastic_<filetype>_checkers = ['<checker-name>']
```
To see the list of supported checkers for your filetype look at the
[wiki][3].
e.g. Python has the following checkers, among others: `flake8`, `pyflakes`,
`pylint` and a native `python` checker.
To tell syntastic to use `pylint`, you would use this setting:
```vim
let g:syntastic_python_checkers = ['pylint']
```
Checkers can be chained together like this:
```vim
let g:syntastic_php_checkers = ['php', 'phpcs', 'phpmd']
```
This is telling syntastic to run the `php` checker first, and if no errors are
found, run `phpcs`, and then `phpmd`.
You can also run checkers explicitly by calling `:SyntasticCheck <checker>`.
e.g. to run `phpcs` and `phpmd`:
```vim
:SyntasticCheck phpcs phpmd
```
This works for any checkers available for the current filetype, even if they
aren't listed in `g:syntastic_<filetype>_checkers`. You can't run checkers for
"foreign" filetypes though (e.g. you can't run, say, a Python checker if the
filetype of the current file is `php`).
<a name="faqstyle"></a>
__4.10. Q. What is the difference between syntax checkers and style checkers?__
A. The errors and warnings they produce are highlighted differently and can
be filtered by different rules, but otherwise the distinction is pretty much
arbitrary. There is an ongoing effort to keep things consistent, so you can
_generally_ expect messages produced by syntax checkers to be _mostly_ related
to syntax, and messages produced by style checkers to be _mostly_ about style.
But there can be no formal guarantee that, say, a style checker that runs into
a syntax error wouldn't die with a fatal message, nor that a syntax checker
wouldn't give you warnings against using some constructs as being bad practice.
There is also no guarantee that messages marked as "style" are less severe than
the ones marked as "syntax" (whatever that might mean). And there are even a
few Frankenstein checkers (for example `flake8` and `pylama`) that, by their
nature, produce both kinds of messages. Syntastic is not smart enough to be
able to sort out these things by itself.
In fact it's more useful to look at this from the perspective of filtering
unwanted messages, rather than as an indicator of severity levels. The
distinction between syntax and style is orthogonal to the distinction between
errors and warnings, and thus you can turn off messages based on level, on
type, or both.
e.g. To disable all style messages:
```vim
let g:syntastic_quiet_messages = { "type": "style" }
```
See `:help syntastic_quiet_messages` for details.
<a name="faqaggregate"></a>
__4.11. Q. I have enabled multiple checkers for the current filetype. How can I
display all of the errors from all of the checkers together?__
A. Set `g:syntastic_aggregate_errors` to 1 in your `vimrc`:
```vim
let g:syntastic_aggregate_errors = 1
```
See `:help syntastic-aggregating-errors` for more details.
<a name="faqlnext"></a>
__4.12. Q. How can I jump between the different errors without using the location
list at the bottom of the window?__
A. Vim provides several built-in commands for this. See `:help :lnext` and
`:help :lprevious`.
If you use these commands a lot then you may want to add shortcut mappings to
your `vimrc`, or install something like [unimpaired][2], which provides such
mappings (among other things).
<a name="faqbdelete"></a>
__4.13. Q. The error window is closed automatically when I :quit the current buffer
but not when I :bdelete it?__
A. There is no safe way to handle that situation automatically, but you can
work around it:
```vim
nnoremap <silent> <C-d> :lclose<CR>:bdelete<CR>
cabbrev <silent> bd lclose\|bdelete
```
<a name="otherresources"></a>
## 5\. Resources
The preferred place for posting suggestions, reporting bugs, and general
discussions related to syntastic is the [issue tracker at GitHub][4].
A guide for writing syntax checkers can be found in the [wiki][11].
There are also a dedicated [google group][5], and a
[syntastic tag at StackOverflow][6].
Syntastic aims to provide a common interface to syntax checkers for as many
languages as possible. For particular languages, there are, of course, other
plugins that provide more functionality than syntastic. You might want to take
a look at [jedi-vim][7], [python-mode][8], or [YouCompleteMe][9].
[0]: https://github.com/scrooloose/syntastic/raw/master/_assets/screenshot_1.png
[1]: https://github.com/tpope/vim-pathogen
[2]: https://github.com/tpope/vim-unimpaired
[3]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers
[4]: https://github.com/scrooloose/syntastic/issues
[5]: https://groups.google.com/group/vim-syntastic
[6]: http://stackoverflow.com/questions/tagged/syntastic
[7]: https://github.com/davidhalter/jedi-vim
[8]: https://github.com/klen/python-mode
[9]: http://valloric.github.io/YouCompleteMe/
[10]: http://perldoc.perl.org/perlrun.html#*-c*
[11]: https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide
[12]: https://github.com/rust-lang/rust.vim
[13]: http://www.vim.org/
[14]: https://github.com/Shougo/neobundle.vim
[15]: https://github.com/MarcWeber/vim-addon-manager
[16]: https://github.com/junegunn/vim-plug/
[17]: https://github.com/gmarik/Vundle.vim
[18]: http://tidy.sourceforge.net/
[19]: http://www.htacg.org/tidy-html5/
[20]: http://about.validator.nu/
[21]: https://github.com/validator/validator/releases/latest
[22]: https://github.com/scrooloose/syntastic/wiki/HTML%3A---validator
[23]: http://validator.github.io/validator/#standalone
[24]: https://github.com/kballard/vim-swift
[25]: https://github.com/OmniSharp/omnisharp-vim
[26]: https://github.com/myint/syntastic-extras
[27]: https://github.com/roktas/syntastic-more
<!--
vim:tw=79:sw=4:
-->

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View file

@ -0,0 +1,345 @@
if exists("g:loaded_syntastic_c_autoload") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_c_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
" Public functions {{{1
" convenience function to determine the 'null device' parameter
" based on the current operating system
function! syntastic#c#NullOutput() abort " {{{2
let known_os = has('unix') || has('mac') || syntastic#util#isRunningWindows()
return known_os ? '-o ' . syntastic#util#DevNull() : ''
endfunction " }}}2
" read additional compiler flags from the given configuration file
" the file format and its parsing mechanism is inspired by clang_complete
function! syntastic#c#ReadConfig(file) abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: looking for', a:file)
" search upwards from the current file's directory
let config = findfile(a:file, '.;')
if config == ''
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: file not found')
return ''
endif
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: config file:', config)
if !filereadable(config)
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: file unreadable')
return ''
endif
" convert filename into absolute path
let filepath = fnamemodify(config, ':p:h')
" try to read config file
try
let lines = readfile(config)
catch /\m^Vim\%((\a\+)\)\=:E48[45]/
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, 'ReadConfig: error reading file')
return ''
endtry
" filter out empty lines and comments
call filter(lines, 'v:val !~ ''\v^(\s*#|$)''')
" remove leading and trailing spaces
call map(lines, 'substitute(v:val, ''\m^\s\+'', "", "")')
call map(lines, 'substitute(v:val, ''\m\s\+$'', "", "")')
let parameters = []
for line in lines
let matches = matchstr(line, '\m\C^\s*-I\s*\zs.\+')
if matches != ''
" this one looks like an absolute path
if match(matches, '\m^\%(/\|\a:\)') != -1
call add(parameters, '-I' . matches)
else
call add(parameters, '-I' . filepath . syntastic#util#Slash() . matches)
endif
else
call add(parameters, line)
endif
endfor
return join(map(parameters, 'syntastic#util#shescape(v:val)'))
endfunction " }}}2
" GetLocList() for C-like compilers
function! syntastic#c#GetLocList(filetype, subchecker, options) abort " {{{2
try
let flags = s:_get_cflags(a:filetype, a:subchecker, a:options)
catch /\m\C^Syntastic: skip checks$/
return []
endtry
let makeprg = syntastic#util#shexpand(g:syntastic_{a:filetype}_compiler) .
\ ' ' . flags . ' ' . syntastic#util#shexpand('%')
let errorformat = s:_get_checker_var('g', a:filetype, a:subchecker, 'errorformat', a:options['errorformat'])
let postprocess = s:_get_checker_var('g', a:filetype, a:subchecker, 'remove_include_errors', 0) ?
\ ['filterForeignErrors'] : []
" process makeprg
return SyntasticMake({
\ 'makeprg': makeprg,
\ 'errorformat': errorformat,
\ 'postprocess': postprocess })
endfunction " }}}2
" }}}1
" Private functions {{{1
" initialize c/cpp syntax checker handlers
function! s:_init() abort " {{{2
let s:handlers = []
let s:cflags = {}
call s:_registerHandler('\m\<cairo', 's:_checkPackage', ['cairo', 'cairo'])
call s:_registerHandler('\m\<freetype', 's:_checkPackage', ['freetype', 'freetype2', 'freetype'])
call s:_registerHandler('\m\<glade', 's:_checkPackage', ['glade', 'libglade-2.0', 'libglade'])
call s:_registerHandler('\m\<glib', 's:_checkPackage', ['glib', 'glib-2.0', 'glib'])
call s:_registerHandler('\m\<gtk', 's:_checkPackage', ['gtk', 'gtk+-2.0', 'gtk+', 'glib-2.0', 'glib'])
call s:_registerHandler('\m\<libsoup', 's:_checkPackage', ['libsoup', 'libsoup-2.4', 'libsoup-2.2'])
call s:_registerHandler('\m\<libxml', 's:_checkPackage', ['libxml', 'libxml-2.0', 'libxml'])
call s:_registerHandler('\m\<pango', 's:_checkPackage', ['pango', 'pango'])
call s:_registerHandler('\m\<SDL', 's:_checkPackage', ['sdl', 'sdl'])
call s:_registerHandler('\m\<opengl', 's:_checkPackage', ['opengl', 'gl'])
call s:_registerHandler('\m\<webkit', 's:_checkPackage', ['webkit', 'webkit-1.0'])
call s:_registerHandler('\m\<php\.h\>', 's:_checkPhp', [])
call s:_registerHandler('\m\<Python\.h\>', 's:_checkPython', [])
call s:_registerHandler('\m\<ruby', 's:_checkRuby', [])
endfunction " }}}2
" register a handler dictionary object
function! s:_registerHandler(regex, function, args) abort " {{{2
let handler = {}
let handler["regex"] = a:regex
let handler["func"] = function(a:function)
let handler["args"] = a:args
call add(s:handlers, handler)
endfunction " }}}2
" try to find library with 'pkg-config'
" search possible libraries from first to last given
" argument until one is found
function! s:_checkPackage(name, ...) abort " {{{2
if executable('pkg-config')
if !has_key(s:cflags, a:name)
for pkg in a:000
let pkg_flags = syntastic#util#system('pkg-config --cflags ' . pkg)
" since we cannot necessarily trust the pkg-config exit code
" we have to check for an error output as well
if v:shell_error == 0 && pkg_flags !~? 'not found'
let pkg_flags = ' ' . substitute(pkg_flags, "\n", '', '')
let s:cflags[a:name] = pkg_flags
return pkg_flags
endif
endfor
else
return s:cflags[a:name]
endif
endif
return ''
endfunction " }}}2
" try to find PHP includes with 'php-config'
function! s:_checkPhp() abort " {{{2
if executable('php-config')
if !has_key(s:cflags, 'php')
let s:cflags['php'] = syntastic#util#system('php-config --includes')
let s:cflags['php'] = ' ' . substitute(s:cflags['php'], "\n", '', '')
endif
return s:cflags['php']
endif
return ''
endfunction " }}}2
" try to find the python headers with distutils
function! s:_checkPython() abort " {{{2
if executable('python')
if !has_key(s:cflags, 'python')
let s:cflags['python'] = syntastic#util#system('python -c ''from distutils import ' .
\ 'sysconfig; import sys; sys.stdout.write(sysconfig.get_python_inc())''')
let s:cflags['python'] = substitute(s:cflags['python'], "\n", '', '')
let s:cflags['python'] = ' -I' . s:cflags['python']
endif
return s:cflags['python']
endif
return ''
endfunction " }}}2
" try to find the ruby headers with 'rbconfig'
function! s:_checkRuby() abort " {{{2
if executable('ruby')
if !has_key(s:cflags, 'ruby')
let s:cflags['ruby'] = syntastic#util#system('ruby -r rbconfig -e ' .
\ '''puts RbConfig::CONFIG["rubyhdrdir"] || RbConfig::CONFIG["archdir"]''')
let s:cflags['ruby'] = substitute(s:cflags['ruby'], "\n", '', '')
let s:cflags['ruby'] = ' -I' . s:cflags['ruby']
endif
return s:cflags['ruby']
endif
return ''
endfunction " }}}2
" }}}1
" Utilities {{{1
" resolve checker-related user variables
function! s:_get_checker_var(scope, filetype, subchecker, name, default) abort " {{{2
let prefix = a:scope . ':' . 'syntastic_'
if exists(prefix . a:filetype . '_' . a:subchecker . '_' . a:name)
return {a:scope}:syntastic_{a:filetype}_{a:subchecker}_{a:name}
elseif exists(prefix . a:filetype . '_' . a:name)
return {a:scope}:syntastic_{a:filetype}_{a:name}
else
return a:default
endif
endfunction " }}}2
" resolve user CFLAGS
function! s:_get_cflags(ft, ck, opts) abort " {{{2
" determine whether to parse header files as well
if has_key(a:opts, 'header_names') && expand('%', 1) =~? a:opts['header_names']
if s:_get_checker_var('g', a:ft, a:ck, 'check_header', 0)
let flags = get(a:opts, 'header_flags', '') . ' -c ' . syntastic#c#NullOutput()
else
" checking headers when check_header is unset: bail out
throw 'Syntastic: skip checks'
endif
else
let flags = get(a:opts, 'main_flags', '')
endif
let flags .= ' ' . s:_get_checker_var('g', a:ft, a:ck, 'compiler_options', '') . ' ' . s:_get_include_dirs(a:ft)
" check if the user manually set some cflags
let b_cflags = s:_get_checker_var('b', a:ft, a:ck, 'cflags', '')
if b_cflags == ''
" check whether to search for include files at all
if !s:_get_checker_var('g', a:ft, a:ck, 'no_include_search', 0)
if a:ft ==# 'c' || a:ft ==# 'cpp'
" refresh the include file search if desired
if s:_get_checker_var('g', a:ft, a:ck, 'auto_refresh_includes', 0)
let flags .= ' ' . s:_search_headers()
else
" search for header includes if not cached already
if !exists('b:syntastic_' . a:ft . '_includes')
let b:syntastic_{a:ft}_includes = s:_search_headers()
endif
let flags .= ' ' . b:syntastic_{a:ft}_includes
endif
endif
endif
else
" user-defined cflags
let flags .= ' ' . b_cflags
endif
" add optional config file parameters
let config_file = s:_get_checker_var('g', a:ft, a:ck, 'config_file', '.syntastic_' . a:ft . '_config')
let flags .= ' ' . syntastic#c#ReadConfig(config_file)
return flags
endfunction " }}}2
" get the gcc include directory argument depending on the default
" includes and the optional user-defined 'g:syntastic_c_include_dirs'
function! s:_get_include_dirs(filetype) abort " {{{2
let include_dirs = []
if a:filetype =~# '\v^%(c|cpp|objc|objcpp)$' &&
\ (!exists('g:syntastic_'.a:filetype.'_no_default_include_dirs') ||
\ !g:syntastic_{a:filetype}_no_default_include_dirs)
let include_dirs = copy(s:default_includes)
endif
if exists('g:syntastic_'.a:filetype.'_include_dirs')
call extend(include_dirs, g:syntastic_{a:filetype}_include_dirs)
endif
return join(map(syntastic#util#unique(include_dirs), 'syntastic#util#shescape("-I" . v:val)'))
endfunction " }}}2
" search the first 100 lines for include statements that are
" given in the handlers dictionary
function! s:_search_headers() abort " {{{2
let includes = ''
let files = []
let found = []
let lines = filter(getline(1, 100), 'v:val =~# ''\m^\s*#\s*include''')
" search current buffer
for line in lines
let file = matchstr(line, '\m"\zs\S\+\ze"')
if file != ''
call add(files, file)
continue
endif
for handler in s:handlers
if line =~# handler["regex"]
let includes .= call(handler["func"], handler["args"])
call add(found, handler["regex"])
break
endif
endfor
endfor
" search included headers
for hfile in files
if hfile != ''
let filename = expand('%:p:h', 1) . syntastic#util#Slash() . hfile
try
let lines = readfile(filename, '', 100)
catch /\m^Vim\%((\a\+)\)\=:E484/
continue
endtry
call filter(lines, 'v:val =~# ''\m^\s*#\s*include''')
for handler in s:handlers
if index(found, handler["regex"]) != -1
continue
endif
for line in lines
if line =~# handler["regex"]
let includes .= call(handler["func"], handler["args"])
call add(found, handler["regex"])
break
endif
endfor
endfor
endif
endfor
return includes
endfunction " }}}2
" }}}1
" default include directories
let s:default_includes = [
\ '.',
\ '..',
\ 'include',
\ 'includes',
\ '..' . syntastic#util#Slash() . 'include',
\ '..' . syntastic#util#Slash() . 'includes' ]
call s:_init()
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,182 @@
if exists("g:loaded_syntastic_log_autoload") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_log_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
let s:one_time_notices_issued = []
" Public functions {{{1
function! syntastic#log#info(msg) abort " {{{2
echomsg "syntastic: info: " . a:msg
endfunction " }}}2
function! syntastic#log#warn(msg) abort " {{{2
echohl WarningMsg
echomsg "syntastic: warning: " . a:msg
echohl None
endfunction " }}}2
function! syntastic#log#error(msg) abort " {{{2
execute "normal \<Esc>"
echohl ErrorMsg
echomsg "syntastic: error: " . a:msg
echohl None
endfunction " }}}2
function! syntastic#log#oneTimeWarn(msg) abort " {{{2
if index(s:one_time_notices_issued, a:msg) >= 0
return
endif
call add(s:one_time_notices_issued, a:msg)
call syntastic#log#warn(a:msg)
endfunction " }}}2
" @vimlint(EVL102, 1, l:OLD_VAR)
function! syntastic#log#deprecationWarn(old, new, ...) abort " {{{2
if exists('g:syntastic_' . a:old) && !exists('g:syntastic_' . a:new)
let msg = 'variable g:syntastic_' . a:old . ' is deprecated, please use '
if a:0
let OLD_VAR = g:syntastic_{a:old}
try
let NEW_VAR = eval(a:1)
let msg .= 'in its stead: let g:syntastic_' . a:new . ' = ' . string(NEW_VAR)
let g:syntastic_{a:new} = NEW_VAR
catch
let msg .= 'g:syntastic_' . a:new . ' instead'
endtry
else
let msg .= 'g:syntastic_' . a:new . ' instead'
let g:syntastic_{a:new} = g:syntastic_{a:old}
endif
call syntastic#log#oneTimeWarn(msg)
endif
endfunction " }}}2
" @vimlint(EVL102, 0, l:OLD_VAR)
function! syntastic#log#debug(level, msg, ...) abort " {{{2
if !s:_isDebugEnabled(a:level)
return
endif
let leader = s:_log_timestamp()
call s:_logRedirect(1)
if a:0 > 0
" filter out dictionary functions
echomsg leader . a:msg . ' ' .
\ strtrans(string(type(a:1) == type({}) || type(a:1) == type([]) ?
\ filter(copy(a:1), 'type(v:val) != type(function("tr"))') : a:1))
else
echomsg leader . a:msg
endif
call s:_logRedirect(0)
endfunction " }}}2
function! syntastic#log#debugShowOptions(level, names) abort " {{{2
if !s:_isDebugEnabled(a:level)
return
endif
let leader = s:_log_timestamp()
call s:_logRedirect(1)
let vlist = copy(type(a:names) == type("") ? [a:names] : a:names)
if !empty(vlist)
call map(vlist, "'&' . v:val . ' = ' . strtrans(string(eval('&' . v:val)))")
echomsg leader . join(vlist, ', ')
endif
call s:_logRedirect(0)
endfunction " }}}2
function! syntastic#log#debugShowVariables(level, names) abort " {{{2
if !s:_isDebugEnabled(a:level)
return
endif
let leader = s:_log_timestamp()
call s:_logRedirect(1)
let vlist = type(a:names) == type("") ? [a:names] : a:names
for name in vlist
let msg = s:_format_variable(name)
if msg != ''
echomsg leader . msg
endif
endfor
call s:_logRedirect(0)
endfunction " }}}2
function! syntastic#log#debugDump(level) abort " {{{2
if !s:_isDebugEnabled(a:level)
return
endif
call syntastic#log#debugShowVariables( a:level, sort(keys(g:_SYNTASTIC_DEFAULTS)) )
endfunction " }}}2
" }}}1
" Private functions {{{1
function! s:_isDebugEnabled_smart(level) abort " {{{2
return and(g:syntastic_debug, a:level)
endfunction " }}}2
function! s:_isDebugEnabled_dumb(level) abort " {{{2
" poor man's bit test for bit N, assuming a:level == 2**N
return (g:syntastic_debug / a:level) % 2
endfunction " }}}2
let s:_isDebugEnabled = function(exists('*and') ? 's:_isDebugEnabled_smart' : 's:_isDebugEnabled_dumb')
lockvar s:_isDebugEnabled
function! s:_logRedirect(on) abort " {{{2
if exists("g:syntastic_debug_file")
if a:on
try
execute 'redir >> ' . fnameescape(expand(g:syntastic_debug_file, 1))
catch /\m^Vim\%((\a\+)\)\=:/
silent! redir END
unlet g:syntastic_debug_file
endtry
else
silent! redir END
endif
endif
endfunction " }}}2
" }}}1
" Utilities {{{1
function! s:_log_timestamp() abort " {{{2
return 'syntastic: ' . split(reltimestr(reltime(g:_SYNTASTIC_START)))[0] . ': '
endfunction " }}}2
function! s:_format_variable(name) abort " {{{2
let vals = []
if exists('g:syntastic_' . a:name)
call add(vals, 'g:syntastic_' . a:name . ' = ' . strtrans(string(g:syntastic_{a:name})))
endif
if exists('b:syntastic_' . a:name)
call add(vals, 'b:syntastic_' . a:name . ' = ' . strtrans(string(b:syntastic_{a:name})))
endif
return join(vals, ', ')
endfunction " }}}2
" }}}1
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,73 @@
if exists("g:loaded_syntastic_postprocess_autoload") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_postprocess_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
" Public functions {{{1
" merge consecutive blanks
function! syntastic#postprocess#compressWhitespace(errors) abort " {{{2
for e in a:errors
let e['text'] = substitute(e['text'], "\001", '', 'g')
let e['text'] = substitute(e['text'], '\n', ' ', 'g')
let e['text'] = substitute(e['text'], '\m\s\{2,}', ' ', 'g')
let e['text'] = substitute(e['text'], '\m^\s\+', '', '')
let e['text'] = substitute(e['text'], '\m\s\+$', '', '')
endfor
return a:errors
endfunction " }}}2
" remove spurious CR under Cygwin
function! syntastic#postprocess#cygwinRemoveCR(errors) abort " {{{2
if has('win32unix')
for e in a:errors
let e['text'] = substitute(e['text'], '\r', '', 'g')
endfor
endif
return a:errors
endfunction " }}}2
" decode XML entities
function! syntastic#postprocess#decodeXMLEntities(errors) abort " {{{2
for e in a:errors
let e['text'] = syntastic#util#decodeXMLEntities(e['text'])
endfor
return a:errors
endfunction " }}}2
" filter out errors referencing other files
function! syntastic#postprocess#filterForeignErrors(errors) abort " {{{2
return filter(copy(a:errors), 'get(v:val, "bufnr") == ' . bufnr(''))
endfunction " }}}2
" make sure line numbers are not past end of buffers
" XXX: this loads all referenced buffers in memory
function! syntastic#postprocess#guards(errors) abort " {{{2
let buffers = syntastic#util#unique(map(filter(copy(a:errors), 'v:val["valid"]'), 'str2nr(v:val["bufnr"])'))
let guards = {}
for b in buffers
let guards[b] = len(getbufline(b, 1, '$'))
endfor
for e in a:errors
if e['valid'] && e['lnum'] > guards[e['bufnr']]
let e['lnum'] = guards[e['bufnr']]
endif
endfor
return a:errors
endfunction " }}}2
" }}}1
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,316 @@
if exists("g:loaded_syntastic_preprocess_autoload") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_preprocess_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
" Public functions {{{1
function! syntastic#preprocess#cabal(errors) abort " {{{2
let out = []
let star = 0
for err in a:errors
if star
if err == ''
let star = 0
else
let out[-1] .= ' ' . err
endif
else
call add(out, err)
if err =~ '\m^*\s'
let star = 1
endif
endif
endfor
return out
endfunction " }}}2
function! syntastic#preprocess#checkstyle(errors) abort " {{{2
let out = []
let fname = expand('%', 1)
for err in a:errors
if match(err, '\m<error\>') > -1
let line = str2nr(matchstr(err, '\m\<line="\zs\d\+\ze"'))
if line == 0
continue
endif
let col = str2nr(matchstr(err, '\m\<column="\zs\d\+\ze"'))
let type = matchstr(err, '\m\<severity="\zs.\ze')
if type !~? '^[EW]'
let type = 'E'
endif
let message = syntastic#util#decodeXMLEntities(matchstr(err, '\m\<message="\zs[^"]\+\ze"'))
call add(out, join([fname, type, line, col, message], ':'))
elseif match(err, '\m<file name="') > -1
let fname = syntastic#util#decodeXMLEntities(matchstr(err, '\v\<file name\="\zs[^"]+\ze"'))
endif
endfor
return out
endfunction " }}}2
function! syntastic#preprocess#cppcheck(errors) abort " {{{2
return map(copy(a:errors), 'substitute(v:val, ''\v^\[[^]]+\]\zs( -\> \[[^]]+\])+\ze:'', "", "")')
endfunction " }}}2
" @vimlint(EVL102, 1, l:true)
" @vimlint(EVL102, 1, l:false)
" @vimlint(EVL102, 1, l:null)
function! syntastic#preprocess#flow(errors) abort " {{{2
" JSON artifacts
let true = 1
let false = 0
let null = ''
" A hat tip to Marc Weber for this trick
" http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763
try
let errs = eval(join(a:errors, ''))
catch
let errs = {}
endtry
let out = []
if type(errs) == type({}) && has_key(errs, 'errors') && type(errs['errors']) == type([])
for e in errs['errors']
if type(e) == type({}) && has_key(e, 'message') && type(e['message']) == type([]) && len(e['message'])
let m = e['message'][0]
let t = e['message'][1:]
try
let msg =
\ m['path'] . ':' .
\ m['line'] . ':' .
\ m['start'] . ':' .
\ (m['line'] ==# m['endline'] ? m['end'] . ':' : '') .
\ ' ' . m['descr']
if len(t)
let msg .= ' ' . join(map(t,
\ 'v:val["descr"] . " (" . v:val["path"] . ":" . v:val["line"] . ":" . v:val["start"] . ' .
\ '"," . (v:val["line"] !=# v:val["endline"] ? v:val["endline"] . ":" : "") . ' .
\ 'v:val["end"] . ")"'))
endif
let msg = substitute(msg, '\r', '', 'g')
let msg = substitute(msg, '\n', ' ', 'g')
call add(out, msg)
catch /\m^Vim\%((\a\+)\)\=:E716/
call syntastic#log#warn('checker javascript/flow: unknown error format')
let out = []
break
endtry
else
call syntastic#log#warn('checker javascript/flow: unknown error format')
let out = []
break
endif
endfor
else
call syntastic#log#warn('checker javascript/flow: unknown error format')
endif
return out
endfunction " }}}2
" @vimlint(EVL102, 0, l:true)
" @vimlint(EVL102, 0, l:false)
" @vimlint(EVL102, 0, l:null)
function! syntastic#preprocess#killEmpty(errors) abort " {{{2
return filter(copy(a:errors), 'v:val != ""')
endfunction " }}}2
function! syntastic#preprocess#perl(errors) abort " {{{2
let out = []
for e in a:errors
let parts = matchlist(e, '\v^(.*)\sat\s(.{-})\sline\s(\d+)(.*)$')
if !empty(parts)
call add(out, parts[2] . ':' . parts[3] . ':' . parts[1] . parts[4])
endif
endfor
return syntastic#util#unique(out)
endfunction " }}}2
" @vimlint(EVL102, 1, l:true)
" @vimlint(EVL102, 1, l:false)
" @vimlint(EVL102, 1, l:null)
function! syntastic#preprocess#prospector(errors) abort " {{{2
" JSON artifacts
let true = 1
let false = 0
let null = ''
" A hat tip to Marc Weber for this trick
" http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763
try
let errs = eval(join(a:errors, ''))
catch
let errs = {}
endtry
let out = []
if type(errs) == type({}) && has_key(errs, 'messages')
if type(errs['messages']) == type([])
for e in errs['messages']
if type(e) == type({})
try
if e['source'] ==# 'pylint'
let e['location']['character'] += 1
endif
let msg =
\ e['location']['path'] . ':' .
\ e['location']['line'] . ':' .
\ e['location']['character'] . ': ' .
\ e['code'] . ' ' .
\ e['message'] . ' ' .
\ '[' . e['source'] . ']'
call add(out, msg)
catch /\m^Vim\%((\a\+)\)\=:E716/
call syntastic#log#warn('checker python/prospector: unknown error format')
let out = []
break
endtry
else
call syntastic#log#warn('checker python/prospector: unknown error format')
let out = []
break
endif
endfor
else
call syntastic#log#warn('checker python/prospector: unknown error format')
endif
endif
return out
endfunction " }}}2
" @vimlint(EVL102, 0, l:true)
" @vimlint(EVL102, 0, l:false)
" @vimlint(EVL102, 0, l:null)
function! syntastic#preprocess#rparse(errors) abort " {{{2
let errlist = copy(a:errors)
" remove uninteresting lines and handle continuations
let i = 0
while i < len(errlist)
if i > 0 && errlist[i][:1] == ' ' && errlist[i] !~ '\m\s\+\^$'
let errlist[i-1] .= errlist[i][1:]
call remove(errlist, i)
elseif errlist[i] !~# '\m^\(Lint:\|Lint checking:\|Error in\) '
call remove(errlist, i)
else
let i += 1
endif
endwhile
let out = []
let fname = ''
for e in errlist
if match(e, '\m^Lint: ') == 0
let parts = matchlist(e, '\m^Lint: \(.*\): found on lines \([0-9, ]\+\)\(+\(\d\+\) more\)\=')
if len(parts) >= 3
for line in split(parts[2], '\m,\s*')
call add(out, 'E:' . fname . ':' . line . ': ' . parts[1])
endfor
endif
if len(parts) >= 5 && parts[4] != ''
call add(out, 'E:' . fname . ':0: ' . parts[1] . ' - ' . parts[4] . ' messages not shown')
endif
elseif match(e, '\m^Lint checking: ') == 0
let fname = matchstr(e, '\m^Lint checking: \zs.*')
elseif match(e, '\m^Error in ') == 0
call add(out, substitute(e, '\m^Error in .\+ : .\+\ze:\d\+:\d\+: ', 'E:' . fname, ''))
endif
endfor
return out
endfunction " }}}2
function! syntastic#preprocess#tslint(errors) abort " {{{2
return map(copy(a:errors), 'substitute(v:val, ''\m^\(([^)]\+)\)\s\(.\+\)$'', ''\2 \1'', "")')
endfunction " }}}2
function! syntastic#preprocess#validator(errors) abort " {{{2
let out = []
for e in a:errors
let parts = matchlist(e, '\v^"([^"]+)"(.+)')
if len(parts) >= 3
" URL decode, except leave alone any "+"
let parts[1] = substitute(parts[1], '\m%\(\x\x\)', '\=nr2char("0x".submatch(1))', 'g')
let parts[1] = substitute(parts[1], '\m\\"', '"', 'g')
let parts[1] = substitute(parts[1], '\m\\\\', '\\', 'g')
call add(out, '"' . parts[1] . '"' . parts[2])
endif
endfor
return out
endfunction " }}}2
" @vimlint(EVL102, 1, l:true)
" @vimlint(EVL102, 1, l:false)
" @vimlint(EVL102, 1, l:null)
function! syntastic#preprocess#vint(errors) abort " {{{2
" JSON artifacts
let true = 1
let false = 0
let null = ''
" A hat tip to Marc Weber for this trick
" http://stackoverflow.com/questions/17751186/iterating-over-a-string-in-vimscript-or-parse-a-json-file/19105763#19105763
try
let errs = eval(join(a:errors, ''))
catch
let errs = []
endtry
let out = []
if type(errs) == type([])
for e in errs
if type(e) == type({})
try
let msg =
\ e['file_path'] . ':' .
\ e['line_number'] . ':' .
\ e['column_number'] . ':' .
\ e['severity'][0] . ': ' .
\ e['description'] . ' (' .
\ e['policy_name'] . ')'
call add(out, msg)
catch /\m^Vim\%((\a\+)\)\=:E716/
call syntastic#log#warn('checker vim/vint: unknown error format')
let out = []
break
endtry
else
call syntastic#log#warn('checker vim/vint: unknown error format')
let out = []
break
endif
endfor
else
call syntastic#log#warn('checker vim/vint: unknown error format')
endif
return out
endfunction " }}}2
" @vimlint(EVL102, 0, l:true)
" @vimlint(EVL102, 0, l:false)
" @vimlint(EVL102, 0, l:null)
" }}}1
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,415 @@
if exists('g:loaded_syntastic_util_autoload') || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_util_autoload = 1
let s:save_cpo = &cpo
set cpo&vim
" Public functions {{{1
function! syntastic#util#isRunningWindows() abort " {{{2
return has('win16') || has('win32') || has('win64')
endfunction " }}}2
function! syntastic#util#DevNull() abort " {{{2
if syntastic#util#isRunningWindows()
return 'NUL'
endif
return '/dev/null'
endfunction " }}}2
" Get directory separator
function! syntastic#util#Slash() abort " {{{2
return (!exists("+shellslash") || &shellslash) ? '/' : '\'
endfunction " }}}2
function! syntastic#util#CygwinPath(path) abort " {{{2
return substitute(syntastic#util#system('cygpath -m ' . syntastic#util#shescape(a:path)), "\n", '', 'g')
endfunction " }}}2
function! syntastic#util#system(command) abort " {{{2
let old_shell = &shell
let old_lc_messages = $LC_MESSAGES
let old_lc_all = $LC_ALL
let &shell = syntastic#util#var('shell')
let $LC_MESSAGES = 'C'
let $LC_ALL = ''
let out = system(a:command)
let $LC_ALL = old_lc_all
let $LC_MESSAGES = old_lc_messages
let &shell = old_shell
return out
endfunction " }}}2
" Create a temporary directory
function! syntastic#util#tmpdir() abort " {{{2
let tempdir = ''
if (has('unix') || has('mac')) && executable('mktemp')
" TODO: option "-t" to mktemp(1) is not portable
let tmp = $TMPDIR != '' ? $TMPDIR : $TMP != '' ? $TMP : '/tmp'
let out = split(syntastic#util#system('mktemp -q -d ' . tmp . '/vim-syntastic-' . getpid() . '-XXXXXXXX'), "\n")
if v:shell_error == 0 && len(out) == 1
let tempdir = out[0]
endif
endif
if tempdir == ''
if has('win32') || has('win64')
let tempdir = $TEMP . syntastic#util#Slash() . 'vim-syntastic-' . getpid()
elseif has('win32unix')
let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . getpid())
elseif $TMPDIR != ''
let tempdir = $TMPDIR . '/vim-syntastic-' . getpid()
else
let tempdir = '/tmp/vim-syntastic-' . getpid()
endif
try
call mkdir(tempdir, 'p', 0700)
catch /\m^Vim\%((\a\+)\)\=:E739/
call syntastic#log#error(v:exception)
let tempdir = '.'
endtry
endif
return tempdir
endfunction " }}}2
" Recursively remove a directory
function! syntastic#util#rmrf(what) abort " {{{2
" try to make sure we don't delete directories we didn't create
if a:what !~? 'vim-syntastic-'
return
endif
if getftype(a:what) ==# 'dir'
if !exists('s:rmrf')
let s:rmrf =
\ has('unix') || has('mac') ? 'rm -rf' :
\ has('win32') || has('win64') ? 'rmdir /S /Q' :
\ has('win16') || has('win95') || has('dos16') || has('dos32') ? 'deltree /Y' : ''
endif
if s:rmrf != ''
silent! call syntastic#util#system(s:rmrf . ' ' . syntastic#util#shescape(a:what))
else
call s:_rmrf(a:what)
endif
else
silent! call delete(a:what)
endif
endfunction " }}}2
"search the first 5 lines of the file for a magic number and return a map
"containing the args and the executable
"
"e.g.
"
"#!/usr/bin/perl -f -bar
"
"returns
"
"{'exe': '/usr/bin/perl', 'args': ['-f', '-bar']}
function! syntastic#util#parseShebang() abort " {{{2
for lnum in range(1, 5)
let line = getline(lnum)
if line =~ '^#!'
let line = substitute(line, '\v^#!\s*(\S+/env(\s+-\S+)*\s+)?', '', '')
let exe = matchstr(line, '\m^\S*\ze')
let args = split(matchstr(line, '\m^\S*\zs.*'))
return { 'exe': exe, 'args': args }
endif
endfor
return { 'exe': '', 'args': [] }
endfunction " }}}2
" Get the value of a variable. Allow local variables to override global ones.
function! syntastic#util#var(name, ...) abort " {{{2
return
\ exists('b:syntastic_' . a:name) ? b:syntastic_{a:name} :
\ exists('g:syntastic_' . a:name) ? g:syntastic_{a:name} :
\ a:0 > 0 ? a:1 : ''
endfunction " }}}2
" Parse a version string. Return an array of version components.
function! syntastic#util#parseVersion(version) abort " {{{2
return map(split(matchstr( a:version, '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.'), 'str2nr(v:val)')
endfunction " }}}2
" Verify that the 'installed' version is at least the 'required' version.
"
" 'installed' and 'required' must be arrays. If they have different lengths,
" the "missing" elements will be assumed to be 0 for the purposes of checking.
"
" See http://semver.org for info about version numbers.
function! syntastic#util#versionIsAtLeast(installed, required) abort " {{{2
return syntastic#util#compareLexi(a:installed, a:required) >= 0
endfunction " }}}2
" Almost lexicographic comparison of two lists of integers. :) If lists
" have different lengths, the "missing" elements are assumed to be 0.
function! syntastic#util#compareLexi(a, b) abort " {{{2
for idx in range(max([len(a:a), len(a:b)]))
let a_element = str2nr(get(a:a, idx, 0))
let b_element = str2nr(get(a:b, idx, 0))
if a_element != b_element
return a_element > b_element ? 1 : -1
endif
endfor
" Everything matched, so it is at least the required version.
return 0
endfunction " }}}2
" strwidth() was added in Vim 7.3; if it doesn't exist, we use strlen()
" and hope for the best :)
let s:_width = function(exists('*strwidth') ? 'strwidth' : 'strlen')
lockvar s:_width
function! syntastic#util#screenWidth(str, tabstop) abort " {{{2
let chunks = split(a:str, "\t", 1)
let width = s:_width(chunks[-1])
for c in chunks[:-2]
let cwidth = s:_width(c)
let width += cwidth + a:tabstop - cwidth % a:tabstop
endfor
return width
endfunction " }}}2
"print as much of a:msg as possible without "Press Enter" prompt appearing
function! syntastic#util#wideMsg(msg) abort " {{{2
let old_ruler = &ruler
let old_showcmd = &showcmd
"This is here because it is possible for some error messages to
"begin with \n which will cause a "press enter" prompt.
let msg = substitute(a:msg, "\n", "", "g")
"convert tabs to spaces so that the tabs count towards the window
"width as the proper amount of characters
let chunks = split(msg, "\t", 1)
let msg = join(map(chunks[:-2], 'v:val . repeat(" ", &tabstop - s:_width(v:val) % &tabstop)'), '') . chunks[-1]
let msg = strpart(msg, 0, &columns - 1)
set noruler noshowcmd
call syntastic#util#redraw(0)
echo msg
let &ruler = old_ruler
let &showcmd = old_showcmd
endfunction " }}}2
" Check whether a buffer is loaded, listed, and not hidden
function! syntastic#util#bufIsActive(buffer) abort " {{{2
" convert to number, or hell breaks loose
let buf = str2nr(a:buffer)
if !bufloaded(buf) || !buflisted(buf)
return 0
endif
" get rid of hidden buffers
for tab in range(1, tabpagenr('$'))
if index(tabpagebuflist(tab), buf) >= 0
return 1
endif
endfor
return 0
endfunction " }}}2
" start in directory a:where and walk up the parent folders until it
" finds a file matching a:what; return path to that file
function! syntastic#util#findInParent(what, where) abort " {{{2
let here = fnamemodify(a:where, ':p')
let root = syntastic#util#Slash()
if syntastic#util#isRunningWindows() && here[1] == ':'
" The drive letter is an ever-green source of fun. That's because
" we don't care about running syntastic on Amiga these days. ;)
let root = fnamemodify(root, ':p')
let root = here[0] . root[1:]
endif
let old = ''
while here != ''
let p = split(globpath(here, a:what, 1), '\n')
if !empty(p)
return fnamemodify(p[0], ':p')
elseif here ==? root || here ==? old
break
endif
let old = here
" we use ':h:h' rather than ':h' since ':p' adds a trailing '/'
" if 'here' is a directory
let here = fnamemodify(here, ':p:h:h')
endwhile
return ''
endfunction " }}}2
" Returns unique elements in a list
function! syntastic#util#unique(list) abort " {{{2
let seen = {}
let uniques = []
for e in a:list
if !has_key(seen, e)
let seen[e] = 1
call add(uniques, e)
endif
endfor
return uniques
endfunction " }}}2
" A less noisy shellescape()
function! syntastic#util#shescape(string) abort " {{{2
return a:string =~# '\m^[A-Za-z0-9_/.-]\+$' ? a:string : shellescape(a:string)
endfunction " }}}2
" A less noisy shellescape(expand())
function! syntastic#util#shexpand(string, ...) abort " {{{2
return syntastic#util#shescape(a:0 ? expand(a:string, a:1) : expand(a:string, 1))
endfunction " }}}2
" Escape arguments
function! syntastic#util#argsescape(opt) abort " {{{2
if type(a:opt) == type('') && a:opt != ''
return [a:opt]
elseif type(a:opt) == type([])
return map(copy(a:opt), 'syntastic#util#shescape(v:val)')
endif
return []
endfunction " }}}2
" decode XML entities
function! syntastic#util#decodeXMLEntities(string) abort " {{{2
let str = a:string
let str = substitute(str, '\m&lt;', '<', 'g')
let str = substitute(str, '\m&gt;', '>', 'g')
let str = substitute(str, '\m&quot;', '"', 'g')
let str = substitute(str, '\m&apos;', "'", 'g')
let str = substitute(str, '\m&amp;', '\&', 'g')
return str
endfunction " }}}2
function! syntastic#util#redraw(full) abort " {{{2
if a:full
redraw!
else
redraw
endif
endfunction " }}}2
function! syntastic#util#dictFilter(errors, filter) abort " {{{2
let rules = s:_translateFilter(a:filter)
" call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, "applying filter:", rules)
try
call filter(a:errors, rules)
catch /\m^Vim\%((\a\+)\)\=:E/
let msg = matchstr(v:exception, '\m^Vim\%((\a\+)\)\=:\zs.*')
call syntastic#log#error('quiet_messages: ' . msg)
endtry
endfunction " }}}2
" Return a [high, low] list of integers, representing the time
" (hopefully high resolution) since program start
" TODO: This assumes reltime() returns a list of integers.
function! syntastic#util#stamp() abort " {{{2
return reltime(g:_SYNTASTIC_START)
endfunction " }}}2
" }}}1
" Private functions {{{1
function! s:_translateFilter(filters) abort " {{{2
let conditions = []
for k in keys(a:filters)
if type(a:filters[k]) == type([])
call extend(conditions, map(copy(a:filters[k]), 's:_translateElement(k, v:val)'))
else
call add(conditions, s:_translateElement(k, a:filters[k]))
endif
endfor
if conditions == []
let conditions = ["1"]
endif
return len(conditions) == 1 ? conditions[0] : join(map(conditions, '"(" . v:val . ")"'), ' && ')
endfunction " }}}2
function! s:_translateElement(key, term) abort " {{{2
let fkey = a:key
if fkey[0] == '!'
let fkey = fkey[1:]
let not = 1
else
let not = 0
endif
if fkey ==? 'level'
let op = not ? ' ==? ' : ' !=? '
let ret = 'v:val["type"]' . op . string(a:term[0])
elseif fkey ==? 'type'
if a:term ==? 'style'
let op = not ? ' ==? ' : ' !=? '
let ret = 'get(v:val, "subtype", "")' . op . '"style"'
else
let op = not ? '!' : ''
let ret = op . 'has_key(v:val, "subtype")'
endif
elseif fkey ==? 'regex'
let op = not ? ' =~? ' : ' !~? '
let ret = 'v:val["text"]' . op . string(a:term)
elseif fkey ==? 'file' || fkey[:4] ==? 'file:'
let op = not ? ' =~# ' : ' !~# '
let ret = 'bufname(str2nr(v:val["bufnr"]))'
let mod = fkey[4:]
if mod != ''
let ret = 'fnamemodify(' . ret . ', ' . string(mod) . ')'
endif
let ret .= op . string(a:term)
else
call syntastic#log#warn('quiet_messages: ignoring invalid key ' . strtrans(string(fkey)))
let ret = "1"
endif
return ret
endfunction " }}}2
function! s:_rmrf(what) abort " {{{2
if !exists('s:rmdir')
let s:rmdir = syntastic#util#shescape(get(g:, 'netrw_localrmdir', 'rmdir'))
endif
if getftype(a:what) ==# 'dir'
if filewritable(a:what) != 2
return
endif
for f in split(globpath(a:what, '*', 1), "\n")
call s:_rmrf(f)
endfor
silent! call syntastic#util#system(s:rmdir . ' ' . syntastic#util#shescape(a:what))
else
silent! call delete(a:what)
endif
endfunction " }}}2
" }}}1
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,924 @@
*syntastic.txt* Syntax checking on the fly has never been so pimp.
*syntastic*
It's a bird! It's a plane! ZOMG It's ... ~
_____ __ __ _ ~
/ ___/__ ______ / /_____ ______/ /_(_)____ ~
\__ \/ / / / __ \/ __/ __ `/ ___/ __/ / ___/ ~
___/ / /_/ / / / / /_/ /_/ (__ ) /_/ / /__ ~
/____/\__, /_/ /_/\__/\__,_/____/\__/_/\___/ ~
/____/ ~
Reference Manual~
==============================================================================
CONTENTS *syntastic-contents*
1.Intro........................................|syntastic-intro|
1.1.Quick start............................|syntastic-quickstart|
1.2.Recommended settings...................|syntastic-recommended|
2.Functionality provided.......................|syntastic-functionality|
2.1.The statusline flag....................|syntastic-statusline-flag|
2.2.Error signs............................|syntastic-error-signs|
2.3.Error window...........................|syntastic-error-window|
2.4.Error highlighting.....................|syntastic-highlighting|
2.5.Aggregating errors.....................|syntastic-aggregating-errors|
2.6.Filtering errors.......................|syntastic-filtering-errors|
3.Commands.....................................|syntastic-commands|
4.Global Options...............................|syntastic-global-options|
5.Checker Options..............................|syntastic-checker-options|
5.1.Choosing which checkers to use.........|syntastic-filetype-checkers|
5.2.Choosing the executable................|syntastic-config-exec|
5.3.Configuring specific checkers..........|syntastic-config-makeprg|
5.4.Sorting errors.........................|syntastic-config-sort|
6.Notes........................................|syntastic-notes|
6.1.Handling of composite filetypes........|syntastic-composite|
6.2.Editing files over network.............|syntastic-netrw|
6.3.The 'shellslash' option................|syntastic-shellslash|
7.Compatibility with other software............|syntastic-compatibility|
7.1.The csh and tcsh shells................|syntastic-csh|
7.2.Eclim..................................|syntastic-eclim|
7.3.The fish shell.........................|syntastic-fish|
7.4.The fizsh shell........................|syntastic-fizsh|
7.5.The PowerShell shell...................|syntastic-powershell|
7.6.python-mode............................|syntastic-pymode|
7.7.vim-auto-save..........................|syntastic-vim-auto-save|
7.8.vim-virtualenv.........................|syntastic-vim-virtualenv|
7.9.YouCompleteMe..........................|syntastic-ycm|
8.About........................................|syntastic-about|
9.License......................................|syntastic-license|
==============================================================================
1. Intro *syntastic-intro*
Syntastic is a syntax checking plugin that runs files through external syntax
checkers. This can be done on demand, or automatically as files are saved and
opened. If syntax errors are detected, the user is notified and is happy
because they didn't have to compile their code or execute their script to find
them.
Syntastic comes in two parts: the syntax checker plugins, and the core. The
syntax checker plugins are defined on a per-filetype basis where each one wraps
up an external syntax checking program. The core script delegates off to these
plugins and uses their output to provide the syntastic functionality.
Take a look at the wiki for a list of supported filetypes and checkers:
https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers
Note: This doc only deals with using syntastic. To learn how to write syntax
checker integrations, see the guide on the GitHub wiki:
https://github.com/scrooloose/syntastic/wiki/Syntax-Checker-Guide
------------------------------------------------------------------------------
1.1. Quick start *syntastic-quickstart*
Syntastic comes preconfigured with a default list of enabled checkers per
filetype. This list is kept reasonably short to prevent slowing down Vim or
trying to use conflicting checkers.
You can see the list of checkers available for the current filetype with the
|:SyntasticInfo| command.
You probably want to override the configured list of checkers for the
filetypes you use, and also change the arguments passed to specific checkers
to suit your needs. See |syntastic-checker-options| below for details.
Use |:SyntasticCheck| to manually check right now. Use |:Errors| to open the
|location-list| window, and |:lclose| to close it. You can clear the error
list with |:SyntasticReset|, and you can use |:SyntasticToggleMode| to switch
between active (checking on writing the buffer) and passive (manual) checking.
You don't have to switch focus to the |location-list| window to jump to the
different errors. Vim provides several built-in commands for this, for
example |:lnext| and |:lprevious|. You may want to add shortcut mappings for
these commands, or perhaps install a plugin such as Tim Pope's 'unimpaired'
(see https://github.com/tpope/vim-unimpaired) that provides such mappings.
------------------------------------------------------------------------------
1.2. Recommended settings *syntastic-recommended*
Syntastic has a large number of options that can be configured, and the
defaults are not particularly well suitable for new users. It is recommended
that you start by adding the following lines to your vimrc, and return to them
later as needed: >
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*
let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 1
let g:syntastic_check_on_open = 1
let g:syntastic_check_on_wq = 0
<
==============================================================================
2. Functionality provided *syntastic-functionality*
Syntax checking can be done automatically or on demand (see
|'syntastic_mode_map'| and |:SyntasticToggleMode| for configuring this).
When syntax checking is done, the features below can be used to notify the
user of errors. See |syntastic-global-options| for how to configure and
activate/deactivate these features.
* A statusline flag
* Signs beside lines with errors
* The |location-list| can be populated with the errors for the associated
buffer
* Erroneous parts of lines can be highlighted (this functionality is only
provided by some syntax checkers)
* Balloons (if the |+balloon_eval| feature is compiled in) can be used to
display error messages for erroneous lines when hovering the mouse over
them
* Error messages from multiple checkers can be aggregated in a single list
------------------------------------------------------------------------------
2.1. The statusline flag *syntastic-statusline-flag*
To use the statusline flag, this must appear in your |'statusline'| setting >
%{SyntasticStatuslineFlag()}
<
Something like this could be more useful: >
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*
<
When syntax errors are detected a flag will be shown. The content of the flag
is derived from the |syntastic_stl_format| option.
------------------------------------------------------------------------------
2.2. Error signs *syntastic-error-signs*
Syntastic uses the |:sign| commands to mark lines with errors and warnings in
the sign column. To enable this feature, use the |'syntastic_enable_signs'|
option.
Signs are colored using the Error and Todo syntax highlight groups by default.
If you wish to customize the colors for the signs, you can use the following
groups:
SyntasticErrorSign - For syntax errors, links to 'error' by default
SyntasticWarningSign - For syntax warnings, links to 'todo' by default
SyntasticStyleErrorSign - For style errors, links to 'SyntasticErrorSign'
by default
SyntasticStyleWarningSign - For style warnings, links to
'SyntasticWarningSign' by default
Example: >
highlight SyntasticErrorSign guifg=white guibg=red
<
To set up highlighting for the line where a sign resides, you can use the
following highlight groups:
SyntasticErrorLine
SyntasticWarningLine
SyntasticStyleErrorLine - Links to 'SyntasticErrorLine' by default
SyntasticStyleWarningLine - Links to 'SyntasticWarningLine' by default
Example: >
highlight SyntasticErrorLine guibg=#2f0000
<
------------------------------------------------------------------------------
2.3. The error window *syntastic-error-window*
You can use the |:Errors| command to display the errors for the current buffer
in the |location-list|.
Note that when you use |:Errors| the current location list is overwritten with
Syntastic's own location list. The location list is also overwritten when
|syntastic_auto_jump| is non-zero and the cursor has to jump to an issue.
By default syntastic doesn't fill the |location-list| with the errors found by
the checkers, in order to reduce clashes with other plugins. Consequently, if
you run |:lopen| or |:lwindow| rather than |:Errors| to open the error window you
wouldn't see syntastic's list of errors. If you insist on using |:lopen| or
|:lwindow| you should either run |:SyntasticSetLoclist| after running the checks,
or set |syntastic_always_populate_loc_list| which tells syntastic to update the
|location-list| automatically.
------------------------------------------------------------------------------
2.4. Error highlighting *syntastic-highlighting*
Some checkers provide enough information for syntastic to be able to highlight
errors. By default the SpellBad syntax highlight group is used to color errors,
and the SpellCap group is used for warnings. If you wish to customize the
colors for highlighting you can use the following groups:
SyntasticError - Links to 'SpellBad' by default
SyntasticWarning - Links to 'SpellCap' by default
SyntasticStyleError - Links to SyntasticError by default
SyntasticStyleWarning - Links to SyntasticWarning by default
Example: >
highlight SyntasticError guibg=#2f0000
<
------------------------------------------------------------------------------
2.5. Aggregating errors *syntastic-aggregating-errors*
By default, namely if |'syntastic_aggregate_errors'| is unset, syntastic runs
in turn the checkers corresponding to the filetype of the current file (see
|syntastic-filetype-checkers|), and stops as soon as a checker reports any
errors. It then notifies you of the errors using the notification mechanisms
above. In this mode error lists are always produced by a single checker, and,
if you open the error window, the name of the checker that generated the errors
is shown on the statusline of the error window.
If |'syntastic_aggregate_errors'| is set, syntastic runs all checkers that
apply (still cf. |syntastic-filetype-checkers|), then aggregates errors found
by all checkers in a single list, and notifies you. In this mode each error
message is labeled with the name of the checker that generated it, but you can
disable generation of these labels by turning off '|syntastic_id_checkers|'.
If |'syntastic_sort_aggregated_errors'| is set (which is the default), messages
in the aggregated list are grouped by file, then sorted by line number, then
type, then column number. Otherwise messages produced by the same checker are
grouped together, and sorting within each group is decided by the variables
|'syntastic_<filetype>_<checker>_sort'|.
------------------------------------------------------------------------------
2.6 Filtering errors *syntastic-filtering-errors*
You can selectively disable some of the errors found by checkers either
using |'syntastic_quiet_messages'|, or by specifying a list of patterns in
|'syntastic_ignore_files'|.
See also: |'syntastic_<filetype>_<checker>_quiet_messages'|.
==============================================================================
3. Commands *syntastic-commands*
:Errors *:Errors*
When errors have been detected, use this command to pop up the |location-list|
and display the error messages.
Please note that the |:Errors| command overwrites the current location list with
syntastic's own location list.
:SyntasticToggleMode *:SyntasticToggleMode*
Toggles syntastic between active and passive mode. See |'syntastic_mode_map'|
for more info.
:SyntasticCheck *:SyntasticCheck*
Manually cause a syntax check to be done. By default the checkers in the
|'g:syntastic_<filetype>_checkers'| or |'b:syntastic_checkers'| lists are run,
cf. |syntastic-filetype-checkers|. If |syntastic_aggregate_errors| is unset
(which is the default), checking stops the first time a checker reports any
errors; if |syntastic_aggregate_errors| is set, all checkers that apply are run
in turn, and all errors found are aggregated in a single list.
The command may be followed by a (space separated) list of checkers. In this
case |'g:syntastic_<filetype>_checkers'| and |'b:syntastic_checkers'| are
ignored, and the checkers named by the command's arguments are run instead, in
the order specified. The rules of |syntastic_aggregate_errors| still apply.
Example: >
:SyntasticCheck flake8 pylint
<
:SyntasticInfo *:SyntasticInfo*
The command takes an optional argument, and outputs information about the
checkers available for the filetype named by said argument, or for the current
filetype if no argument was provided.
:SyntasticReset *:SyntasticReset*
Resets the list of errors and turns off all error notifiers.
:SyntasticSetLoclist *:SyntasticSetLoclist*
If |'syntastic_always_populate_loc_list'| is not set, the |location-list| is
not filled in automatically with the list of errors detected by the checkers.
This is useful if you run syntastic along with other plugins that use location
lists. The |:SyntasticSetLoclist| command allows you to stick the errors into
the location list explicitly.
==============================================================================
4. Global Options *syntastic-global-options*
*'syntastic_check_on_open'*
Default: 0
If enabled, syntastic will do syntax checks when buffers are first loaded as
well as on saving >
let g:syntastic_check_on_open = 1
<
*'syntastic_check_on_wq'*
Default: 1
Normally syntastic runs syntax checks whenever buffers are written to disk.
If you want to skip these checks when you issue |:wq|, |:x|, and |:ZZ|, set this
variable to 0. >
let g:syntastic_check_on_wq = 0
<
*'syntastic_aggregate_errors'*
Default: 0
When enabled, syntastic runs all checkers that apply to the current filetype,
then aggregates errors found by all checkers and displays them. When disabled,
syntastic runs each checker in turn, and stops to display the results the first
time a checker finds any errors. >
let g:syntastic_aggregate_errors = 1
<
*'syntastic_id_checkers'*
Default: 1
When results from multiple checkers are aggregated in a single error list
(that is either when |syntastic_aggregate_errors| is enabled, or when checking
a file with a composite filetype), it might not be immediately obvious which
checker has produced a given error message. This variable instructs syntastic
to label error messages with the names of the checkers that created them. >
let g:syntastic_id_checkers = 0
<
*'syntastic_sort_aggregated_errors'*
Default: 1
By default, when results from multiple checkers are aggregated in a single
error list (that is either when |syntastic_aggregate_errors| is enabled, or
when checking a file with a composite filetype), errors are grouped by file,
then sorted by line number, then grouped by type (namely errors take precedence
over warnings), then they are sorted by column number. If you want to leave
messages grouped by checker output, set this variable to 0. >
let g:syntastic_sort_aggregated_errors = 0
<
*'syntastic_echo_current_error'*
Default: 1
If enabled, syntastic will echo current error to the command window. If
multiple errors are found on the same line, |syntastic_cursor_columns| is used
to decide which one is shown. >
let g:syntastic_echo_current_error = 1
<
*'syntastic_cursor_columns'*
Default: 1
This option controls which errors are echoed to the command window if
|syntastic_echo_current_error| is set and multiple errors are found on the same
line. When the option is enabled, the first error corresponding to the current
column is show. Otherwise, the first error on the current line is echoed,
regardless of the cursor position on the current line.
When dealing with very large lists of errors, disabling this option can speed
up navigation significantly: >
let g:syntastic_cursor_column = 0
<
*'syntastic_enable_signs'*
Default: 1
Use this option to tell syntastic whether to use the |:sign| interface to mark
syntax errors: >
let g:syntastic_enable_signs = 1
<
*'syntastic_error_symbol'* *'syntastic_style_error_symbol'*
*'syntastic_warning_symbol'* *'syntastic_style_warning_symbol'*
Use this option to control what the syntastic |:sign| text contains. Several
error symbols can be customized:
syntastic_error_symbol - For syntax errors, defaults to '>>'
syntastic_style_error_symbol - For style errors, defaults to 'S>'
syntastic_warning_symbol - For syntax warnings, defaults to '>>'
syntastic_style_warning_symbol - For style warnings, defaults to 'S>'
Example: >
let g:syntastic_error_symbol = "✗"
let g:syntastic_warning_symbol = "⚠"
<
*'syntastic_enable_balloons'*
Default: 1
Use this option to tell syntastic whether to display error messages in balloons
when the mouse is hovered over erroneous lines: >
let g:syntastic_enable_balloons = 1
<
Note that Vim must be compiled with |+balloon_eval|.
*'syntastic_enable_highlighting'*
Default: 1
Use this option to tell syntastic whether to use syntax highlighting to mark
errors (where possible). Highlighting can be turned off with the following >
let g:syntastic_enable_highlighting = 0
<
*'syntastic_always_populate_loc_list'*
Default: 0
Enable this option to tell syntastic to always stick any detected errors into
the |location-list|: >
let g:syntastic_always_populate_loc_list = 1
<
*'syntastic_auto_jump'*
Default: 0
Enable this option if you want the cursor to jump to the first detected issue
when saving or opening a file.
When set to 0 the cursor won't jump automatically. >
let g:syntastic_auto_jump = 0
<
When set to 1 the cursor will always jump to the first issue detected,
regardless of type. >
let g:syntastic_auto_jump = 1
<
When set to 2 the cursor will jump to the first issue detected, but only if
this issue is an error. >
let g:syntastic_auto_jump = 2
<
When set to 3 the cursor will jump to the first error detected, if any. If
all issues detected are warnings, the cursor won't jump. >
let g:syntastic_auto_jump = 3
<
*'syntastic_auto_loc_list'*
Default: 2
Use this option to tell syntastic to automatically open and/or close the
|location-list| (see |syntastic-error-window|).
When set to 0 the error window will not be opened or closed automatically. >
let g:syntastic_auto_loc_list = 0
<
When set to 1 the error window will be automatically opened when errors are
detected, and closed when none are detected. >
let g:syntastic_auto_loc_list = 1
<
When set to 2 the error window will be automatically closed when no errors are
detected, but not opened automatically. >
let g:syntastic_auto_loc_list = 2
<
*'syntastic_loc_list_height'*
Default: 10
Use this option to specify the height of the location lists that syntastic
opens. >
let g:syntastic_loc_list_height = 5
<
*'syntastic_ignore_files'*
Default: []
Use this option to specify files that syntastic should never check. It's a
list of |regular-expression| patterns. The full paths of files (see |::p|) are
matched against these patterns, and the matches are case sensitive. Use |\c|
to specify case insensitive patterns. Example: >
let g:syntastic_ignore_files = ['\m^/usr/include/', '\m\c\.h$']
<
*'syntastic_filetype_map'*
Default: {}
Use this option to map non-standard filetypes to standard ones. Corresponding
checkers are mapped accordingly, which allows syntastic to check files with
non-standard filetypes: >
let g:syntastic_filetype_map = {
\ "latex": "tex",
\ "gentoo-metadata": "xml" }
<
Composite filetypes can also be mapped to simple types, which disables the
default behaviour of running both checkers against the input file: >
let g:syntastic_filetype_map = { "handlebars.html": "handlebars" }
<
*'syntastic_mode_map'*
Default: { "mode": "active",
"active_filetypes": [],
"passive_filetypes": [] }
Use this option to fine tune when automatic syntax checking is done (or not
done).
The option should be set to something like: >
let g:syntastic_mode_map = {
\ "mode": "active",
\ "active_filetypes": ["ruby", "php"],
\ "passive_filetypes": ["puppet"] }
<
"mode" can be mapped to one of two values - "active" or "passive". When set
to "active", syntastic does automatic checking whenever a buffer is saved or
initially opened. When set to "passive" syntastic only checks when the user
calls |:SyntasticCheck|.
The exceptions to these rules are defined with "active_filetypes" and
"passive_filetypes". In passive mode, automatic checks are still done for
filetypes in the "active_filetypes" array (and "passive_filetypes" is
ignored). In active mode, automatic checks are not done for any filetypes in
the "passive_filetypes" array ("active_filetypes" is ignored).
If any of "mode", "active_filetypes", or "passive_filetypes" are left
unspecified, they default to values above.
If local variable |'b:syntastic_mode'| is defined its value takes precedence
over all calculations involving |'syntastic_mode_map'| for the corresponding
buffer.
At runtime, the |:SyntasticToggleMode| command can be used to switch between
active and passive modes.
*'b:syntastic_mode'*
Default: unset
Only the local form |'b:syntastic_mode'| is used. When set to either "active"
or "passive", it takes precedence over |'syntastic_mode_map'| when deciding
whether the corresponding buffer should be checked automatically.
*'syntastic_quiet_messages'*
Default: {}
Use this option to filter out some of the messages produced by checkers. The
option should be set to something like: >
let g:syntastic_quiet_messages = {
\ "!level": "errors",
\ "type": "style",
\ "regex": '\m\[C03\d\d\]',
\ "file:p": ['\m^/usr/include/', '\m\c\.h$'] }
<
Each element turns off messages matching the patterns specified by the
corresponding value. Values are lists, but if a list consist of a single
element you may omit the brackets (e.g. you may write "style" instead of
["style"]). Elements with values [] or '' are ignored (this is useful for
overriding filters, cf. |filter-overrides|).
"level" - takes one of two values, "warnings" or "errors"
"type" - can be either "syntax" or "style"
"regex" - is matched against the messages' text as a case insensitive
|regular-expression|
"file" - is matched against the filenames the messages refer to, as a
case sensitive |regular-expression|.
If a key is prefixed by an exclamation mark "!", the corresponding filter is
negated (i.e. the above example silences all messages that are NOT errors).
The "file" key may be followed by one or more filename modifiers (see
|filename-modifiers|). The modifiers are applied to the filenames the messages
refer to before matching against the value (i.e. in the above example the full
path of the issues are matched against '\m^/usr/include/' and '\m\c\.h$').
If |'syntastic_id_checkers'| is set, filters are applied before error messages
are labeled with the names of the checkers that created them.
There are also checker-specific variants of this option, providing finer
control. They are named |'syntastic_<filetype>_<checker>_quiet_messages'|.
For a particular checker, if both a |'syntastic_quiet_messages'| filter and
a checker-specific filter are present, they are both applied (to the list of
errors produced by the said checker). In case of conflicting values for the
same keys, the values of the checker-specific filters take precedence.
*filter-overrides*
Since filter elements with values [] or '' are ignored, you can disable global
filters for particular checkers, by setting the values of the corresponding
elements in |'syntastic_<filetype>_<checker>_quiet_messages'| to [] or ''. For
example, the following setting will silence all warnings, except for the
ones produced by "pylint": >
let g:syntastic_quiet_messages = { "level": "warnings" }
let g:syntastic_python_pylint_quiet_messages = { "level" : [] }
<
*'syntastic_stl_format'*
Default: [Syntax: line:%F (%t)]
Use this option to control what the syntastic statusline text contains. Several
magic flags are available to insert information:
%e - number of errors
%w - number of warnings
%t - total number of warnings and errors
%fe - line number of first error
%fw - line number of first warning
%F - line number of first warning or error
Several additional flags are available to hide text under certain conditions:
%E{...} - hide the text in the brackets unless there are errors
%W{...} - hide the text in the brackets unless there are warnings
%B{...} - hide the text in the brackets unless there are both warnings AND
errors
These flags can't be nested.
Example: >
let g:syntastic_stl_format = '[%E{Err: %fe #%e}%B{, }%W{Warn: %fw #%w}]'
<
If this format is used and the current buffer has 5 errors and 1 warning
starting on lines 20 and 10 respectively then this would appear on the
statusline: >
[Err: 20 #5, Warn: 10 #1]
<
If the buffer had 2 warnings, starting on line 5 then this would appear: >
[Warn: 5 #2]
<
*'b:syntastic_skip_checks'*
Default: unset
Only the local form |'b:syntastic_skip_checks'| is used. When set to a true
value, no checks are run against the corresponding buffer. Example: >
let b:syntastic_skip_checks = 1
<
*'syntastic_full_redraws'*
Default: 0 in GUI Vim and MacVim, 1 otherwise
Controls whether syntastic calls |:redraw| or |:redraw!| for screen redraws.
Changing it can in principle make screen redraws smoother, but it can also
cause screen to flicker, or cause ghost characters. Leaving it to the default
should be safe.
*'syntastic_exit_checks'*
Default: 0 when running under "cmd.exe" on Windows, 1 otherwise
Syntastic attempts to catch abnormal termination conditions from checkers by
looking at their exit codes. The "cmd.exe" shell on Windows make these checks
meaningless, by returning 1 to Vim when the checkers exit with non-zero codes.
The above variable can be used to disable exit code checks in syntastic.
*'syntastic_shell'*
Default: Vim's 'shell'
This is the (full path to) the shell syntastic will use to run the checkers.
On UNIX and Mac OS-X this shell must accept Bourne-compatible syntax for
file "stdout" and "stderr" redirections ">file" and "2>file". Examples of
compatible shells are "zsh", "bash", "ksh", and of course the original Bourne
"sh".
This shell is independent of Vim's 'shell', and it isn't used for interactive
operations. It must take care to initialize all environment variables needed
by the checkers you're using. Example: >
let g:syntastic_shell = "/bin/sh"
<
*'syntastic_debug'*
Default: 0
Set this to the sum of one or more of the following flags to enable
debugging:
1 - trace general workflow
2 - dump location lists
4 - trace notifiers
8 - trace autocommands
16 - dump options
32 - trace running of specific checkers
Example: >
let g:syntastic_debug = 1
<
Syntastic will then add debugging messages to Vim's |message-history|. You can
examine these messages with |:mes|.
*'syntastic_debug_file'*
Default: unset
When set, debugging messages are written to the file named by its value, in
addition to being added to Vim's |message-history|: >
let g:syntastic_debug_file = '~/syntastic.log'
<
*'syntastic_extra_filetypes'*
Default: []
List of filetypes handled by checkers external to syntastic. If you have a Vim
plugin that adds a checker for syntastic, and if the said checker deals with a
filetype that is unknown to syntastic, you might consider adding that filetype
to this list: >
let g:syntastic_extra_filetypes = [ "make", "gitcommit" ]
<
This will allow |:SyntasticInfo| to do proper tab completion for the new
filetypes.
==============================================================================
5. Checker Options *syntastic-checker-options*
------------------------------------------------------------------------------
5.1 Choosing which checkers to use *syntastic-filetype-checkers*
*'g:syntastic_<filetype>_checkers'*
You can tell syntastic which checkers to run for a given filetype by setting a
variable 'g:syntastic_<filetype>_checkers' to a list of checkers, e.g. >
let g:syntastic_php_checkers = ["php", "phpcs", "phpmd"]
<
*'b:syntastic_checkers'*
There is also a per-buffer version of this setting, 'b:syntastic_checkers'.
When set, it takes precedence over |'g:syntastic_<filetype>_checkers'|. You can
use this in an autocmd to configure specific checkers for particular paths: >
autocmd FileType python if stridx(expand("%:p"), "/some/path/") == 0 |
\ let b:syntastic_checkers = ["pylint"] | endif
<
If neither |'g:syntastic_<filetype>_checkers'| nor |'b:syntastic_checkers'|
is set, a default list of checker is used. Beware however that this list
deliberately kept minimal, for performance reasons.
Take a look at the wiki to find out what checkers and filetypes are supported
by syntastic:
https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers
Use |:SyntasticInfo| to see which checkers are available for a given filetype.
------------------------------------------------------------------------------
5.2 Choosing the executable *syntastic-config-exec*
*'syntastic_<filetype>_<checker>_exec'*
The executable run by a checker is normally defined automatically, when the
checker is registered. You can however override it, by setting the variable
'g:syntastic_<filetype>_<checker>_exec': >
let g:syntastic_ruby_mri_exec = '~/bin/ruby2'
<
This variable has a local version, 'b:syntastic_<filetype>_<checker>_exec',
which takes precedence over the global one in the corresponding buffer.
*'b:syntastic_<checker>_exec'*
And there is also a local variable named 'b:syntastic_<checker>_exec', which
takes precedence over both 'b:syntastic_<filetype>_<checker>_exec' and
'g:syntastic_<filetype>_<checker>_exec' in the buffers where it is defined.
------------------------------------------------------------------------------
5.3 Configuring specific checkers *syntastic-config-makeprg*
Most checkers use the 'makeprgBuild()' function and provide many options by
default - in fact you can customise every part of the command that gets called.
*'syntastic_<filetype>_<checker>_<option>'*
Checkers that use 'makeprgBuild()' construct a 'makeprg' like this: >
let makeprg = self.makeprgBuild({
\ "exe": self.getExec(),
\ "args": "-a -b -c",
\ "post_args": "--more --args",
\ "tail": "2>/dev/null" })
<
The result is a 'makeprg' of the form: >
<exe> <args> <fname> <post_args> <tail>
<
All arguments above are optional, and can be overridden by setting global
variables 'g:syntastic_<filetype>_<checker-name>_<option-name>' - even
parameters not specified in the call to makeprgBuild(). These variables also
have local versions 'b:syntastic_<filetype>_<checker-name>_<option-name>',
which take precedence over the global ones in the corresponding buffers.
If one of these variables has a non-empty default and you want it to be empty,
you can set it to an empty string, e.g.: >
let g:syntastic_javascript_jslint_args = ""
<
*'syntastic_<filetype>_<checker>_exe'*
The 'exe' is normally the same as the 'exec' attribute described above, in
which case it may be omitted. However, you can use it to add environment
variables, or to change the way the checker is run. For example this setup
allows you to run PC-Lint under Wine emulation on Linux: >
let g:syntastic_c_pc_lint_exec = "wine"
let g:syntastic_c_pc_lint_exe = "wine c:/path/to/lint-nt.exe"
<
To override the args and the tail: >
let g:syntastic_c_pc_lint_args = "-w5 -Iz:/usr/include/linux"
let g:syntastic_c_pc_lint_tail = "2>/dev/null"
<
The general form of the override options is: >
syntastic_<filetype>_<checker>_<option-name>
<
For checkers that do not use the 'makeprgBuild()' function you will have to
look at the source code of the checker in question. If there are specific
options that can be set, these are usually documented in the wiki:
https://github.com/scrooloose/syntastic/wiki/Syntax-Checkers
*'syntastic_<filetype>_<checker>_quiet_messages'*
In the same vein, 'g:syntastic_<filetype>_<checker-name>_quiet_messages' can
be used to restrict message filters to messages produced by specific checkers.
Example: >
let g:syntastic_python_pylama_quiet_messages = {
\ "type": "style",
\ "regex": '\m\[C03\d\d\]' }
<
See |syntastic_quiet_messages| for the syntax.
------------------------------------------------------------------------------
5.4 Sorting errors *syntastic-config-sort*
*'syntastic_<filetype>_<checker>_sort'*
Syntastic may decide to group the errors produced by some checkers by file,
then sort them by line number, then by type, then by column number. If you'd
prefer to see the errors in the order in which they are output by the external
checker you can set the variable |'g:syntastic_<filetype>_<checker>_sort'| to 0.
Alternatively, if syntastic doesn't reorder the errors produced by a checker
but you'd like it to sort them, you can set the same variable to 1.
There is also a local version |'b:syntastic_<filetype>_<checker>_sort'| of
this variable, that takes precedence over it in the buffers where it is
defined.
For aggregated lists (see |syntastic-aggregating-errors|) these variables are
ignored if |syntastic_sort_aggregated_errors| is set (which is the default).
==============================================================================
6. Notes *syntastic-notes*
------------------------------------------------------------------------------
6.1. Handling of composite filetypes *syntastic-composite*
Some Vim plugins use composite filetypes, such as "django.python" or
"handlebars.html". Normally, syntastic deals with this situation by splitting
the filetype in its simple components, and calling all checkers that apply.
If this behaviour is not desirable, you can disable it by mapping the
composite filetypes to a simple ones using |syntastic_filetype_map|, e.g.: >
let g:syntastic_filetype_map = { "handlebars.html": "handlebars" }
<
------------------------------------------------------------------------------
6.2 Editing files over network *syntastic-netrw*
The standard plugin |netrw| allows Vim to transparently edit files over
network and inside archives. Currently syntastic doesn't support this mode
of operation. It can only check files that can be accessed directly by local
checkers, without any translation or conversion.
------------------------------------------------------------------------------
6.3 The 'shellslash' option *syntastic-shellslash*
The 'shellslash' option is relevant only on Windows systems. This option
determines (among other things) the rules for quoting command lines, and there
is no easy way for syntastic to make sure its state is appropriate for your
shell. It should be turned off if your 'shell' (or |g:syntastic_shell|) is
"cmd.exe", and on for shells that expect an UNIX-like syntax, such as Cygwin's
"sh". Most checkers will stop working if 'shellslash' is set to the wrong
value.
==============================================================================
7. Compatibility with other software *syntastic-compatibility*
------------------------------------------------------------------------------
7.1 The csh and tcsh shells *syntastic-csh*
The "csh" and "tcsh" shells are mostly compatible with syntastic. However,
some checkers assume Bourne shell syntax for redirecting "stderr". For this
reason, you should point |g:syntastic_shell| to a Bourne-compatible shell,
such as "zsh", "bash", "ksh", or even the original Bourne "sh": >
let g:syntastic_shell = "/bin/sh"
<
------------------------------------------------------------------------------
7.2. Eclim *syntastic-eclim*
Syntastic can be used together with "Eclim" (see http://eclim.org/). However,
by default Eclim disables syntastic's checks for the filetypes it supports, in
order to run its own validation. If you'd prefer to use Eclim but still run
syntastic's checks, set |g:EclimFileTypeValidate| to 0: >
let g:EclimFileTypeValidate = 0
<
It is also possible to re-enable syntastic checks only for some filetypes, and
run Eclim's validation for others. Please consult Eclim's documentation for
details.
------------------------------------------------------------------------------
7.3 The fish shell *syntastic-fish*
At the time of this writing the "fish" shell (see http://fishshell.com/)
doesn't support the standard UNIX syntax for file redirections, and thus it
can't be used together with syntastic. You can however set |g:syntastic_shell|
to a more traditional shell, such as "zsh", "bash", "ksh", or even the
original Bourne "sh": >
let g:syntastic_shell = "/bin/sh"
<
------------------------------------------------------------------------------
7.4. The fizsh shell *syntastic-fizsh*
Using syntastic with the "fizsh" shell (see https://github.com/zsh-users/fizsh)
is possible, but potentially problematic. In order to do it you'll need to set
'shellredir' like this: >
set shellredir=>%s\ 2>&1
<
Please keep in mind however that Vim can't take advantage of any of the
interactive features of "fizsh". Using a more traditional shell such as "zsh",
"bash", "ksh", or the original Bourne "sh" might be a better choice: >
let g:syntastic_shell = "/bin/sh"
<
------------------------------------------------------------------------------
7.5. The PowerShell shell *syntastic-powershell*
At the time of this writing, syntastic is not compatible with using "Windows
PowerShell" (http://technet.microsoft.com/en-us/library/bb978526.aspx) as Vim's
'shell'. You may still run Vim from 'PowerShell', but you do have to point
Vim's 'shell' to a more traditional program, such as "cmd.exe": >
set shell=cmd.exe
<
------------------------------------------------------------------------------
7.6 python-mode *syntastic-pymode*
Syntastic can be used along with the "python-mode" Vim plugin (see
https://github.com/klen/python-mode). However, they both run syntax checks by
default when you save buffers to disk, and this is probably not what you want.
To avoid both plugins opening error windows, you can either set passive mode
for python in syntastic (see |syntastic_mode_map|), or disable lint checks in
"python-mode", by setting |pymode_lint_write| to 0. E.g.: >
let g:pymode_lint_write = 0
<
------------------------------------------------------------------------------
7.7. vim-auto-save *syntastic-vim-auto-save*
Syntastic can be used together with the "vim-auto-save" Vim plugin (see
https://github.com/907th/vim-auto-save). However, syntastic checks in active
mode only work with "vim-auto-save" version 0.1.7 or later.
------------------------------------------------------------------------------
7.8. vim-virtualenv *syntastic-vim-virtualenv*
At the time of this writing, syntastic can't run checkers installed
in Python virtual environments activated by "vim-virtualenv" (see
https://github.com/jmcantrell/vim-virtualenv). This is a limitation of
"vim-virtualenv".
------------------------------------------------------------------------------
7.9 YouCompleteMe *syntastic-ycm*
Syntastic can be used together with the "YouCompleteMe" Vim plugin (see
http://valloric.github.io/YouCompleteMe/). However, by default "YouCompleteMe"
disables syntastic's checkers for the "c", "cpp", "objc", and "objcpp"
filetypes, in order to allow its own checkers to run. If you want to use YCM's
identifier completer but still run syntastic's checkers for those filetypes you
have to set |ycm_show_diagnostics_ui| to 0. E.g.: >
let g:ycm_show_diagnostics_ui = 0
<
==============================================================================
8. About *syntastic-about*
The core maintainers of syntastic are:
Martin Grenfell (GitHub: scrooloose)
Gregor Uhlenheuer (GitHub: kongo2002)
LCD 047 (GitHub: lcd047)
Find the latest version of syntastic at:
http://github.com/scrooloose/syntastic
==============================================================================
9. License *syntastic-license*
Syntastic is released under the WTFPL.
See http://sam.zoy.org/wtfpl/COPYING.
vim:tw=78:sw=4:ft=help:norl:

View file

@ -0,0 +1,669 @@
"============================================================================
"File: syntastic.vim
"Description: Vim plugin for on the fly syntax checking.
"License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"
"============================================================================
if exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_plugin = 1
if has('reltime')
let g:_SYNTASTIC_START = reltime()
lockvar! g:_SYNTASTIC_START
endif
let g:_SYNTASTIC_VERSION = '3.6.0-57'
lockvar g:_SYNTASTIC_VERSION
" Sanity checks {{{1
for s:feature in [
\ 'autocmd',
\ 'eval',
\ 'file_in_path',
\ 'modify_fname',
\ 'quickfix',
\ 'reltime',
\ 'user_commands'
\ ]
if !has(s:feature)
call syntastic#log#error("need Vim compiled with feature " . s:feature)
finish
endif
endfor
let s:_running_windows = syntastic#util#isRunningWindows()
lockvar s:_running_windows
if !exists('g:syntastic_shell')
let g:syntastic_shell = &shell
endif
if s:_running_windows
let g:_SYNTASTIC_UNAME = 'Windows'
elseif executable('uname')
try
let g:_SYNTASTIC_UNAME = split(syntastic#util#system('uname'), "\n")[0]
catch /\m^Vim\%((\a\+)\)\=:E484/
call syntastic#log#error("your shell " . syntastic#util#var('shell') . " can't handle traditional UNIX syntax for redirections")
finish
catch /\m^Vim\%((\a\+)\)\=:E684/
let g:_SYNTASTIC_UNAME = 'Unknown'
endtry
else
let g:_SYNTASTIC_UNAME = 'Unknown'
endif
lockvar g:_SYNTASTIC_UNAME
" }}}1
" Defaults {{{1
let g:_SYNTASTIC_DEFAULTS = {
\ 'aggregate_errors': 0,
\ 'always_populate_loc_list': 0,
\ 'auto_jump': 0,
\ 'auto_loc_list': 2,
\ 'check_on_open': 0,
\ 'check_on_wq': 1,
\ 'cursor_columns': 1,
\ 'debug': 0,
\ 'echo_current_error': 1,
\ 'enable_balloons': 1,
\ 'enable_highlighting': 1,
\ 'enable_signs': 1,
\ 'error_symbol': '>>',
\ 'exit_checks': !(s:_running_windows && syntastic#util#var('shell', &shell) =~? '\m\<cmd\.exe$'),
\ 'filetype_map': {},
\ 'full_redraws': !(has('gui_running') || has('gui_macvim')),
\ 'id_checkers': 1,
\ 'ignore_extensions': '\c\v^([gx]?z|lzma|bz2)$',
\ 'ignore_files': [],
\ 'loc_list_height': 10,
\ 'quiet_messages': {},
\ 'reuse_loc_lists': 0,
\ 'shell': &shell,
\ 'sort_aggregated_errors': 1,
\ 'stl_format': '[Syntax: line:%F (%t)]',
\ 'style_error_symbol': 'S>',
\ 'style_warning_symbol': 'S>',
\ 'warning_symbol': '>>'
\ }
lockvar! g:_SYNTASTIC_DEFAULTS
for s:key in keys(g:_SYNTASTIC_DEFAULTS)
if !exists('g:syntastic_' . s:key)
let g:syntastic_{s:key} = copy(g:_SYNTASTIC_DEFAULTS[s:key])
endif
endfor
if exists("g:syntastic_quiet_warnings")
call syntastic#log#oneTimeWarn("variable g:syntastic_quiet_warnings is deprecated, please use let g:syntastic_quiet_messages = {'level': 'warnings'} instead")
if g:syntastic_quiet_warnings
let s:quiet_warnings = get(g:syntastic_quiet_messages, 'type', [])
if type(s:quiet_warnings) != type([])
let s:quiet_warnings = [s:quiet_warnings]
endif
call add(s:quiet_warnings, 'warnings')
let g:syntastic_quiet_messages['type'] = s:quiet_warnings
endif
endif
" }}}1
" Debug {{{1
let s:_DEBUG_DUMP_OPTIONS = [
\ 'shell',
\ 'shellcmdflag',
\ 'shellpipe',
\ 'shellquote',
\ 'shellredir',
\ 'shellslash',
\ 'shelltemp',
\ 'shellxquote'
\ ]
if v:version > 703 || (v:version == 703 && has('patch446'))
call add(s:_DEBUG_DUMP_OPTIONS, 'shellxescape')
endif
lockvar! s:_DEBUG_DUMP_OPTIONS
" debug constants
let g:_SYNTASTIC_DEBUG_TRACE = 1
lockvar g:_SYNTASTIC_DEBUG_TRACE
let g:_SYNTASTIC_DEBUG_LOCLIST = 2
lockvar g:_SYNTASTIC_DEBUG_LOCLIST
let g:_SYNTASTIC_DEBUG_NOTIFICATIONS = 4
lockvar g:_SYNTASTIC_DEBUG_NOTIFICATIONS
let g:_SYNTASTIC_DEBUG_AUTOCOMMANDS = 8
lockvar g:_SYNTASTIC_DEBUG_AUTOCOMMANDS
let g:_SYNTASTIC_DEBUG_VARIABLES = 16
lockvar g:_SYNTASTIC_DEBUG_VARIABLES
let g:_SYNTASTIC_DEBUG_CHECKERS = 32
lockvar g:_SYNTASTIC_DEBUG_CHECKERS
" }}}1
runtime! plugin/syntastic/*.vim
let s:registry = g:SyntasticRegistry.Instance()
let s:notifiers = g:SyntasticNotifiers.Instance()
let s:modemap = g:SyntasticModeMap.Instance()
" Commands {{{1
" @vimlint(EVL103, 1, a:cursorPos)
" @vimlint(EVL103, 1, a:cmdLine)
" @vimlint(EVL103, 1, a:argLead)
function! s:CompleteCheckerName(argLead, cmdLine, cursorPos) abort " {{{2
let checker_names = []
for ft in s:_resolve_filetypes([])
call extend(checker_names, s:registry.getNamesOfAvailableCheckers(ft))
endfor
return join(checker_names, "\n")
endfunction " }}}2
" @vimlint(EVL103, 0, a:cursorPos)
" @vimlint(EVL103, 0, a:cmdLine)
" @vimlint(EVL103, 0, a:argLead)
" @vimlint(EVL103, 1, a:cursorPos)
" @vimlint(EVL103, 1, a:cmdLine)
" @vimlint(EVL103, 1, a:argLead)
function! s:CompleteFiletypes(argLead, cmdLine, cursorPos) abort " {{{2
return join(s:registry.getKnownFiletypes(), "\n")
endfunction " }}}2
" @vimlint(EVL103, 0, a:cursorPos)
" @vimlint(EVL103, 0, a:cmdLine)
" @vimlint(EVL103, 0, a:argLead)
command! -nargs=* -complete=custom,s:CompleteCheckerName SyntasticCheck call SyntasticCheck(<f-args>)
command! -nargs=? -complete=custom,s:CompleteFiletypes SyntasticInfo call SyntasticInfo(<f-args>)
command! Errors call SyntasticErrors()
command! SyntasticReset call SyntasticReset()
command! SyntasticToggleMode call SyntasticToggleMode()
command! SyntasticSetLoclist call SyntasticSetLoclist()
" }}}1
" Public API {{{1
function! SyntasticCheck(...) abort " {{{2
call s:UpdateErrors(0, a:000)
call syntastic#util#redraw(g:syntastic_full_redraws)
endfunction " }}}2
function! SyntasticInfo(...) abort " {{{2
call s:modemap.modeInfo(a:000)
call s:registry.echoInfoFor(s:_resolve_filetypes(a:000))
call s:_explain_skip(a:000)
endfunction " }}}2
function! SyntasticErrors() abort " {{{2
call g:SyntasticLoclist.current().show()
endfunction " }}}2
function! SyntasticReset() abort " {{{2
call s:ClearCache()
call s:notifiers.refresh(g:SyntasticLoclist.New([]))
endfunction " }}}2
function! SyntasticToggleMode() abort " {{{2
call s:modemap.toggleMode()
call s:ClearCache()
call s:notifiers.refresh(g:SyntasticLoclist.New([]))
call s:modemap.echoMode()
endfunction " }}}2
function! SyntasticSetLoclist() abort " {{{2
call g:SyntasticLoclist.current().setloclist()
endfunction " }}}2
" }}}1
" Autocommands {{{1
augroup syntastic
autocmd BufReadPost * call s:BufReadPostHook()
autocmd BufWritePost * call s:BufWritePostHook()
autocmd BufEnter * call s:BufEnterHook()
augroup END
if v:version > 703 || (v:version == 703 && has('patch544'))
" QuitPre was added in Vim 7.3.544
augroup syntastic
autocmd QuitPre * call s:QuitPreHook()
augroup END
endif
function! s:BufReadPostHook() abort " {{{2
if g:syntastic_check_on_open
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS,
\ 'autocmd: BufReadPost, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))))
call s:UpdateErrors(1, [])
endif
endfunction " }}}2
function! s:BufWritePostHook() abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS,
\ 'autocmd: BufWritePost, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))))
call s:UpdateErrors(1, [])
endfunction " }}}2
function! s:BufEnterHook() abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS,
\ 'autocmd: BufEnter, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))) .
\ ', &buftype = ' . string(&buftype))
if &buftype == ''
call s:notifiers.refresh(g:SyntasticLoclist.current())
elseif &buftype ==# 'quickfix'
" TODO: this is needed because in recent versions of Vim lclose
" can no longer be called from BufWinLeave
" TODO: at this point there is no b:syntastic_loclist
let loclist = filter(copy(getloclist(0)), 'v:val["valid"] == 1')
let owner = str2nr(getbufvar(bufnr(""), 'syntastic_owner_buffer'))
let buffers = syntastic#util#unique(map(loclist, 'v:val["bufnr"]') + (owner ? [owner] : []))
if get(w:, 'syntastic_loclist_set', 0) && !empty(loclist) && empty(filter( buffers, 'syntastic#util#bufIsActive(v:val)' ))
call SyntasticLoclistHide()
endif
endif
endfunction " }}}2
function! s:QuitPreHook() abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_AUTOCOMMANDS,
\ 'autocmd: QuitPre, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))))
let b:syntastic_skip_checks = get(b:, 'syntastic_skip_checks', 0) || !syntastic#util#var('check_on_wq')
if get(w:, 'syntastic_loclist_set', 0)
call SyntasticLoclistHide()
endif
endfunction " }}}2
" }}}1
" Main {{{1
"refresh and redraw all the error info for this buf when saving or reading
function! s:UpdateErrors(auto_invoked, checker_names) abort " {{{2
call syntastic#log#debugShowVariables(g:_SYNTASTIC_DEBUG_TRACE, 'version')
call syntastic#log#debugShowOptions(g:_SYNTASTIC_DEBUG_TRACE, s:_DEBUG_DUMP_OPTIONS)
call syntastic#log#debugDump(g:_SYNTASTIC_DEBUG_VARIABLES)
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'UpdateErrors' . (a:auto_invoked ? ' (auto)' : '') .
\ ': ' . (len(a:checker_names) ? join(a:checker_names) : 'default checkers'))
if s:_skip_file()
return
endif
call s:modemap.synch()
let run_checks = !a:auto_invoked || s:modemap.doAutoChecking()
if run_checks
call s:CacheErrors(a:checker_names)
endif
let loclist = g:SyntasticLoclist.current()
if exists('*SyntasticCheckHook')
call SyntasticCheckHook(loclist.getRaw())
endif
" populate loclist and jump {{{3
let do_jump = syntastic#util#var('auto_jump') + 0
if do_jump == 2
let do_jump = loclist.getFirstError(1)
elseif do_jump == 3
let do_jump = loclist.getFirstError()
elseif 0 > do_jump || do_jump > 3
let do_jump = 0
endif
let w:syntastic_loclist_set = 0
if syntastic#util#var('always_populate_loc_list') || do_jump
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'loclist: setloclist (new)')
call setloclist(0, loclist.getRaw())
let w:syntastic_loclist_set = 1
if run_checks && do_jump && !loclist.isEmpty()
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'loclist: jump')
execute 'silent! lrewind ' . do_jump
" XXX: Vim doesn't call autocmd commands in a predictible
" order, which can lead to missing filetype when jumping
" to a new file; the following is a workaround for the
" resulting brain damage
if &filetype == ''
silent! filetype detect
endif
endif
endif
" }}}3
call s:notifiers.refresh(loclist)
endfunction " }}}2
"clear the loc list for the buffer
function! s:ClearCache() abort " {{{2
call s:notifiers.reset(g:SyntasticLoclist.current())
call b:syntastic_loclist.destroy()
endfunction " }}}2
"detect and cache all syntax errors in this buffer
function! s:CacheErrors(checker_names) abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: ' .
\ (len(a:checker_names) ? join(a:checker_names) : 'default checkers'))
call s:ClearCache()
let newLoclist = g:SyntasticLoclist.New([])
if !s:_skip_file()
" debug logging {{{3
call syntastic#log#debugShowVariables(g:_SYNTASTIC_DEBUG_TRACE, 'aggregate_errors')
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, '$PATH = ' . string($PATH))
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'getcwd() = ' . string(getcwd()))
" }}}3
let filetypes = s:_resolve_filetypes([])
let aggregate_errors = syntastic#util#var('aggregate_errors') || len(filetypes) > 1
let decorate_errors = aggregate_errors && syntastic#util#var('id_checkers')
let sort_aggregated_errors = aggregate_errors && syntastic#util#var('sort_aggregated_errors')
let clist = []
for type in filetypes
call extend(clist, s:registry.getCheckers(type, a:checker_names))
endfor
let names = []
let unavailable_checkers = 0
for checker in clist
let cname = checker.getFiletype() . '/' . checker.getName()
if !checker.isAvailable()
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: Checker ' . cname . ' is not available')
let unavailable_checkers += 1
continue
endif
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: Invoking checker: ' . cname)
let loclist = checker.getLocList()
if !loclist.isEmpty()
if decorate_errors
call loclist.decorate(cname)
endif
call add(names, cname)
if checker.wantSort() && !sort_aggregated_errors
call loclist.sort()
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'sorted:', loclist)
endif
let newLoclist = newLoclist.extend(loclist)
if !aggregate_errors
break
endif
endif
endfor
" set names {{{3
if !empty(names)
if len(syntastic#util#unique(map( copy(names), 'substitute(v:val, "\\m/.*", "", "")' ))) == 1
let type = substitute(names[0], '\m/.*', '', '')
let name = join(map( names, 'substitute(v:val, "\\m.\\{-}/", "", "")' ), ', ')
call newLoclist.setName( name . ' ('. type . ')' )
else
" checkers from mixed types
call newLoclist.setName(join(names, ', '))
endif
endif
" }}}3
" issue warning about no active checkers {{{3
if len(clist) == unavailable_checkers
if !empty(a:checker_names)
if len(a:checker_names) == 1
call syntastic#log#warn('checker ' . a:checker_names[0] . ' is not available')
else
call syntastic#log#warn('checkers ' . join(a:checker_names, ', ') . ' are not available')
endif
else
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'CacheErrors: no checkers available for ' . &filetype)
endif
endif
" }}}3
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'aggregated:', newLoclist)
if sort_aggregated_errors
call newLoclist.sort()
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'sorted:', newLoclist)
endif
endif
call newLoclist.deploy()
endfunction " }}}2
"Emulates the :lmake command. Sets up the make environment according to the
"options given, runs make, resets the environment, returns the location list
"
"a:options can contain the following keys:
" 'makeprg'
" 'errorformat'
"
"The corresponding options are set for the duration of the function call. They
"are set with :let, so dont escape spaces.
"
"a:options may also contain:
" 'defaults' - a dict containing default values for the returned errors
" 'subtype' - all errors will be assigned the given subtype
" 'preprocess' - a function to be applied to the error file before parsing errors
" 'postprocess' - a list of functions to be applied to the error list
" 'cwd' - change directory to the given path before running the checker
" 'env' - environment variables to set before running the checker
" 'returns' - a list of valid exit codes for the checker
" @vimlint(EVL102, 1, l:env_save)
function! SyntasticMake(options) abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'SyntasticMake: called with options:', a:options)
" save options and locale env variables {{{3
let old_local_errorformat = &l:errorformat
let old_errorformat = &errorformat
let old_cwd = getcwd()
" }}}3
if has_key(a:options, 'errorformat')
let &errorformat = a:options['errorformat']
endif
if has_key(a:options, 'cwd')
execute 'lcd ' . fnameescape(a:options['cwd'])
endif
" set environment variables {{{3
let env_save = {}
if has_key(a:options, 'env') && len(a:options['env'])
for key in keys(a:options['env'])
if key =~? '\m^[a-z_]\+$'
execute 'let env_save[' . string(key) . '] = $' . key
execute 'let $' . key . ' = ' . string(a:options['env'][key])
endif
endfor
endif
" }}}3
let err_lines = split(syntastic#util#system(a:options['makeprg']), "\n", 1)
" restore environment variables {{{3
if len(env_save)
for key in keys(env_save)
execute 'let $' . key . ' = ' . string(env_save[key])
endfor
endif
" }}}3
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'checker output:', err_lines)
" Does it still make sense to go on?
let bailout =
\ syntastic#util#var('exit_checks') &&
\ has_key(a:options, 'returns') &&
\ index(a:options['returns'], v:shell_error) == -1
if !bailout
if has_key(a:options, 'Preprocess')
let err_lines = call(a:options['Preprocess'], [err_lines])
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'preprocess (external):', err_lines)
elseif has_key(a:options, 'preprocess')
let err_lines = call('syntastic#preprocess#' . a:options['preprocess'], [err_lines])
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'preprocess:', err_lines)
endif
lgetexpr err_lines
let errors = deepcopy(getloclist(0))
if has_key(a:options, 'cwd')
execute 'lcd ' . fnameescape(old_cwd)
endif
try
silent lolder
catch /\m^Vim\%((\a\+)\)\=:E380/
" E380: At bottom of quickfix stack
call setloclist(0, [], 'r')
catch /\m^Vim\%((\a\+)\)\=:E776/
" E776: No location list
" do nothing
endtry
else
let errors = []
endif
" restore options {{{3
let &errorformat = old_errorformat
let &l:errorformat = old_local_errorformat
" }}}3
if !s:_running_windows && (s:_os_name() =~? "FreeBSD" || s:_os_name() =~? "OpenBSD")
call syntastic#util#redraw(g:syntastic_full_redraws)
endif
if bailout
throw 'Syntastic: checker error'
endif
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'raw loclist:', errors)
if has_key(a:options, 'defaults')
call s:_add_to_errors(errors, a:options['defaults'])
endif
" Add subtype info if present.
if has_key(a:options, 'subtype')
call s:_add_to_errors(errors, { 'subtype': a:options['subtype'] })
endif
if has_key(a:options, 'Postprocess') && !empty(a:options['Postprocess'])
for rule in a:options['Postprocess']
let errors = call(rule, [errors])
endfor
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'postprocess (external):', errors)
elseif has_key(a:options, 'postprocess') && !empty(a:options['postprocess'])
for rule in a:options['postprocess']
let errors = call('syntastic#postprocess#' . rule, [errors])
endfor
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'postprocess:', errors)
endif
return errors
endfunction " }}}2
" @vimlint(EVL102, 0, l:env_save)
"return a string representing the state of buffer according to
"g:syntastic_stl_format
"
"return '' if no errors are cached for the buffer
function! SyntasticStatuslineFlag() abort " {{{2
return g:SyntasticLoclist.current().getStatuslineFlag()
endfunction " }}}2
" }}}1
" Utilities {{{1
function! s:_resolve_filetypes(filetypes) abort " {{{2
let type = len(a:filetypes) ? a:filetypes[0] : &filetype
return split( get(g:syntastic_filetype_map, type, type), '\m\.' )
endfunction " }}}2
function! s:_ignore_file(filename) abort " {{{2
let fname = fnamemodify(a:filename, ':p')
for pattern in g:syntastic_ignore_files
if fname =~# pattern
return 1
endif
endfor
return 0
endfunction " }}}2
" Skip running in special buffers
function! s:_skip_file() abort " {{{2
let fname = expand('%', 1)
let skip = get(b:, 'syntastic_skip_checks', 0) || (&buftype != '') ||
\ !filereadable(fname) || getwinvar(0, '&diff') || s:_ignore_file(fname) ||
\ fnamemodify(fname, ':e') =~? g:syntastic_ignore_extensions
if skip
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, '_skip_file: skipping checks')
endif
return skip
endfunction " }}}2
" Explain why checks will be skipped for the current file
function! s:_explain_skip(filetypes) abort " {{{2
if empty(a:filetypes) && s:_skip_file()
let why = []
let fname = expand('%', 1)
if get(b:, 'syntastic_skip_checks', 0)
call add(why, 'b:syntastic_skip_checks set')
endif
if &buftype != ''
call add(why, 'buftype = ' . string(&buftype))
endif
if !filereadable(fname)
call add(why, 'file not readable / not local')
endif
if getwinvar(0, '&diff')
call add(why, 'diff mode')
endif
if s:_ignore_file(fname)
call add(why, 'filename matching g:syntastic_ignore_files')
endif
if fnamemodify(fname, ':e') =~? g:syntastic_ignore_extensions
call add(why, 'extension matching g:syntastic_ignore_extensions')
endif
echomsg 'The current file will not be checked (' . join(why, ', ') . ')'
endif
endfunction " }}}2
" Take a list of errors and add default values to them from a:options
function! s:_add_to_errors(errors, options) abort " {{{2
for err in a:errors
for key in keys(a:options)
if !has_key(err, key) || empty(err[key])
let err[key] = a:options[key]
endif
endfor
endfor
return a:errors
endfunction " }}}2
function! s:_os_name() abort " {{{2
return g:_SYNTASTIC_UNAME
endfunction " }}}2
" }}}1
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,38 @@
if exists("g:loaded_syntastic_notifier_autoloclist") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_notifier_autoloclist = 1
let g:SyntasticAutoloclistNotifier = {}
" Public methods {{{1
"
function! g:SyntasticAutoloclistNotifier.New() abort " {{{2
let newObj = copy(self)
return newObj
endfunction " }}}2
function! g:SyntasticAutoloclistNotifier.refresh(loclist) abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'autoloclist: refresh')
call g:SyntasticAutoloclistNotifier.AutoToggle(a:loclist)
endfunction " }}}2
function! g:SyntasticAutoloclistNotifier.AutoToggle(loclist) abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'autoloclist: toggle')
if !a:loclist.isEmpty()
if syntastic#util#var('auto_loc_list') == 1
call a:loclist.show()
endif
else
if syntastic#util#var('auto_loc_list') > 0
"TODO: this will close the loc list window if one was opened by
"something other than syntastic
lclose
endif
endif
endfunction " }}}2
" }}}1
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,59 @@
if exists("g:loaded_syntastic_notifier_balloons") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_notifier_balloons = 1
if !has('balloon_eval')
let g:syntastic_enable_balloons = 0
endif
let g:SyntasticBalloonsNotifier = {}
" Public methods {{{1
function! g:SyntasticBalloonsNotifier.New() abort " {{{2
let newObj = copy(self)
return newObj
endfunction " }}}2
function! g:SyntasticBalloonsNotifier.enabled() abort " {{{2
return has('balloon_eval') && syntastic#util#var('enable_balloons')
endfunction " }}}2
" Update the error balloons
function! g:SyntasticBalloonsNotifier.refresh(loclist) abort " {{{2
unlet! b:syntastic_private_balloons
if self.enabled() && !a:loclist.isEmpty()
let b:syntastic_private_balloons = a:loclist.balloons()
if !empty(b:syntastic_private_balloons)
set ballooneval balloonexpr=SyntasticBalloonsExprNotifier()
endif
endif
endfunction " }}}2
" Reset the error balloons
" @vimlint(EVL103, 1, a:loclist)
function! g:SyntasticBalloonsNotifier.reset(loclist) abort " {{{2
let b:syntastic_private_balloons = {}
if has('balloon_eval')
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'balloons: reset')
unlet! b:syntastic_private_balloons
set noballooneval
endif
endfunction " }}}2
" @vimlint(EVL103, 0, a:loclist)
" }}}1
" Private functions {{{1
function! SyntasticBalloonsExprNotifier() abort " {{{2
if !exists('b:syntastic_private_balloons')
return ''
endif
return get(b:syntastic_private_balloons, v:beval_lnum, '')
endfunction " }}}2
" }}}1
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,228 @@
if exists("g:loaded_syntastic_checker") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_checker = 1
let g:SyntasticChecker = {}
" Public methods {{{1
function! g:SyntasticChecker.New(args) abort " {{{2
let newObj = copy(self)
let newObj._filetype = a:args['filetype']
let newObj._name = a:args['name']
let newObj._exec = get(a:args, 'exec', newObj._name)
if has_key(a:args, 'redirect')
let [filetype, name] = split(a:args['redirect'], '/')
let prefix = 'SyntaxCheckers_' . filetype . '_' . name . '_'
if exists('g:syntastic_' . filetype . '_' . name . '_sort') && !exists('g:syntastic_' . newObj._filetype . '_' . newObj._name . '_sort')
let g:syntastic_{newObj._filetype}_{newObj._name}_sort = g:syntastic_{filetype}_{name}_sort
endif
else
let prefix = 'SyntaxCheckers_' . newObj._filetype . '_' . newObj._name . '_'
endif
let newObj._locListFunc = function(prefix . 'GetLocList')
if exists('*' . prefix . 'IsAvailable')
let newObj._isAvailableFunc = function(prefix . 'IsAvailable')
else
let newObj._isAvailableFunc = function('s:_isAvailableDefault')
endif
if exists('*' . prefix . 'GetHighlightRegex')
let newObj._highlightRegexFunc = function(prefix . 'GetHighlightRegex')
endif
return newObj
endfunction " }}}2
function! g:SyntasticChecker.getFiletype() abort " {{{2
return self._filetype
endfunction " }}}2
function! g:SyntasticChecker.getName() abort " {{{2
return self._name
endfunction " }}}2
" Synchronise _exec with user's setting. Force re-validation if needed.
"
" XXX: This function must be called at least once before calling either
" getExec() or getExecEscaped(). Normally isAvailable() does that for you
" automatically, but you should keep still this in mind if you change the
" current checker workflow.
function! g:SyntasticChecker.syncExec() dict " {{{2
let user_exec =
\ expand( exists('b:syntastic_' . self._name . '_exec') ? b:syntastic_{self._name}_exec :
\ syntastic#util#var(self._filetype . '_' . self._name . '_exec'), 1 )
if user_exec != '' && user_exec !=# self._exec
let self._exec = user_exec
if has_key(self, '_available')
" we have a new _exec on the block, it has to be validated
call remove(self, '_available')
endif
endif
endfunction " }}}2
function! g:SyntasticChecker.getExec() abort " {{{2
return self._exec
endfunction " }}}2
function! g:SyntasticChecker.getExecEscaped() abort " {{{2
return syntastic#util#shescape(self._exec)
endfunction " }}}2
function! g:SyntasticChecker.getLocListRaw() abort " {{{2
let name = self._filetype . '/' . self._name
try
let list = self._locListFunc()
if self._exec != ''
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'getLocList: checker ' . name . ' returned ' . v:shell_error)
endif
catch /\m\C^Syntastic: checker error$/
let list = []
if self._exec != ''
call syntastic#log#error('checker ' . name . ' returned abnormal status ' . v:shell_error)
else
call syntastic#log#error('checker ' . name . ' aborted')
endif
endtry
call self._populateHighlightRegexes(list)
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, name . ' raw:', list)
call self._quietMessages(list)
return list
endfunction " }}}2
function! g:SyntasticChecker.getLocList() abort " {{{2
return g:SyntasticLoclist.New(self.getLocListRaw())
endfunction " }}}2
function! g:SyntasticChecker.getVersion(...) abort " {{{2
if !exists('self._version')
let command = a:0 ? a:1 : self.getExecEscaped() . ' --version'
let version_output = syntastic#util#system(command)
call self.log('getVersion: ' . string(command) . ': ' .
\ string(split(version_output, "\n", 1)) .
\ (v:shell_error ? ' (exit code ' . v:shell_error . ')' : '') )
call self.setVersion(syntastic#util#parseVersion(version_output))
endif
return get(self, '_version', [])
endfunction " }}}2
function! g:SyntasticChecker.setVersion(version) abort " {{{2
if len(a:version)
let self._version = copy(a:version)
call self.log(self.getExec() . ' version =', a:version)
else
call syntastic#log#error("checker " . self._filetype . "/" . self._name . ": can't parse version string (abnormal termination?)")
endif
endfunction " }}}2
function! g:SyntasticChecker.log(msg, ...) abort " {{{2
let leader = self._filetype . '/' . self._name . ': '
if a:0 > 0
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, leader . a:msg, a:1)
else
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, leader . a:msg)
endif
endfunction " }}}2
function! g:SyntasticChecker.makeprgBuild(opts) abort " {{{2
let basename = self._filetype . '_' . self._name . '_'
let parts = []
call extend(parts, self._getOpt(a:opts, basename, 'exe', self.getExecEscaped()))
call extend(parts, self._getOpt(a:opts, basename, 'args', ''))
call extend(parts, self._getOpt(a:opts, basename, 'fname', syntastic#util#shexpand('%')))
call extend(parts, self._getOpt(a:opts, basename, 'post_args', ''))
call extend(parts, self._getOpt(a:opts, basename, 'tail', ''))
return join(parts)
endfunction " }}}2
function! g:SyntasticChecker.isAvailable() abort " {{{2
call self.syncExec()
if !has_key(self, '_available')
let self._available = self._isAvailableFunc()
endif
return self._available
endfunction " }}}2
function! g:SyntasticChecker.wantSort() abort " {{{2
return syntastic#util#var(self._filetype . '_' . self._name . '_sort', 0)
endfunction " }}}2
" This method is no longer used by syntastic. It's here only to maintain
" backwards compatibility with external checkers which might depend on it.
function! g:SyntasticChecker.setWantSort(val) abort " {{{2
if !exists('g:syntastic_' . self._filetype . '_' . self._name . '_sort')
let g:syntastic_{self._filetype}_{self._name}_sort = a:val
endif
endfunction " }}}2
" }}}1
" Private methods {{{1
function! g:SyntasticChecker._quietMessages(errors) abort " {{{2
" wildcard quiet_messages
let quiet_filters = copy(syntastic#util#var('quiet_messages', {}))
if type(quiet_filters) != type({})
call syntastic#log#warn('ignoring invalid syntastic_quiet_messages')
unlet quiet_filters
let quiet_filters = {}
endif
" per checker quiet_messages
let name = self._filetype . '_' . self._name
try
call extend( quiet_filters, copy(syntastic#util#var(name . '_quiet_messages', {})), 'force' )
catch /\m^Vim\%((\a\+)\)\=:E712/
call syntastic#log#warn('ignoring invalid syntastic_' . name . '_quiet_messages')
endtry
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'quiet_messages filter:', quiet_filters)
if !empty(quiet_filters)
call syntastic#util#dictFilter(a:errors, quiet_filters)
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_LOCLIST, 'filtered by quiet_messages:', a:errors)
endif
endfunction " }}}2
function! g:SyntasticChecker._populateHighlightRegexes(errors) abort " {{{2
if has_key(self, '_highlightRegexFunc')
for e in a:errors
if e['valid']
let term = self._highlightRegexFunc(e)
if term != ''
let e['hl'] = term
endif
endif
endfor
endif
endfunction " }}}2
function! g:SyntasticChecker._getOpt(opts, basename, name, default) abort " {{{2
let ret = []
call extend( ret, syntastic#util#argsescape(get(a:opts, a:name . '_before', '')) )
call extend( ret, syntastic#util#argsescape(syntastic#util#var( a:basename . a:name, get(a:opts, a:name, a:default) )) )
call extend( ret, syntastic#util#argsescape(get(a:opts, a:name . '_after', '')) )
return ret
endfunction " }}}2
" }}}1
" Private functions {{{1
function! s:_isAvailableDefault() dict " {{{2
return executable(self.getExec())
endfunction " }}}2
" }}}1
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -0,0 +1,138 @@
if exists("g:loaded_syntastic_notifier_cursor") || !exists("g:loaded_syntastic_plugin")
finish
endif
let g:loaded_syntastic_notifier_cursor = 1
let g:SyntasticCursorNotifier = {}
" Public methods {{{1
function! g:SyntasticCursorNotifier.New() abort " {{{2
let newObj = copy(self)
return newObj
endfunction " }}}2
function! g:SyntasticCursorNotifier.enabled() abort " {{{2
return syntastic#util#var('echo_current_error')
endfunction " }}}2
function! g:SyntasticCursorNotifier.refresh(loclist) abort " {{{2
if self.enabled() && !a:loclist.isEmpty()
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'cursor: refresh')
let b:syntastic_private_messages = copy(a:loclist.messages(bufnr('')))
let b:syntastic_private_line = -1
let b:syntastic_cursor_columns = a:loclist.getCursorColumns()
autocmd! syntastic CursorMoved
autocmd syntastic CursorMoved * call SyntasticRefreshCursor()
endif
endfunction " }}}2
" @vimlint(EVL103, 1, a:loclist)
function! g:SyntasticCursorNotifier.reset(loclist) abort " {{{2
call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'cursor: reset')
autocmd! syntastic CursorMoved
unlet! b:syntastic_private_messages
let b:syntastic_private_line = -1
endfunction " }}}2
" @vimlint(EVL103, 0, a:loclist)
" }}}1
" Private functions {{{1
function! SyntasticRefreshCursor() abort " {{{2
if !exists('b:syntastic_private_messages') || empty(b:syntastic_private_messages)
" file not checked
return
endif
if !exists('b:syntastic_private_line')
let b:syntastic_private_line = -1
endif
let l = line('.')
let current_messages = get(b:syntastic_private_messages, l, {})
if !exists('b:syntastic_cursor_columns')
let b:syntastic_cursor_columns = g:syntastic_cursor_columns
endif
if b:syntastic_cursor_columns
let c = virtcol('.')
if !exists('b:syntastic_private_idx')
let b:syntastic_private_idx = -1
endif
if s:_is_same_index(l, b:syntastic_private_line, c, b:syntastic_private_idx, current_messages)
return
else
let b:syntastic_private_line = l
endif
if !empty(current_messages)
let b:syntastic_private_idx = s:_find_index(c, current_messages)
call syntastic#util#wideMsg(current_messages[b:syntastic_private_idx].text)
else
let b:syntastic_private_idx = -1
echo
endif
else
if l == b:syntastic_private_line
return
endif
let b:syntastic_private_line = l
if !empty(current_messages)
call syntastic#util#wideMsg(current_messages[0].text)
else
echo
endif
endif
endfunction " }}}2
" }}}1
" Utilities {{{1
function! s:_is_same_index(line, old_line, column, idx, messages) abort " {{{2
if a:old_line >= 0 && a:line == a:old_line && a:idx >= 0
if len(a:messages) <= 1
return 1
endif
if a:messages[a:idx].scol <= a:column || a:idx == 0
if a:idx == len(a:messages) - 1 || a:column < a:messages[a:idx + 1].scol
return 1
else
return 0
endif
else
return 0
endif
else
return 0
endif
endfunction " }}}2
function! s:_find_index(column, messages) abort " {{{2
let max = len(a:messages) - 1
if max == 0
return 0
endif
let min = 0
" modified binary search: assign index 0 to columns to the left of the first error
while min < max - 1
let mid = (min + max) / 2
if a:column < a:messages[mid].scol
let max = mid
else
let min = mid
endif
endwhile
return a:column < a:messages[max].scol ? min : max
endfunction " }}}2
" }}}1
" vim: set sw=4 sts=4 et fdm=marker:

Some files were not shown because too many files have changed in this diff Show more