sorting and escaping

This commit is contained in:
Kien N 2011-09-13 08:27:27 +07:00
parent 719df0ec79
commit c360f2db47
3 changed files with 76 additions and 62 deletions

View File

@ -42,7 +42,7 @@ else
endif endif
if !exists('g:ctrlp_ignore_space') if !exists('g:ctrlp_ignore_space')
let s:igspace = 1 let s:igspace = 0
else else
let s:igspace = g:ctrlp_ignore_space let s:igspace = g:ctrlp_ignore_space
unl g:ctrlp_ignore_space unl g:ctrlp_ignore_space
@ -228,9 +228,10 @@ func! s:ListAllBuffers() "{{{
endfunc "}}} endfunc "}}}
func! s:SplitPattern(str,...) "{{{ func! s:SplitPattern(str,...) "{{{
let str = a:str
" ignore spaces " ignore spaces
if s:igspace if s:igspace
let str = substitute(a:str, ' ', '', 'g') let str = substitute(str, ' ', '', 'g')
endif endif
" clear the jumptoline var " clear the jumptoline var
if exists('s:jmpln') | unl s:jmpln | endif if exists('s:jmpln') | unl s:jmpln | endif
@ -241,15 +242,19 @@ func! s:SplitPattern(str,...) "{{{
" remove the line number " remove the line number
let str = substitute(str, ':\d*$', '', 'g') let str = substitute(str, ':\d*$', '', 'g')
endif endif
if s:regexp || match(str, '[*^$+|]') >= 0
\ || match(str, '\\\(zs\|ze\|<\|>\)') >= 0
let str = substitute(str, '\\\\', '\', 'g') let str = substitute(str, '\\\\', '\', 'g')
if s:regexp || match(str, '[*|]') >= 0
\ || match(str, '\\\(zs\|ze\|<\|>\)') >= 0
let array = [str] let array = [str]
else else
let array = split(str, '\zs') let array = split(str, '\zs')
if exists('+ssl') && !&ssl if exists('+ssl') && !&ssl
cal map(array, 'substitute(v:val, "\\", "\\\\\\\\", "g")') cal map(array, 'substitute(v:val, "\\", "\\\\\\", "g")')
endif endif
" literal ^ and $
for each in ['^', '$']
cal map(array, 'substitute(v:val, "\\\'.each.'", "\\\\\\'.each.'", "g")')
endfor
endif endif
" Build the new pattern " Build the new pattern
let nitem = !empty(array) ? array[0] : '' let nitem = !empty(array) ? array[0] : ''
@ -280,6 +285,7 @@ func! s:GetMatchedItems(items, pats, limit) "{{{
if exists('newitems') && len(newitems) < limit if exists('newitems') && len(newitems) < limit
let items = deepcopy(newitems) let items = deepcopy(newitems)
endif endif
if !s:regexp | let each = escape(each, '.') | endif
if empty(items) " end here if empty(items) " end here
retu exists('newitems') ? newitems : [] retu exists('newitems') ? newitems : []
else " start here, goes back up if has 2 or more in pats else " start here, goes back up if has 2 or more in pats
@ -408,7 +414,7 @@ func! s:Renderer(lines, pat) "{{{
" don't sort " don't sort
if index([2], s:itemtype) < 0 if index([2], s:itemtype) < 0
let s:compat = a:pat let s:compat = a:pat
cal sort(nls, 's:comatlen') cal sort(nls, 's:mixedsort')
unl s:compat unl s:compat
endif endif
if s:mwreverse if s:mwreverse
@ -436,8 +442,8 @@ func! s:UpdateMatches(pat) "{{{
" Delete the buffer's content " Delete the buffer's content
sil! %d _ sil! %d _
let pats = s:SplitPattern(a:pat) let pats = s:SplitPattern(a:pat)
let pat = pats[-1]
let lines = s:GetMatchedItems(s:lines, pats, s:mxheight) let lines = s:GetMatchedItems(s:lines, pats, s:mxheight)
let pat = pats[-1]
cal s:Renderer(lines, pat) cal s:Renderer(lines, pat)
" highlighting " highlighting
if type(s:mathi) == 3 && len(s:mathi) == 2 && s:mathi[0] && exists('*clearmatches') if type(s:mathi) == 3 && len(s:mathi) == 2 && s:mathi[0] && exists('*clearmatches')
@ -456,7 +462,8 @@ func! s:BuildPrompt(...) "{{{
cal map(prt, 'escape(v:val, estr)') cal map(prt, 'escape(v:val, estr)')
let str = prt[0] . prt[1] . prt[2] let str = prt[0] . prt[1] . prt[2]
if s:nomatches if s:nomatches
cal s:UpdateMatches(str) " note: add sil! back after testing
sil! cal s:UpdateMatches(str)
endif endif
cal s:statusline() cal s:statusline()
" Toggling " Toggling
@ -769,6 +776,7 @@ func! s:AcceptSelection(mode,...) "{{{
let str = prt[0] . prt[1] . prt[2] let str = prt[0] . prt[1] . prt[2]
if str == '..' if str == '..'
cal s:parentdir(getcwd()) cal s:parentdir(getcwd())
cal s:SetLines(s:itemtype)
cal s:PrtClear() cal s:PrtClear()
retu retu
endif endif
@ -799,9 +807,8 @@ func! s:AcceptSelection(mode,...) "{{{
let bufnum = bufnr(filpath) let bufnum = bufnr(filpath)
let bufwinnr = bufwinnr(bufnum) let bufwinnr = bufwinnr(bufnum)
" check if the buffer's already opened in a tab " check if the buffer's already opened in a tab
let nr = 1 for nr in range(1, tabpagenr('$'))
while nr <= tabpagenr('$') " get a list of the buffers in the nr tab
" get list of buffers in the nr tab
let buflist = tabpagebuflist(nr) let buflist = tabpagebuflist(nr)
" if it has the buffer we're looking for " if it has the buffer we're looking for
if match(buflist, bufnum) >= 0 if match(buflist, bufnum) >= 0
@ -809,16 +816,13 @@ func! s:AcceptSelection(mode,...) "{{{
" get the number of windows " get the number of windows
let tabwinnrs = tabpagewinnr(nr, '$') let tabwinnrs = tabpagewinnr(nr, '$')
" find the buffer that we know is in this tab " find the buffer that we know is in this tab
let ewin = 1 for ewin in range(1, tabwinnrs)
while ewin <= tabwinnrs
if buflist[ewin - 1] == bufnum if buflist[ewin - 1] == bufnum
let buftabwinnr = ewin let buftabwinnr = ewin
endif endif
let ewin += 1 endfor
endwhile
endif endif
let nr += 1 endfor
endwhile
" switch to the buffer or open the file " switch to the buffer or open the file
if bufnum > 0 if bufnum > 0
if exists('buftabwinnr') if exists('buftabwinnr')
@ -841,23 +845,22 @@ func! s:AcceptSelection(mode,...) "{{{
endfunc "}}} endfunc "}}}
" * Helper functions {{{ " * Helper functions {{{
" comparing and sorting {{{
func! s:compare(s1, s2) func! s:compare(s1, s2)
" by length " by length
let str1 = strlen(a:s1) let len1 = strlen(a:s1)
let str2 = strlen(a:s2) let len2 = strlen(a:s2)
retu str1 == str2 ? 0 : str1 > str2 ? 1 : -1 retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1
endfunc endfunc
func! s:comatlen(s1, s2) func! s:compmatlen(s1, s2)
" by match length " by match length
let str1 = min(s:smatstr(a:s1, s:compat)) let mln1 = min(s:matchlens(a:s1, s:compat))
let str2 = min(s:smatstr(a:s2, s:compat)) let mln2 = min(s:matchlens(a:s2, s:compat))
retu str1 == str2 ? 0 : str1 > str2 ? 1 : -1 retu mln1 == mln2 ? 0 : mln1 > mln2 ? 1 : -1
endfunc endfunc
" find shortest match in a string func! s:matchlens(str, pat, ...)
" return a list with lengths of the matches
func! s:smatstr(str, pat, ...)
if empty(a:pat) || a:pat == '$' || a:pat == '^' if empty(a:pat) || a:pat == '$' || a:pat == '^'
retu [] retu []
endif endif
@ -865,28 +868,21 @@ func! s:smatstr(str, pat, ...)
let lens = exists('a:2') ? a:2 : [] let lens = exists('a:2') ? a:2 : []
if match(a:str, a:pat, st) != -1 if match(a:str, a:pat, st) != -1
let start = match(a:str, a:pat, st) let start = match(a:str, a:pat, st)
let len = len(matchstr(a:str, a:pat, st)) let str = matchstr(a:str, a:pat, st)
let len = len(str)
let end = matchend(a:str, a:pat, st) let end = matchend(a:str, a:pat, st)
let lens = add(lens, len) let lens = add(lens, len)
let lens = s:smatstr(a:str, a:pat, end, lens) let lens = s:matchlens(a:str, a:pat, end, lens)
endif endif
retu lens retu lens
endfunc endfunc
func! s:walker(max, pos, dir, ...) func! s:mixedsort(s1, s2)
if a:dir == 1 retu 2 * s:compmatlen(a:s1, a:s2) + s:compare(a:s1, a:s2)
let pos = a:pos < a:max ? a:pos + 1 : 0
elseif a:dir == -1
let pos = a:pos > 0 ? a:pos - 1 : a:max
endif
if !g:ctrlp_mru_files && pos == 2
\ && !exists('a:1')
let jmp = pos == a:max ? 0 : 3
let pos = a:pos == 1 ? jmp : 1
endif
retu pos
endfunc endfunc
"}}}
" dealing with statusline {{{
func! s:statusline(...) func! s:statusline(...)
let itemtypes = { let itemtypes = {
\ 0: ['files', 'fil'], \ 0: ['files', 'fil'],
@ -910,15 +906,13 @@ func! s:statusline(...)
exe 'setl stl='.focus.byfname.regex.slider exe 'setl stl='.focus.byfname.regex.slider
endfunc endfunc
func! s:matchsubstr(item, pat)
retu match(split(a:item, '[\/]\ze[^\/]\+$')[-1], a:pat)
endfunc
func! s:progress(len) func! s:progress(len)
exe 'setl stl=%#Function#\ '.a:len.'\ %*\ ' exe 'setl stl=%#Function#\ '.a:len.'\ %*\ '
redr redr
endfunc endfunc
"}}}
" working with paths {{{
func! s:dirfilter(val) func! s:dirfilter(val)
if isdirectory(a:val) && match(a:val, '[\/]\.\{,2}$') < 0 if isdirectory(a:val) && match(a:val, '[\/]\.\{,2}$') < 0
retu 1 retu 1
@ -931,9 +925,10 @@ func! s:parentdir(curr)
if parent != a:curr if parent != a:curr
exe 'chdir' parent exe 'chdir' parent
endif endif
cal s:SetLines(s:itemtype)
endfunc endfunc
"}}}
" syntax and coloring {{{
func! s:syntax() func! s:syntax()
syn match CtrlPNoEntries '^ == NO MATCHES ==$' syn match CtrlPNoEntries '^ == NO MATCHES ==$'
syn match CtrlPLineMarker '^>' syn match CtrlPLineMarker '^>'
@ -945,12 +940,10 @@ func! s:highlight(pat, grp)
cal clearmatches() cal clearmatches()
if !empty(a:pat) && a:pat != '..' if !empty(a:pat) && a:pat != '..'
let pat = substitute(a:pat, '\~', '\\~', 'g') let pat = substitute(a:pat, '\~', '\\~', 'g')
if !s:regexp if !s:regexp | let pat = escape(pat, '.') | endif
let pat = escape(pat, '.')
endif
" match only filename " match only filename
if s:byfname if s:byfname
let pat = substitute(pat, '\.\\{-}', '[^\\/]\\{-}', 'g') let pat = substitute(pat, '\[\^\(.\{-}\)\]\\{-}', '[^\\/\1]\\{-}', 'g')
let pat = substitute(pat, '$', '\\ze[^\\/]*$', 'g') let pat = substitute(pat, '$', '\\ze[^\\/]*$', 'g')
endif endif
cal matchadd(a:grp, '\c'.pat) cal matchadd(a:grp, '\c'.pat)
@ -959,6 +952,27 @@ func! s:highlight(pat, grp)
endfunc endfunc
"}}} "}}}
" misc {{{
func! s:walker(max, pos, dir, ...)
if a:dir == 1
let pos = a:pos < a:max ? a:pos + 1 : 0
elseif a:dir == -1
let pos = a:pos > 0 ? a:pos - 1 : a:max
endif
if !g:ctrlp_mru_files && pos == 2
\ && !exists('a:1')
let jmp = pos == a:max ? 0 : 3
let pos = a:pos == 1 ? jmp : 1
endif
retu pos
endfunc
func! s:matchsubstr(item, pat)
retu match(split(a:item, '[\/]\ze[^\/]\+$')[-1], a:pat)
endfunc
"}}}
"}}}
" * Initialization {{{ " * Initialization {{{
func! s:SetLines(type) func! s:SetLines(type)
let s:itemtype = a:type let s:itemtype = a:type

View File

@ -78,8 +78,8 @@ Use this option to specify how the file is to be opened when pressing <cr>:
< <
*'g:ctrlp_ignore_space'* *'g:ctrlp_ignore_space'*
If you want the search to include whitespaces, change this to 0: > Set this to 1 to ignore whitespaces in filenames and directory names: >
let g:ctrlp_ignore_space = 1 let g:ctrlp_ignore_space = 0
< <
*'g:ctrlp_working_path_mode'* *'g:ctrlp_working_path_mode'*
@ -227,7 +227,7 @@ Examples: >
:CtrlP [starting-directory] :CtrlP [starting-directory]
Open the |CtrlP| prompt in find files mode. Open the |CtrlP| prompt in find files mode.
If no argument is given, the value of |g:ctrlp_working_path_mode| will be If no argument is given, the value of |g:ctrlp_working_path_mode| will be
used to determined the starting directory. used to determine the starting directory.
*:CtrlPBuffer* *:CtrlPBuffer*
:CtrlPBuffer :CtrlPBuffer
@ -271,8 +271,7 @@ The following commands ignore the value of |g:ctrlp_working_path_mode|:
Once inside the prompt: Once inside the prompt:
<c-r> *'ctrlp-fullregexp'* <c-r> *'ctrlp-fullregexp'*
Toggle between the smart |regexp|/string mode (section 5.b) and full Toggle between the string mode (section 5.a & b) and full |regexp| mode.
|regexp| mode.
(note: in full |regexp| mode, the prompts base is 'r>>' instead of '>>>') (note: in full |regexp| mode, the prompts base is 'r>>' instead of '>>>')
See also |input-formats| and |g:ctrlp_regexp_search|. See also |input-formats| and |g:ctrlp_regexp_search|.
@ -364,8 +363,8 @@ Formats for inputting in the prompt:
a) Simple string. e.g. 'abc' is understood internally as 'a.\{-}b.\{-}c' a) Simple string. e.g. 'abc' is understood internally as 'a.\{-}b.\{-}c'
b) Vim |regexp|. If the input string contains '*', '^', '$', '+' or '$', itll b) Vim |regexp|. If the input string contains '*' or '|', itll be treated as
be treated as a Vims |regexp| |pattern| without any modification. a Vims |regexp| |pattern| without any modification.
e.g. 'abc\d*efg' will be read as 'abc\d*efg'. e.g. 'abc\d*efg' will be read as 'abc\d*efg'.
See also |ctrlp-fullregexp| and |g:ctrlp_regexp_search|. See also |ctrlp-fullregexp| and |g:ctrlp_regexp_search|.
@ -397,8 +396,8 @@ Mercurial repository: https://bitbucket.org/kien/ctrlp.vim
=============================================================================== ===============================================================================
CHANGELOG CHANGELOG
*ctrlp-update-2* Before 2011/09/12
Update #2~
+ Ability to cycle through matched lines in the match window. + Ability to cycle through matched lines in the match window.
+ Extended the behavior of |g:ctrlp_persistent_input| + Extended the behavior of |g:ctrlp_persistent_input|
+ Extended the behavior of |:CtrlP| + Extended the behavior of |:CtrlP|
@ -412,8 +411,6 @@ Update #2~
|:CtrlPCurFile|, |:CtrlPCurFile|,
|:CtrlPRoot| |:CtrlPRoot|
*ctrlp-update-1*
Update #1~
+ New feature: search in most recently used (MRU) files + New feature: search in most recently used (MRU) files
+ New mapping: <c-b>. + New mapping: <c-b>.
+ Extended the behavior of <c-f>. + Extended the behavior of <c-f>.
@ -423,5 +420,8 @@ Update #1~
|g:ctrlp_mruf_include| |g:ctrlp_mruf_include|
+ New command: |:CtrlPMRUFiles| + New command: |:CtrlPMRUFiles|
The updates are shown in reverse chronological order, from newest (top) to
oldest (bottom).
=============================================================================== ===============================================================================
vim:nofen:et:ts=2:sw=2:sts=2 vim:nofen:et:ts=2:sw=2:sts=2

View File

@ -11,7 +11,7 @@ Full path fuzzy __file__, __buffer__ and __MRU__ file finder for Vim.
* Press `<c-p>` or run `:CtrlP` to invoke CtrlP. * Press `<c-p>` or run `:CtrlP` to invoke CtrlP.
* Press `<c-f>` and `<c-b>` while CtrlP is open to switch between find file, find buffer, and find MRU file modes. * Press `<c-f>` and `<c-b>` while CtrlP is open to switch between find file, find buffer, and find MRU file modes.
* Ever remember only a files name but not where it is? Press `<c-d>` while CtrlP is open to switch to filename only search. * Ever remember only a files name but not where it is? Press `<c-d>` while CtrlP is open to switch to filename only search.
* Use `*` `?` `^` `+` or `|` in the prompt to submit the string as a Vims regexp pattern. * Use `*` or `|` in the prompt to submit the string as a Vims regexp pattern.
* Or press `<c-r>` while CtrlP is open to switch to full regexp search mode. * Or press `<c-r>` while CtrlP is open to switch to full regexp search mode.
* End the input string with a colon `:` followed with a number to jump to that line in the selected file. * End the input string with a colon `:` followed with a number to jump to that line in the selected file.
e.g. `abc:45` to open the file matched the pattern and jump to line 45. e.g. `abc:45` to open the file matched the pattern and jump to line 45.