add initial qnamebuf scripts from http://www.vim.org/scripts/script.php?script_id=3217
This commit is contained in:
parent
3326c15cee
commit
a848fd42e6
138
doc/qnamebuf.txt
Normal file
138
doc/qnamebuf.txt
Normal file
@ -0,0 +1,138 @@
|
||||
*qnamebuf.txt* QuickNameBuf: A quick buffer manager
|
||||
|
||||
Author: Matt Spear <batman900 at gmail DOT com>
|
||||
QuickNameBuf version 0.06
|
||||
|
||||
==============================================================================
|
||||
1. Overview~
|
||||
*qnamebuf-overview*
|
||||
|
||||
I really like qname (vimscript #2317) and qbuf (vimscript #1910) and
|
||||
decided that it would be nice to combine them. The author recommended I
|
||||
upload under my name.
|
||||
|
||||
==============================================================================
|
||||
2. Installation ~
|
||||
*qnamebuf-installation*
|
||||
|
||||
Extract the downloaded file in your personal |vimfiles| directory (~/.vim
|
||||
under Unix or %HOMEPATH%\vimfiles under Windows). Restart Vim and execute:
|
||||
>
|
||||
helptags ~/.vim/doc
|
||||
<
|
||||
==============================================================================
|
||||
2. Usage ~
|
||||
*qnamebuf-usage*
|
||||
|
||||
<F4> opens a list of the current buffers, and typing a string filters
|
||||
the list (by default ala lustyexplorer vimscript #1890). All filtering
|
||||
is case insensitive (even if using Regular Expressions). If there
|
||||
are many files open goes to a simplified view (just relative buffer
|
||||
number, and the filename with path), when filtered enough shows more
|
||||
information:
|
||||
1) Relative Buffer Number
|
||||
2) Current Buffer (%), Alternative Buffer (#), or if it is open in a visible split (=)
|
||||
3) File name
|
||||
4) Buffer number
|
||||
5) Relative file path
|
||||
|
||||
|
||||
Beyond the keybindinfs of |qnamepicker.txt| qnamefile provides:
|
||||
<M-L> Toggle between listed and unlisted buffers
|
||||
<M-D> Delete the selected buffer, the explorer stays open and
|
||||
retains cursor position
|
||||
<M-C> Close the window containing the buffer
|
||||
<ESC> or <F4> or <C-G> Close the buffer explorer
|
||||
<M-S> Open the selected file in a split window
|
||||
<M-V> Open the selected file in a vert split window
|
||||
<M-T> Open the selected file in a new tab
|
||||
|
||||
==============================================================================
|
||||
3. Customization ~
|
||||
*qnamebuf-customization*
|
||||
|
||||
|g:qnamebuf_hotkey| Set the default key to toggle qnamebuf (defaults to <F4>).
|
||||
|
||||
>
|
||||
nmap <KEY> :call QNameBufInit(REGEXP, [SIZE], [FILE_NAME_ONLY], [ALLOW_LEADER])<cr>:~
|
||||
<
|
||||
If REGEXP is true use regular expressions instead of the lusty filter.
|
||||
SIZE controls the size of the popup. Defaults to 1/2 of the visible lines
|
||||
(|&lines|/2).
|
||||
If FILE_NAME_ONLY is false then use the path and filename otherwise just use
|
||||
the filename. Defaults to true.
|
||||
If ALLOW_LEADER is true then <LEADER>X can be used instead of <M-X> in the
|
||||
list above. Defaults to false.
|
||||
|
||||
|g:qnamebuf_unlisted| If set will start in unlisted mode instead of the
|
||||
default (listed mode).
|
||||
|
||||
==============================================================================
|
||||
4. Hints ~
|
||||
*qnamebuf-hints*
|
||||
|
||||
I find the following mappings very useful (jump to the ith file):
|
||||
nmap <silent> <M-1> :brewind<CR>
|
||||
nmap <silent> <M-2> :brewind \| 1bn<CR>
|
||||
nmap <silent> <M-3> :brewind \| 2bn<CR>
|
||||
nmap <silent> <M-4> :brewind \| 3bn<CR>
|
||||
nmap <silent> <M-5> :brewind \| 4bn<CR>
|
||||
nmap <silent> <M-6> :brewind \| 5bn<CR>
|
||||
nmap <silent> <M-7> :brewind \| 6bn<CR>
|
||||
nmap <silent> <M-8> :brewind \| 7bn<CR>
|
||||
nmap <silent> <M-9> :brewind \| 8bn<CR>
|
||||
nmap <silent> <M-0> :brewind \| 9bn<CR>
|
||||
|
||||
When starting qnamebuf the relative numbers are displayed and this allows
|
||||
consistent access.
|
||||
|
||||
==============================================================================
|
||||
6. History~
|
||||
*qnamebuf-history*
|
||||
Version 0.07
|
||||
- Refactored to have a generic core and many wrappers
|
||||
- Increased speed by changing from a custom function for matching to a
|
||||
regular expression (achieves the same result, but is significantly
|
||||
faster)
|
||||
Version 0.06
|
||||
- Fixed a bug when switching between listed and unlisted
|
||||
Version 0.05
|
||||
- Fixed a bug which would cause operations to fail when filtered
|
||||
Version 0.04
|
||||
- Save and restore register |@y| instead of overwriting it
|
||||
- Made the |cmap|s <silent>
|
||||
Version 0.03
|
||||
- Mistake in always defining the <F4> mapping even if a map to QNameInit exists
|
||||
Version 0.02
|
||||
- Added support for <Leader>X as a synonym for <M-X> for |guioptions|+=m users
|
||||
- Some minor code cleanup
|
||||
Version 0.01
|
||||
- Initial release
|
||||
|
||||
==============================================================================
|
||||
7. Thanks~
|
||||
*qnamebuf-thanks*
|
||||
|
||||
- Vim Devs for vim
|
||||
- Stefano for finding that <M-X> doesn't work with the menu shown and an
|
||||
initial documentation
|
||||
- Peter for a patch for fixing |@y| being overwritten and pointing out the cmap
|
||||
noisiness
|
||||
- pal nart For the amazing qname and qbuf which were the inspiration and basis
|
||||
for this
|
||||
|
||||
==============================================================================
|
||||
8. Contact ~
|
||||
*qnamebuf-contact*
|
||||
|
||||
If you have questions, bug reports, suggestions, etc. the author can be
|
||||
contacted at batman900 AT gmail DOT com. The latest version is available at
|
||||
http://www.vim.org/scripts/script.php?script_id=3217. If you like the script
|
||||
please vote for it on www.vim.org.
|
||||
|
||||
==============================================================================
|
||||
License ~
|
||||
|
||||
This software is licensed under the MIT license.
|
||||
|
||||
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
|
98
doc/qnamefile.txt
Normal file
98
doc/qnamefile.txt
Normal file
@ -0,0 +1,98 @@
|
||||
*qnamefile.txt* QuickNameBuf: A quick buffer manager
|
||||
|
||||
Author: Matt Spear <batman900 at gmail DOT com>
|
||||
QNameFile version 0.07
|
||||
|
||||
==============================================================================
|
||||
1. Overview~
|
||||
*qnamefile-overview*
|
||||
|
||||
After using qnamebuf for a while I noticed I wanted to be able to choose a
|
||||
file in a similar manner (by typing a non-). After a refactoring of the
|
||||
qnamebuf code into a core module |qnamepicker| and modules, this became
|
||||
possible.
|
||||
|
||||
==============================================================================
|
||||
2. Installation ~
|
||||
*qnamefile-installation*
|
||||
|
||||
Extract the downloaded file in your personal |vimfiles| directory (~/.vim
|
||||
under Unix or %HOMEPATH%\vimfiles under Windows). Restart Vim and execute:
|
||||
>
|
||||
helptags ~/.vim/doc
|
||||
<
|
||||
|
||||
Requires that there be a find utility available in the path. This should be
|
||||
available on unix, on Windows GnuWin32 should be sufficient:
|
||||
http://gnuwin32.sourceforge.net/packages/findutils.htm
|
||||
|
||||
==============================================================================
|
||||
2. Usage ~
|
||||
*qnamefile-usage*
|
||||
|
||||
<S-F4> opens a listing of the files recursively from the current directory.
|
||||
By default the only files that are not shown are those that are hidden, or are
|
||||
in a hidden directory (e.g. .vimrc and anything in .vim/). Typing a string
|
||||
filters the list (by default using an algorithm like lustyexplorer vimscript
|
||||
#1890). All filtering is case insensitive.
|
||||
|
||||
Beyond the keybindinfs of |qnamepicker.txt| qnamefile provides:
|
||||
<M-V> Opens the selected file in a vertical split
|
||||
<M-S> Opens the selected file in a split
|
||||
<M-T> Opens the selected file in a new tab
|
||||
<C-G> Cancels
|
||||
<S-F4> Cancels
|
||||
|
||||
==============================================================================
|
||||
3. Customization ~
|
||||
*qnamefile-customization*
|
||||
|
||||
|g:qnamefile_hotkey| Set the default key to toggle qnamefile (defaults to <S-F4>).
|
||||
|
||||
One can create a mapping using something like:
|
||||
>
|
||||
nmap <unique> <KEY> :call QNameFileInit(PATH, EXTENSIONS,
|
||||
INCLUDE_HIDDEN)<cr>:~
|
||||
<
|
||||
PATH specifies the path to start from, if it is |''| then it will default to
|
||||
the current working directory (see |:pwd|).
|
||||
EXTENSIONS is a space separated list of extensions to filter on (e.g. "h cpp
|
||||
cc cxx c"), if it is |''| then there will be no filtering.
|
||||
INCLUDE_HIDDEN if true will recurse into hidden directories, and show hidden
|
||||
files (i.e. files starting with .).
|
||||
|
||||
|g:qnamefile_height| Controls the initial height of the window.
|
||||
|
||||
|g:qnamefile_leader| If true then will allow <LEADER><KEY> instead of <M-KEY>
|
||||
in the mappings.
|
||||
|
||||
|g:qnamefile_regexp| If true will use regular expressions instead of a lusty
|
||||
style selector.
|
||||
|
||||
==============================================================================
|
||||
6. History~
|
||||
*qnamefile-history*
|
||||
Version 0.07
|
||||
- Initial release
|
||||
|
||||
==============================================================================
|
||||
7. Thanks~
|
||||
*qnamefile-thanks*
|
||||
|
||||
- Vim Devs for vim
|
||||
|
||||
==============================================================================
|
||||
8. Contact ~
|
||||
*qnamefile-contact*
|
||||
|
||||
If you have questions, bug reports, suggestions, etc. the author can be
|
||||
contacted at batman900 AT gmail DOT com. The latest version is available at
|
||||
http://www.vim.org/scripts/script.php?script_id=3217. If you like the script
|
||||
please vote for it on www.vim.org.
|
||||
|
||||
==============================================================================
|
||||
License ~
|
||||
|
||||
This software is licensed under the MIT license.
|
||||
|
||||
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
|
210
doc/qnamepicker.txt
Normal file
210
doc/qnamepicker.txt
Normal file
@ -0,0 +1,210 @@
|
||||
*qnamepicker.txt* QuickNamePicker: A quick list selector library
|
||||
|
||||
Author: Matt Spear <batman900 at gmail DOT com>
|
||||
QNamePicker version 0.07
|
||||
|
||||
==============================================================================
|
||||
1. Overview~
|
||||
*qnamepicker-overview*
|
||||
|
||||
After using qnamebuf for a while I realized it would be useful to have a
|
||||
generic selector interface and to allow modules to build off this. In this
|
||||
manner qnamebuf becomes an extension (and I introduced qnamefile). The big
|
||||
driver for this was the Project plugin (vimscript #69) which I felt very much
|
||||
needed a lusty picker for the file to open.
|
||||
|
||||
==============================================================================
|
||||
2. Installation ~
|
||||
*qnamepicker-installation*
|
||||
|
||||
Extract the downloaded file in your personal |vimfiles| directory (~/.vim
|
||||
under Unix or %HOMEPATH%\vimfiles under Windows). Restart Vim and execute:
|
||||
>
|
||||
helptags ~/.vim/doc
|
||||
<
|
||||
==============================================================================
|
||||
2. Usage ~
|
||||
*qnamepicker-usage*
|
||||
|
||||
This exposes one function for the user:
|
||||
>
|
||||
QNamePickerStart(list, dict)
|
||||
<
|
||||
|a:list| is the |List| of items to have the user choose from.
|
||||
|a:dict| has the optional keys:
|
||||
|acceptors| The set of additional keys to accept on.
|
||||
By default has [<Enter>, <M-1>, ..., <M-0>].
|
||||
e.g. "acceptors": ["\<M-D>", "\<C-T>", "\<M-L>"].
|
||||
|cancelors| The set of keys to close the qnamepicker.
|
||||
By default has <Esc>.
|
||||
e.g. "cancelors": ["\<C-G>", "\<C-C>"]
|
||||
|modifiers| The set of keys to call the modifier_func when pressed.
|
||||
By default is empty.
|
||||
e.g. "modifiers": ["\<M-L>"]
|
||||
|modifier_func| The callback function to modify the list that is
|
||||
displayed. The callback is expected to return the new list to
|
||||
display. Called as:
|
||||
modifier_func(|index|, |modifier_key|)
|
||||
where
|
||||
|a:index| is the index in |a:list| that is selected, if there is
|
||||
no selected item then it will be -1 (this will happen if there are
|
||||
no items in the filtered list).
|
||||
|modifier_key| is the key that was pressed.
|
||||
|render_func| The function to call to render each item. The callback is
|
||||
expected to return a string that represents what to show for each item
|
||||
in the filtered |a:list|. Called as:
|
||||
render_func(|index|, |rel_index|, |length|, |in_column_mode|)
|
||||
where
|
||||
|a:index| is the index in |a:list| of the item to render.
|
||||
|a:rel_index| is the relative index in the filtered list (so that
|
||||
one can show the shortcut counts for the <M-1>... keys).
|
||||
|a:length| is the number of items in the filtered list (so that
|
||||
one can show more information if there are few enough items).
|
||||
|a:in_column_mode| is true if there are more items than the size
|
||||
of the window.
|
||||
|complete_func| The function to call when an item is selected by one of
|
||||
the |acceptors|. Called as:
|
||||
complete_func(|index|, |acceptor_key|)
|
||||
where
|
||||
|a:index| is the index in |a:index| of the selected item.
|
||||
|a:acceptor_key| is the acceptor key that was pressed.
|
||||
|regexp| If true then treats the user input as a regular expression. If
|
||||
false or not present, then will use a lusty-style selector.
|
||||
|height| The height of the window. If set to 0 or not present, will
|
||||
default to one-half of |&lines|.
|
||||
|use_leader| If true then any word characters ([a-zA-Z0-9]) in acceptors
|
||||
or cancelors or modifiers will be accessable via <Leader><CHAR>. When
|
||||
false then any word characters are treated as user input (including
|
||||
<Leader>).
|
||||
|
||||
The default controls are:
|
||||
<BS> Delete last char entered
|
||||
<C-U> Delete all entered chars
|
||||
<ESC> Close the explorer
|
||||
<CR> Choose the currently selected file
|
||||
<UP> <DOWN> <LEFT> <RIGHT> Navigate the selection
|
||||
<HOME> <END> Move to the first/last item
|
||||
<M-1>, ..., <M-0> Open the first, ..., tenth file in the list
|
||||
|
||||
Note, I wanted these to be <C-...> but <C-1>...<C-0> are not real key sequences.
|
||||
|
||||
Once a function has been written to use |QNamePickerInit| (say |MyQNameWrapper|), then one should add
|
||||
a mapping to call the wrapper via:
|
||||
>
|
||||
nmap <unique> <KEY> :call MyQNameWrapper()<cr>:~
|
||||
<
|
||||
|
||||
==============================================================================
|
||||
3. Customization ~
|
||||
*qnamepicker-customization*
|
||||
Every other line can be colored by highlighting |QNamePickerAlt|, e.g.
|
||||
>
|
||||
hi QNamePickerAlt gui=NONE guibg=#222222
|
||||
<
|
||||
|
||||
==============================================================================
|
||||
4. Example ~
|
||||
*qnamepicker-example*
|
||||
Included in this are two fairly comprehensive examples:
|
||||
|qnamebuf| which shows how I used this core to interact with the set of
|
||||
vim buffers. This is very comprehensive and uses pretty much every
|
||||
feature of |qnamepicker|.
|
||||
|qnamefile| which shows the recursive set of files from a given path, and
|
||||
restricting to a set of extensions. This is a much simpler example,
|
||||
only requiring a |complete_func| and custom |acceptors|/|cancelors| list.
|
||||
|
||||
These (and the hint example below) should be sufficient to make use of the
|
||||
plugin.
|
||||
|
||||
==============================================================================
|
||||
5. Hints ~
|
||||
*qnamepicker-hints*
|
||||
|
||||
To plug this into the Project (vimscript #69) plugin one would add something
|
||||
like:
|
||||
>
|
||||
function! LustyProjectFilePicker()
|
||||
let s:sid = substitute(maparg('<Return>', 'n'), '.*\(<SNR>.\{-}\)_.*', '\1', '')
|
||||
" As there may not have been a file opened in the project, if a CD is
|
||||
" specified, then we should cd to it before showing the list so that
|
||||
" the :. works as expected...all of this is to get to that
|
||||
let cd_cmd = b:proj_cd_cmd
|
||||
let infoline = {s:sid}_RecursivelyConstructDirectives(line('.'))
|
||||
let home = {s:sid}_GetHome(infoline, '') . '/'
|
||||
let c_d = {s:sid}_GetCd(infoline, home)
|
||||
let abs = {s:sid}_IsAbsolutePath(home)
|
||||
if c_d != '' && abs != 2
|
||||
if match(g:proj_flags, '\CL') != -1
|
||||
call {s:sid}_SetupAutoCommand(c_d)
|
||||
endif
|
||||
if !isdirectory(glob(c_d))
|
||||
call confirm("From this fold's entry,\nCD=".'"'.c_d.'" is not a valid directory.', "&OK", 1)
|
||||
else
|
||||
silent exec cd_cmd.' '.c_d
|
||||
endif
|
||||
endif
|
||||
let ofnames=split(Project_GetAllFnames(1, line("."), ",,"), ',,')
|
||||
let g:cmd_arr = map(ofnames, "fnamemodify(v:val, ':.')")
|
||||
call QNamePickerStart(g:cmd_arr, {
|
||||
\ "complete_func": function("LustyProjectFileCompletion"),
|
||||
\ "acceptors": ["v", "s", "t", "\<M-V>", "\<M-S>", "\<M-T>"],
|
||||
\ "use_leader": 1,
|
||||
\})
|
||||
endfunction
|
||||
|
||||
function! LustyProjectFileCompletion(index, key)
|
||||
let infoline = {s:sid}_RecursivelyConstructDirectives(line('.'))
|
||||
if a:key == "\<M-V>" || a:key == "v"
|
||||
call {s:sid}_OpenEntry2(line('.'), infoline, fnamemodify(g:cmd_arr[a:index], ':p'), 'vert sp')
|
||||
elseif a:key == "\<M-S>" || a:key == "s"
|
||||
call {s:sid}_OpenEntry2(line('.'), infoline, fnamemodify(g:cmd_arr[a:index], ':p'), 'sp')
|
||||
elseif a:key == "\<M-T>" || a:key == "t"
|
||||
call {s:sid}_OpenEntry2(line('.'), infoline, fnamemodify(g:cmd_arr[a:index], ':p'), 'tabe')
|
||||
else
|
||||
call {s:sid}_OpenEntry2(line('.'), infoline, fnamemodify(g:cmd_arr[a:index], ':p'), 'e')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
nmap <buffer> <unique> <LocalLeader>a :call LustyProjectFilePicker()<cr>:~
|
||||
<
|
||||
to the .vimproject_mappings file.
|
||||
|
||||
With this <M-V> will open the selected file in a vert split window, <M-S> will
|
||||
open it in a split window, <M-T> will open it in a new tab, and <CR> will open
|
||||
it in the last accessed window (this is accomplished by cheating and calling
|
||||
the |QNameFileCompletion| which is publically exposed from the |qnamefile|
|
||||
plugin).
|
||||
|
||||
==============================================================================
|
||||
7. History~
|
||||
*qnamepicker-history*
|
||||
Version 0.07
|
||||
- Initial release
|
||||
|
||||
==============================================================================
|
||||
8. Thanks~
|
||||
*qnamepicker-thanks*
|
||||
|
||||
- Vim Devs for vim
|
||||
- Stefano for finding that <M-X> doesn't work with the menu shown and an
|
||||
initial documentation
|
||||
- Peter for a patch for fixing |@y| being overwritten and pointing out the cmap
|
||||
noisiness
|
||||
- pal nart For the amazing qname and qbuf which were the inspiration and basis
|
||||
for this
|
||||
|
||||
==============================================================================
|
||||
9. Contact ~
|
||||
*qnamepicker-contact*
|
||||
|
||||
If you have questions, bug reports, suggestions, etc. the author can be
|
||||
contacted at batman900 AT gmail DOT com. The latest version is available at
|
||||
http://www.vim.org/scripts/script.php?script_id=3217. If you like the script
|
||||
please vote for it on www.vim.org.
|
||||
|
||||
==============================================================================
|
||||
License ~
|
||||
|
||||
This software is licensed under the MIT license.
|
||||
|
||||
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
|
143
plugin/qnamebuf.vim
Normal file
143
plugin/qnamebuf.vim
Normal file
@ -0,0 +1,143 @@
|
||||
"=============================================================================
|
||||
" File: qnamebuf.vim
|
||||
" Author: batman900 <batman900+vim@gmail.com>
|
||||
" Last Change: 5/12/2011
|
||||
" Version: 0.07
|
||||
|
||||
if v:version < 700
|
||||
finish
|
||||
endif
|
||||
|
||||
if exists("g:qnamebuf_loaded") && g:qnamebuf_loaded
|
||||
finish
|
||||
endif
|
||||
let g:qnamebuf_loaded = 1
|
||||
|
||||
if !exists("g:qnamebuf_hotkey") || g:qnamebuf_hotkey == ""
|
||||
let g:qnamebuf_hotkey = "<F4>"
|
||||
endif
|
||||
|
||||
if !hasmapto('QNameBufInit')
|
||||
exe "nmap <unique>" g:qnamebuf_hotkey ":call QNameBufInit(0, 0, 1, 0)<cr>:~"
|
||||
endif
|
||||
let s:qnamebuf_hotkey = eval('"\'.g:qnamebuf_hotkey.'"')
|
||||
let s:modified_string = '[+]'
|
||||
|
||||
let g:qnamebuf_unlisted = 0
|
||||
|
||||
function! QNameBufInit(regexp, ...)
|
||||
let s:fileName = (a:0 > 1) ? a:2 : 1
|
||||
let s:unlisted = g:qnamebuf_unlisted
|
||||
let name_arr = s:QNameBufParseLs()
|
||||
call QNamePickerStart(name_arr, {
|
||||
\ "render_func": function("QNameBufRender"),
|
||||
\ "complete_func": function("QNameBufCompletion"),
|
||||
\ "modifiers": ["l", "d", "c", "\<M-l>", "\<M-d>", "\<M-c>"],
|
||||
\ "modifier_func": function("QNameBufModifier"),
|
||||
\ "acceptors": ["v", "s", "t", "\<M-v>", "\<M-s>", "\<M-t>"],
|
||||
\ "cancelors": ["g", "\<C-g>", s:qnamebuf_hotkey],
|
||||
\ "regexp": a:regexp,
|
||||
\ "use_leader": (a:0 > 2) ? a:3 : 0,
|
||||
\ "height": (a:0 > 0) ? a:1 : 0,
|
||||
\})
|
||||
endfunction
|
||||
|
||||
function! QNameBufModifier(index, key)
|
||||
if a:key == "l" || a:key == "\<M-l>"
|
||||
let s:unlisted = 1 - s:unlisted
|
||||
elseif a:key == "d" || a:key == "\<M-d>" && a:index >= 0
|
||||
exe 'bd ' . g:cmd_arr[a:index]['bno']
|
||||
elseif a:key == "c" || a:key == "\<M-c>" && a:index >= 0
|
||||
call s:closewindow(g:cmd_arr[a:index]['bno'])
|
||||
endif
|
||||
return s:QNameBufParseLs()
|
||||
endfunction
|
||||
|
||||
function! QNameBufCompletion(index, key)
|
||||
if a:key == "v" || a:key == "\<M-v>"
|
||||
vert split
|
||||
elseif a:key == "s" || a:key == "\<M-s>"
|
||||
split
|
||||
elseif a:key == "t" || a:key == "\<M-t>"
|
||||
tab split
|
||||
endif
|
||||
call s:swb(g:cmd_arr[a:index]['bno'])
|
||||
unlet g:cmd_arr
|
||||
endfunction
|
||||
|
||||
function! QNameBufRender(index, count, len, columnar)
|
||||
let rel_len_len = len(a:len)
|
||||
let rel_len_fill = repeat(' ', rel_len_len - len(a:count) + 1)
|
||||
let item = g:cmd_arr[a:index]
|
||||
let name = item['name']
|
||||
if a:columnar
|
||||
return a:count . rel_len_fill . name
|
||||
else
|
||||
let name_fill = repeat(' ', s:len_longest_name - len(name) + 1)
|
||||
let modified_fill = repeat(' ', len(s:modified_string) - len(item['modified']))
|
||||
let type = len(item['type']) ? item['type'] : ' '
|
||||
return a:count . type . rel_len_fill . name . name_fill
|
||||
\ . ' ' . item['modified'] . modified_fill
|
||||
\ . ' <' . item['bno'] . '> ' . item['path']
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:QNameBufParseLs()
|
||||
let _y = @y
|
||||
redir @y | silent ls! | redir END
|
||||
let g:cmd_arr = []
|
||||
let name_arr = []
|
||||
let s:len_longest_name = 0
|
||||
let i = 1
|
||||
for _line in split(@y, "\n")
|
||||
if s:unlisted && _line[3] == "u" && (_line[6] != "-" || _line[5] != " ")
|
||||
\ || !s:unlisted && _line[3] != "u"
|
||||
let _bno = matchstr(_line, '^ *\zs\d*')+0
|
||||
let _fname = substitute(expand("#"._bno.":p"), '\', '/', 'g')
|
||||
if _fname == ""
|
||||
let _fname = "|".matchstr(_line, '"\[\zs[^\]]*')."|"
|
||||
endif
|
||||
let _moreinfo = ""
|
||||
if s:unlisted
|
||||
let _moreinfo = substitute(_line[5], "[ah]", s:modified_string, "")
|
||||
else
|
||||
let _moreinfo = substitute(_line[7], "+", s:modified_string, "")
|
||||
endif
|
||||
if _bno == bufnr('')
|
||||
let _type = '%'
|
||||
elseif bufwinnr(str2nr(_bno)) > 0
|
||||
let _type = '='
|
||||
elseif _bno == bufnr('#')
|
||||
let _type = '#'
|
||||
else
|
||||
let _type = ' '
|
||||
endif
|
||||
let _tname = fnamemodify(_fname,":t")
|
||||
let _path = fnamemodify(_fname,":~:.:h")
|
||||
let _name = s:fileName ? _tname : _path . '/' . _tname
|
||||
if len(_name) > s:len_longest_name
|
||||
let s:len_longest_name = len(_name)
|
||||
endif
|
||||
call add(name_arr, _name)
|
||||
call add(g:cmd_arr, {"bno": _bno, "type": _type, "modified": _moreinfo, "name": _name, "path": _path})
|
||||
let i = i + 1
|
||||
endif
|
||||
endfor
|
||||
let @y = _y
|
||||
return name_arr
|
||||
endfunction
|
||||
|
||||
function! s:closewindow(bno)
|
||||
if bufwinnr(a:bno) != -1
|
||||
exe bufwinnr(a:bno) . "winc w|close"
|
||||
endif
|
||||
endfunc
|
||||
|
||||
function! s:swb(bno)
|
||||
if bufwinnr(a:bno) == -1
|
||||
exe "hid b" a:bno
|
||||
else
|
||||
exe bufwinnr(a:bno) . "winc w"
|
||||
endif
|
||||
endfunc
|
||||
|
71
plugin/qnamefile.vim
Normal file
71
plugin/qnamefile.vim
Normal file
@ -0,0 +1,71 @@
|
||||
"=============================================================================
|
||||
" File: qnamefile.vim
|
||||
" Author: batman900 <batman900+vim@gmail.com>
|
||||
" Last Change: 5/12/2011
|
||||
" Version: 0.07
|
||||
|
||||
if v:version < 700
|
||||
finish
|
||||
endif
|
||||
|
||||
if exists("g:qnamefile_loaded") && g:qnamefile_loaded
|
||||
finish
|
||||
endif
|
||||
let g:qnamefile_loaded = 1
|
||||
|
||||
if !exists("g:qnamefile_hotkey") || g:qnamefile_hotkey == ""
|
||||
let g:qnamefile_hotkey = "<S-F4>"
|
||||
endif
|
||||
|
||||
if !hasmapto('QNameFileInit')
|
||||
exe "nmap <unique>" g:qnamefile_hotkey ":call QNameFileInit('', '', 0)<cr>:~"
|
||||
endif
|
||||
|
||||
let s:qnamefile_hotkey = eval('"\' . g:qnamefile_hotkey . '"')
|
||||
|
||||
let g:qnamefile_height = 0
|
||||
let g:qnamefile_leader = 0
|
||||
let g:qnamefile_regexp = 0
|
||||
|
||||
" Find all files from path of the given extension ignoring hidden files
|
||||
" a:path Where to start searching from
|
||||
" a:extensions A space separated list of extensions to filter on (e.g. "java cpp h")
|
||||
function! QNameFileInit(path, extensions, include_hidden)
|
||||
let path = a:path
|
||||
if !path
|
||||
let path = '.'
|
||||
endif
|
||||
let ext = ''
|
||||
if a:extensions
|
||||
let ext = join(split(a:extensions, ' '), '\|')
|
||||
let ext = '-and -regex ".*/.*\.\(' . ext . '\)"'
|
||||
endif
|
||||
let hidden = ''
|
||||
if !a:include_hidden
|
||||
let hidden = '-not -regex ".*/\..*"'
|
||||
endif
|
||||
let ofnames = sort(split(system('find ' . a:path . ' -type f ' . hidden . ' ' . ext . ' -print'), "\n"))
|
||||
let g:cmd_arr = map(ofnames, "fnamemodify(v:val, ':.')")
|
||||
call QNamePickerStart(g:cmd_arr, {
|
||||
\ "complete_func": function("QNameFileCompletion"),
|
||||
\ "acceptors": ["v", "s", "t", "\<M-v>", "\<M-s>", "\<M-t>"],
|
||||
\ "cancelors": ["g", "\<C-g>", s:qnamefile_hotkey],
|
||||
\ "regexp": g:qnamefile_regexp,
|
||||
\ "use_leader": g:qnamefile_leader,
|
||||
\ "height": g:qnamefile_height,
|
||||
\})
|
||||
endfunction
|
||||
|
||||
function! QNameFileCompletion(index, key)
|
||||
if a:key == "s" || a:key == "\<M-s>"
|
||||
let cmd = "sp"
|
||||
elseif a:key == "v" || a:key == "\<M-v>"
|
||||
let cmd = "vert sp"
|
||||
elseif a:key == "t" || a:key == "\<M-t>"
|
||||
let cmd = "tabe"
|
||||
else
|
||||
let cmd = "e"
|
||||
endif
|
||||
exe ':' . cmd . ' ' . g:cmd_arr[a:index]
|
||||
unlet g:cmd_arr
|
||||
endfunction
|
380
plugin/qnamepicker.vim
Normal file
380
plugin/qnamepicker.vim
Normal file
@ -0,0 +1,380 @@
|
||||
"=============================================================================
|
||||
" File: qnamepicker.vim
|
||||
" Author: batman900 <batman900+vim@gmail.com>
|
||||
" Last Change: 5/12/2011
|
||||
" Version: 0.07
|
||||
|
||||
if v:version < 700
|
||||
finish
|
||||
endif
|
||||
|
||||
if exists("g:qnamepicker_loaded") && g:qnamepicker_loaded
|
||||
finish
|
||||
endif
|
||||
let g:qnamepicker_loaded = 1
|
||||
|
||||
let s:colPrinter = {"trow": 20}
|
||||
let s:mapleader = exists('mapleader') ? mapleader : "\\"
|
||||
|
||||
" Start the list picker
|
||||
" a:list is the set of items to choose from
|
||||
" a:dict has keys
|
||||
" acceptors The set of additional keys to accept on
|
||||
" By default has <Enter>, <M-1>, ..., <M-0>
|
||||
" e.g. "acceptors": ["\<M-D>", "\<C-T>", "\<M-L>"]
|
||||
" cancelors The set of keys to cancel on
|
||||
" By default has <Esc>
|
||||
" e.g. "cancelors": ["\<C-G>", "\<C-C>"]
|
||||
" modifiers The set of keys to call the modifier_func
|
||||
" By default empty
|
||||
" e.g. "modifiers": ["\<M-L>"]
|
||||
" modifier_func The set of keys to modify the list
|
||||
" modifier_func(index, modifier_key)
|
||||
" Must return the NEW list to show
|
||||
" render_func The function to call to render each item
|
||||
" render_func(index, rel_index, length, in_column_mode)
|
||||
" complete_func The function to call when an item is selected
|
||||
" complete_func(index, acceptor_key)
|
||||
" regexp If should use regexp instead of a lusty style selector
|
||||
" height The height of the window
|
||||
" use_leader If should allow <mapleader>X to be used instead of <M-X>
|
||||
" By default false
|
||||
" If true then any word characters ([a-zA-Z0-9]) in acceptors or
|
||||
" cancelors or modifiers will be accessable via <Leader><CHAR>.
|
||||
" When false then any word characters are ignored.
|
||||
function! QNamePickerStart(list, dict)
|
||||
let s:cmdh = &cmdheight
|
||||
let s:inp = ""
|
||||
let s:colPrinter.trow = 0
|
||||
let s:colPrinter.sel = 0
|
||||
let s:inLeader = 0
|
||||
let s:useLeader = has_key(a:dict, "use_leader") ? a:dict["use_leader"] : 0
|
||||
let s:paste = &paste
|
||||
set nopaste
|
||||
"unlet s:modifier_func s:render_func s:complete_func
|
||||
let s:selectors = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\<M-1>", "\<M-2>", "\<M-3>", "\<M-4>", "\<M-5>", "\<M-6>", "\<M-7>", "\<M-8>", "\<M-9>", "\<M-0>"]
|
||||
let s:acceptors = ["\<CR>"]
|
||||
if has_key(a:dict, "acceptors")
|
||||
call extend(s:acceptors, a:dict["acceptors"])
|
||||
endif
|
||||
let s:cancelors = ["\<ESC>"]
|
||||
if has_key(a:dict, "cancelors")
|
||||
call extend(s:cancelors, a:dict["cancelors"])
|
||||
endif
|
||||
let s:modifiers = []
|
||||
let s:modifier_func = function("s:QNamePickerModIdentity")
|
||||
if has_key(a:dict, "modifiers")
|
||||
let s:modifiers = a:dict["modifiers"]
|
||||
if has_key(a:dict, "modifier_func")
|
||||
let s:modifier_func = a:dict["modifier_func"]
|
||||
else
|
||||
throw "QNamePicker requires modifier_func being specified when specifying modifiers"
|
||||
endif
|
||||
endif
|
||||
let s:render_func = function("s:QNamePickerRender")
|
||||
if has_key(a:dict, "render_func")
|
||||
let s:render_func = a:dict["render_func"]
|
||||
endif
|
||||
if has_key(a:dict, "complete_func")
|
||||
let s:complete_func = a:dict["complete_func"]
|
||||
else
|
||||
throw "QNamePicker requires complete_func being specified"
|
||||
endif
|
||||
let s:regexp = has_key(a:dict, "regexp") ? a:dict['regexp'] : 0
|
||||
if has_key(a:dict, "height")
|
||||
let s:colPrinter.trow = a:dict["height"]
|
||||
endif
|
||||
if s:colPrinter.trow == 0
|
||||
let s:colPrinter.trow = &lines / 2
|
||||
endif
|
||||
cmap <silent> ~ call QNamePickerRun()<CR>:~
|
||||
let s:origList = a:list
|
||||
let s:indices = range(0, len(s:origList) - 1)
|
||||
call s:colPrinter.put(s:indices, 0)
|
||||
exe "set cmdheight=" . (min([s:colPrinter.trow, len(s:origList)]) + 1)
|
||||
endfunction
|
||||
|
||||
" The main loop. Reads a char from the user, processes it, and ``calls''
|
||||
" itself.
|
||||
function! QNamePickerRun()
|
||||
let _sel = s:colPrinter.sel
|
||||
let _len = len(s:indices)
|
||||
call s:colPrinter.print()
|
||||
call inputsave()
|
||||
echo "\rMatch " . _len . '/' . len(s:origList) . ' names: ' . s:inp
|
||||
let _key = getchar()
|
||||
if !type(_key)
|
||||
let _key = nr2char(_key)
|
||||
endif
|
||||
if _key == "\<BS>"
|
||||
let s:inp = s:inp[:-2]
|
||||
if s:colPrinter.sel < 0 | let s:colPrinter.sel = 0 | endif
|
||||
let s:indices = range(0, len(s:origList)-1)
|
||||
call s:FilterList()
|
||||
elseif _key == "\<C-U>"
|
||||
let s:inp = ""
|
||||
if s:colPrinter.sel < 0 | let s:colPrinter.sel = 0 | endif
|
||||
let s:indices = range(0, len(s:origList)-1)
|
||||
call s:FilterList()
|
||||
elseif _key == "'"
|
||||
" NOTE this causes problems with the regexp so ignore the key
|
||||
elseif _key == s:mapleader && s:useLeader
|
||||
let s:inLeader = 1
|
||||
elseif s:InArr(s:cancelors, _key)
|
||||
call s:QNamePickerUnload()
|
||||
elseif s:InArr(s:acceptors, _key) && _sel < _len
|
||||
call s:Finish(s:indices[_sel], _key)
|
||||
elseif s:InArr(s:modifiers, _key)
|
||||
let s:origList = s:modifier_func((_sel < _len && _sel >= 0) ? s:indices[_sel] : -1, _key)
|
||||
let s:indices = range(0, len(s:origList) - 1)
|
||||
call s:FilterList()
|
||||
if s:colPrinter.sel < 0 | let s:colPrinter.sel = 0 | endif
|
||||
elseif s:InArr(s:selectors, _key)
|
||||
let _nr = char2nr(_key) - char2nr("\<M-1>")
|
||||
if _nr <= -120
|
||||
let _nr = char2nr(_key) - char2nr("1")
|
||||
endif
|
||||
if _nr < 0 " Handle that <M-0> should be index 10
|
||||
let _nr = 9
|
||||
endif
|
||||
if _nr < _len
|
||||
call s:Finish(s:indices[_nr], "\<CR>")
|
||||
endif
|
||||
elseif _key == "\<Up>"
|
||||
call s:colPrinter.vert(-1)
|
||||
elseif _key == "\<Down>"
|
||||
call s:colPrinter.vert(1)
|
||||
elseif _key == "\<Left>"
|
||||
call s:colPrinter.horz(-1)
|
||||
elseif _key == "\<Right>"
|
||||
call s:colPrinter.horz(1)
|
||||
elseif _key == "\<Home>"
|
||||
let s:colPrinter.sel = 0
|
||||
elseif _key == "\<End>"
|
||||
let s:colPrinter.sel = _len-1
|
||||
elseif strlen(_key) == 1 && char2nr(_key) > 31
|
||||
let s:inp = s:inp . _key
|
||||
if _len == 0 " NOTE for s:regexp it may reach 0 b/c of an invalid regexp instead of there being no real matches
|
||||
let s:indices = range(0, len(s:origList) - 1)
|
||||
endif
|
||||
call s:FilterList()
|
||||
endif
|
||||
if _key != s:mapleader && s:inLeader
|
||||
let s:inLeader = 0
|
||||
endif
|
||||
redraws
|
||||
call inputrestore()
|
||||
endfunction
|
||||
|
||||
" Cleans up all the stuff qnamepicker created.
|
||||
function! s:QNamePickerUnload()
|
||||
cmap <silent> ~ exe "cunmap \x7E"<cr>
|
||||
exe "set cmdheight=" . s:cmdh
|
||||
if s:paste
|
||||
set paste
|
||||
else
|
||||
set nopaste
|
||||
endif
|
||||
unlet s:origList
|
||||
unlet s:indices
|
||||
unlet s:colPrinter.rows
|
||||
unlet s:colPrinter.cols
|
||||
endfunction
|
||||
|
||||
" Essentially an identity function
|
||||
function! s:QNamePickerModIdentity(index, key)
|
||||
return s:origList
|
||||
endfunction
|
||||
|
||||
" A simple renderer, it shows the relative index, and the
|
||||
" content in the list given.
|
||||
function! s:QNamePickerRender(index, count, length, columnar)
|
||||
let len = len(a:length)
|
||||
let fill = repeat(' ', len - len(a:count) + 1)
|
||||
return a:count . fill . s:origList[a:index]
|
||||
endfunction
|
||||
|
||||
" The actual finish function, called when an acceptors is pressed.
|
||||
function! s:Finish(item, keypressed)
|
||||
call s:QNamePickerUnload()
|
||||
call s:complete_func(a:item, a:keypressed)
|
||||
endfunction
|
||||
|
||||
" Restricts the set of indices to the set that match the query
|
||||
" (using the original list as the strings)
|
||||
function! s:FilterList()
|
||||
if len(s:inp) > 0
|
||||
let query = tolower(s:inp)
|
||||
if !s:regexp
|
||||
let query = join(split(query, '\zs'), '.*')
|
||||
let query = substitute(query, "\\", "\\\\", "g")
|
||||
let query = substitute(query, "\\.\\.", "\\\\..", "g")
|
||||
endif
|
||||
let s:indices = filter(s:indices, "s:origList[v:val] =~ '" . query . "'")
|
||||
endif
|
||||
call s:colPrinter.put(s:indices, s:colPrinter.sel)
|
||||
endfunction
|
||||
|
||||
" Checks if the character is [a-zA-Z0-9]
|
||||
function! s:IsPrintable(key)
|
||||
return ("a" <= a:key && a:key <= "z") || ("A" <= a:key && a:key <= "Z") || ("0" <= a:key && a:key <= "9")
|
||||
endfunction
|
||||
|
||||
" Checks if the key pressed is present in the array given, taking into account
|
||||
" s:inLeader.
|
||||
function! s:InArr(arr, key)
|
||||
for a in a:arr
|
||||
if s:IsPrintable(a)
|
||||
if a:key == a && s:inLeader
|
||||
return 1
|
||||
endif
|
||||
elseif a:key == a
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Functions for the s:colPrinter
|
||||
function! s:colPrinter.put(its, sel) dict
|
||||
let _cols = []
|
||||
let _trow = self.trow
|
||||
let _len = len(a:its)
|
||||
|
||||
let _its = []
|
||||
let c = 1
|
||||
for i in a:its
|
||||
call add(_its, s:render_func(i, c, _len, _len > _trow))
|
||||
let c += 1
|
||||
endfor
|
||||
let _i = 0
|
||||
while _i < _len
|
||||
if _i+_trow <= _len
|
||||
call add(_cols, remove(_its,0,_trow-1))
|
||||
else
|
||||
call add(_cols, _its)
|
||||
endif
|
||||
let _i += _trow
|
||||
endwhile
|
||||
|
||||
let _cpos = [0]
|
||||
let _cw = []
|
||||
let _t = 0
|
||||
for _li in _cols
|
||||
let _w = max(map(copy(_li), 'strlen(v:val)')) + 4
|
||||
let _t += _w
|
||||
call add(_cpos, _t)
|
||||
call add(_cw, _w)
|
||||
endfor
|
||||
|
||||
let _rows = []
|
||||
for _i in range(_trow)
|
||||
let _row = []
|
||||
for _j in range(len(_cols))
|
||||
if _j*_trow+_i < _len
|
||||
call add(_row, _cols[_j][_i])
|
||||
endif
|
||||
endfor
|
||||
call add(_rows, _row)
|
||||
endfor
|
||||
|
||||
let self.cols = _cols
|
||||
let self.cw = _cw
|
||||
let self.rows = _rows
|
||||
let self.cpos = _cpos
|
||||
let self.len = _len
|
||||
let self.lcol = 0
|
||||
let self.sel = a:sel < _len ? a:sel : _len - 1
|
||||
endfunc
|
||||
|
||||
function! s:colPrinter.horz(mv) dict
|
||||
if self.len < self.trow
|
||||
return
|
||||
endif
|
||||
let _len = self.len
|
||||
let _trow = self.trow
|
||||
let _nr = (_len / _trow) + ((_len % _trow != 0) ? 1 : 0)
|
||||
let _t = self.sel + a:mv * _trow
|
||||
if _t < 0 && _len > 0
|
||||
let _t = abs(_t) % self.trow
|
||||
if _t == 0
|
||||
let self.sel = _trow * _nr - _trow
|
||||
else
|
||||
let _tt = _trow * _nr - _t
|
||||
if _tt >= _len
|
||||
let self.sel = _trow * (_nr-1) - _t
|
||||
else
|
||||
let self.sel = _tt
|
||||
endif
|
||||
endif
|
||||
elseif _t >= 0 && _t < _len
|
||||
let self.sel = _t
|
||||
elseif _t >= _len
|
||||
let self.sel = _t % self.trow
|
||||
endif
|
||||
endfunc
|
||||
|
||||
function! s:colPrinter.vert(mv) dict
|
||||
let _t = self.sel + a:mv
|
||||
let _len = self.len
|
||||
if _t < 0 && _len > 0
|
||||
let self.sel = _len-1
|
||||
elseif _t >= _len
|
||||
let self.sel = 0
|
||||
else
|
||||
let self.sel = _t
|
||||
endif
|
||||
endfunc
|
||||
|
||||
function! s:colPrinter.print() dict
|
||||
let _len = self.len
|
||||
let _trow = &cmdheight - 1
|
||||
if !_len
|
||||
echo " [...NO MATCH...]" repeat("\n",_trow)
|
||||
return
|
||||
endif
|
||||
let _sel = self.sel
|
||||
let _t = _sel/_trow
|
||||
let _cpos = self.cpos
|
||||
let _lcol = self.lcol
|
||||
let _tcol = &columns
|
||||
if _cpos[_lcol]+_tcol < _cpos[_t+1]
|
||||
let _rcol = _t
|
||||
let _pos = _cpos[_t+1]-_tcol-2
|
||||
while _cpos[_lcol] < _pos
|
||||
let _lcol += 1
|
||||
endwhile
|
||||
let _lcol -= _lcol > _t
|
||||
else
|
||||
if _t < _lcol
|
||||
let _lcol = _t
|
||||
endif
|
||||
let _rcol = len(_cpos)-1
|
||||
let _pos = _cpos[_lcol]+_tcol+2
|
||||
while _cpos[_rcol] > _pos
|
||||
let _rcol -= 1
|
||||
endwhile
|
||||
let _rcol -= _rcol > _lcol
|
||||
endif
|
||||
let _cw = self.cw
|
||||
let _pos = _cpos[_lcol]+_tcol
|
||||
let self.lcol = _lcol
|
||||
for _i in range(_trow)
|
||||
let _row = self.rows[_i]
|
||||
for _j in range(_lcol,_rcol)
|
||||
if _j*_trow+_i < _len
|
||||
let _txt = " " . _row[_j]
|
||||
let _txt .= repeat(" ", _cw[_j] - strlen(_txt))
|
||||
let _txt = _txt[:_pos-_cpos[_j]-2]
|
||||
if _j*_trow + _i == _sel
|
||||
echoh Search | echon _txt | echoh None
|
||||
elseif (_i % 2) == 1
|
||||
echoh QNamePickerAlt | echon _txt | echoh None
|
||||
else
|
||||
echon _txt
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
echon "\n"
|
||||
endfor
|
||||
endfunc
|
Loading…
x
Reference in New Issue
Block a user