mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-04-13 22:59:15 +08:00
Add doc for undotree (#3889)
This commit is contained in:
parent
939d8a617f
commit
15a511c32f
@ -12,6 +12,7 @@ let s:PASSWORD = SpaceVim#api#import('password')
|
||||
let s:NUMBER = SpaceVim#api#import('data#number')
|
||||
let s:LIST = SpaceVim#api#import('data#list')
|
||||
let s:VIM = SpaceVim#api#import('vim')
|
||||
let s:CMP = SpaceVim#api#import('vim#compatible')
|
||||
|
||||
function! SpaceVim#layers#edit#plugins() abort
|
||||
let plugins = [
|
||||
@ -38,6 +39,11 @@ function! SpaceVim#layers#edit#plugins() abort
|
||||
if g:spacevim_enable_bepo_layout
|
||||
call add(plugins,[g:_spacevim_root_dir . 'bundle/vim-bepo', { 'merged' : 0}])
|
||||
endif
|
||||
if s:CMP.has('python') || s:CMP.has('python3')
|
||||
call add(plugins,[g:_spacevim_root_dir . 'bundle/vim-mundo', { 'on_cmd' : 'MundoToggle'}])
|
||||
else
|
||||
call add(plugins,[g:_spacevim_root_dir . 'bundle/undotree', { 'on_cmd' : 'UndotreeToggle'}])
|
||||
endif
|
||||
return plugins
|
||||
endfunction
|
||||
|
||||
@ -66,6 +72,12 @@ function! SpaceVim#layers#edit#config() abort
|
||||
vmap <silent> J <Plug>(jplus)
|
||||
" }}}
|
||||
|
||||
|
||||
if s:CMP.has('python') || s:CMP.has('python3')
|
||||
nnoremap <silent> <F7> :MundoToggle<CR>
|
||||
else
|
||||
nnoremap <silent> <F7> :UndotreeToggle<CR>
|
||||
endif
|
||||
let g:_spacevim_mappings_space.x = {'name' : '+Text'}
|
||||
let g:_spacevim_mappings_space.x.a = {'name' : '+align'}
|
||||
let g:_spacevim_mappings_space.x.d = {'name' : '+delete'}
|
||||
@ -307,7 +319,7 @@ endfunction
|
||||
|
||||
function! s:lowerCamelCase() abort
|
||||
" fooFzz
|
||||
if matchstr(getline('.'), '\%' . col('.') . 'c.') =~ '\s'
|
||||
if matchstr(getline('.'), '\%' . col('.') . 'c.') =~# '\s'
|
||||
return
|
||||
endif
|
||||
let cword = s:parse_symbol(expand('<cword>'))
|
||||
@ -327,7 +339,7 @@ endfunction
|
||||
|
||||
function! s:UpperCamelCase() abort
|
||||
" FooFzz
|
||||
if strcharpart(getline('.')[col('.') - 1:], 0, 1) =~ '\s'
|
||||
if strcharpart(getline('.')[col('.') - 1:], 0, 1) =~# '\s'
|
||||
return
|
||||
endif
|
||||
let cword = s:parse_symbol(expand('<cword>'))
|
||||
@ -344,7 +356,7 @@ endfunction
|
||||
|
||||
function! s:kebab_case() abort
|
||||
" foo-fzz
|
||||
if matchstr(getline('.'), '\%' . col('.') . 'c.') =~ '\s'
|
||||
if matchstr(getline('.'), '\%' . col('.') . 'c.') =~# '\s'
|
||||
return
|
||||
endif
|
||||
let cword = s:parse_symbol(expand('<cword>'))
|
||||
@ -373,7 +385,7 @@ endfunction
|
||||
|
||||
function! s:up_case() abort
|
||||
" FOO_FZZ
|
||||
if matchstr(getline('.'), '\%' . col('.') . 'c.') =~ '\s'
|
||||
if matchstr(getline('.'), '\%' . col('.') . 'c.') =~# '\s'
|
||||
return
|
||||
endif
|
||||
let cword =map(s:parse_symbol(expand('<cword>')), 'toupper(v:val)')
|
||||
|
@ -6,6 +6,8 @@
|
||||
" License: GPLv3
|
||||
"=============================================================================
|
||||
|
||||
let s:CMP = SpaceVim#api#import('vim#compatible')
|
||||
|
||||
function! SpaceVim#layers#tools#plugins() abort
|
||||
let plugins = []
|
||||
call add(plugins, ['tpope/vim-scriptease', { 'merged' : 0}])
|
||||
@ -13,7 +15,6 @@ function! SpaceVim#layers#tools#plugins() abort
|
||||
call add(plugins, ['lymslive/vnote', { 'depends' : 'vimloo', 'on_cmd' : ['NoteBook','NoteNew','NoteEdit', 'NoteList', 'NoteConfig', 'NoteIndex', 'NoteImport']}])
|
||||
call add(plugins, ['junegunn/rainbow_parentheses.vim', { 'merged' : 0}])
|
||||
call add(plugins, ['mbbill/fencview', { 'on_cmd' : 'FencAutoDetect'}])
|
||||
call add(plugins, ['simnalamburt/vim-mundo', { 'on_cmd' : 'MundoToggle'}])
|
||||
call add(plugins, ['wsdjeg/vim-cheat', { 'on_cmd' : 'Cheat'}])
|
||||
call add(plugins, ['wsdjeg/Mysql.vim', { 'on_cmd' : 'SQLGetConnection'}])
|
||||
call add(plugins, ['wsdjeg/SourceCounter.vim', { 'on_cmd' : 'SourceCounter'}])
|
||||
@ -29,7 +30,6 @@ function! SpaceVim#layers#tools#plugins() abort
|
||||
\ 'BookmarkPrev',
|
||||
\ ],
|
||||
\ 'loadconf_before' : 1}])
|
||||
let s:CMP = SpaceVim#api#import('vim#compatible')
|
||||
if s:CMP.has('python')
|
||||
call add(plugins, ['gregsexton/VimCalc', {'on_cmd' : 'Calc'}])
|
||||
elseif s:CMP.has('python3')
|
||||
@ -56,7 +56,6 @@ function! SpaceVim#layers#tools#config() abort
|
||||
nnoremap <silent> ma :<C-u>BookmarkShowAll<Cr>
|
||||
nnoremap <silent> mn :<C-u>BookmarkNext<Cr>
|
||||
nnoremap <silent> mp :<C-u>BookmarkPrev<Cr>
|
||||
nnoremap <silent> <F7> :MundoToggle<CR>
|
||||
augroup rainbow_lisp
|
||||
autocmd!
|
||||
autocmd FileType lisp,clojure,scheme,racket,java RainbowParentheses
|
||||
|
1
bundle/undotree/.gitignore
vendored
Normal file
1
bundle/undotree/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
doc/tags
|
66
bundle/undotree/README.md
Normal file
66
bundle/undotree/README.md
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
### [Project on Vim.org](http://www.vim.org/scripts/script.php?script_id=4177)
|
||||
|
||||
[](https://gitter.im/mbbill/undotree?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
### Screenshot
|
||||
|
||||

|
||||
|
||||
### Description
|
||||
|
||||
The plug-in visualizes undo history and makes it easier to browse and switch between different undo branches. You might wonder what is undo "branches"? It's vim feature that allows you to go back to a state when it is overwritten by a latest edit. For most editors, if you make a change A, then B, then go back to A and make change C, normally you won't be able to go back to B because undo history is linear. That's not the case for Vim because it internally keeps all the edit history like a tree structure, and this plug-in exposes the tree to you so that you not only can switch back and forth but also can switch between branches.
|
||||
|
||||
|
||||
Some people have questions about file contents being changed when switching between undo history states. Don't worry, *undotree* will **NEVER** save your data or write to disk. All it does is to change the current buffer little bit, just like those auto-completion plug-ins do. It just adds or removes something in the buffer temporarily, and if you don't like you can always go back to the last state easily. Let's say, you made some change but didn't save, then you use *undotree* and go back to an arbitrary version, your unsaved change doesn't get lost - it stores in the latest undo history node. Clicking that node on *undotree* will bring you back instantly. Play with undo/redo on other editors is always dangerous because when you step back and accidentally typed something, boom! You lose your edits. But don't worry, that won't happen in Vim. Then you might ask what if I make some changes without saving and switch back to an old version and then **exit**? Well, imaging what would happen if you don't have *undotree*? You lose your latest edits and the file on disk is your last saved version. This behaviour **remains the same** with *undotree*. So, if you saved, you won't lose anything.
|
||||
|
||||
|
||||
We all know that usually undo/redo is only for the current edit session. It's stored in memory and once the process exits, the undo history is lost. Although *undotree* makes switching between history states easier, it doesn't do more than that. Sometimes it would be much safer or more convenient to keep the undo history across edit sessions. In this case you might need to enable a Vim feature called *persistent undo*. Let me explain how persistent undo works: instead of keeping undo history in *RAM*, persistent undo keeps undo history in file. Let's say you make a change A, then B, then go back to A and make change C, then you *save* the file. Now Vim save the file with content state C, and in the mean time it saves **the entire** undo history to a file including state A, B and C. Next time when you open the file, Vim will also restore undo history. So you can still go back to B. The history file is incremental, and every change will be recorded permanently, kind of like Git. You might think that's too much, well, *undotree* does provide a way to clean them up. If you need to enable *persistent undo*, type ```:h persistent-undo``` or follow the instructions below.
|
||||
|
||||
|
||||
Undotree is written in **pure Vim script** and doesn't rely on any third party tools. It's lightweight, simple and fast. It only does what it supposed to do, and it only runs when you need it.
|
||||
|
||||
|
||||
### Download and Install
|
||||
|
||||
Use whatever plug-in manager to pull the master branch.
|
||||
|
||||
|
||||
### Usage
|
||||
1. Use `:UndotreeToggle` to toggle the undo-tree panel. You may want to map this command to whatever hotkey by adding the following line to your vimrc, take F5 for example.
|
||||
|
||||
nnoremap <F5> :UndotreeToggle<cr>
|
||||
|
||||
1. Markers
|
||||
* Every change has a sequence number and it is displayed before timestamps.
|
||||
* The current state is marked as `> number <`.
|
||||
* The next state which will be restored by `:redo` or `<ctrl-r>` is marked as `{ number }`.
|
||||
* The `[ number ]` marks the most recent change.
|
||||
* The undo history is sorted by timestamps.
|
||||
* Saved changes are marked as `s` and the big `S` indicates the most recent saved change.
|
||||
1. Press `?` in undotree window for quick help.
|
||||
1. Persistent undo
|
||||
* Usually I would like to store the undo files in a seperate place like below.
|
||||
|
||||
```
|
||||
if has("persistent_undo")
|
||||
set undodir=$HOME."/.undodir"
|
||||
set undofile
|
||||
endif
|
||||
```
|
||||
|
||||
### Configuration
|
||||
[Here](https://github.com/mbbill/undotree/blob/master/plugin/undotree.vim#L15) is a list of options.
|
||||
|
||||
### Debug
|
||||
1. Create a file under $HOME with the name `undotree_debug.log`
|
||||
* `$touch ~/undotree_debug.log`
|
||||
1. Run vim, and the log will automatically be appended to the file, and you may watch it using `tail`:
|
||||
* `$tail -F ~/undotree_debug.log`
|
||||
1. If you want to disable debug, just delete that file.
|
||||
|
||||
### License
|
||||
**BSD**
|
||||
|
||||
### Author
|
||||
Ming Bai <mbbill AT gmail DOT COM>
|
1420
bundle/undotree/autoload/undotree.vim
Normal file
1420
bundle/undotree/autoload/undotree.vim
Normal file
File diff suppressed because it is too large
Load Diff
457
bundle/undotree/doc/undotree.txt
Normal file
457
bundle/undotree/doc/undotree.txt
Normal file
@ -0,0 +1,457 @@
|
||||
*undotree.txt* The undo history visualizer for VIM
|
||||
|
||||
Author: Ming Bai <mbbill AT gmail DOT COM>
|
||||
Licence: BSD
|
||||
Homepage: https://github.com/mbbill/undotree/
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *undotree-contents*
|
||||
|
||||
1. Intro ................................ |undotree-intro|
|
||||
2. Usage ................................ |undotree-usage|
|
||||
3. Configuration ........................ |undotree-config|
|
||||
3.1 undotree_WindowLayout .......... |undotree_WindowLayout|
|
||||
3.2 undotree_CustomUndotreeCmd...... |undotree_CustomUndotreeCmd|
|
||||
undotree_CustomDiffpanelCmd..... |undotree_CustomDiffpanelCmd|
|
||||
3.3 undotree_SplitWidth ............ |undotree_SplitWidth|
|
||||
3.4 undotree_DiffpanelHeight ....... |undotree_DiffpanelHeight|
|
||||
3.5 undotree_DiffAutoOpen .......... |undotree_DiffAutoOpen|
|
||||
3.6 undotree_SetFocusWhenToggle .... |undotree_SetFocusWhenToggle|
|
||||
3.7 undotree_TreeNodeShape ......... |undotree_TreeNodeShape|
|
||||
3.8 undotree_DiffCommand ........... |undotree_DiffCommand|
|
||||
3.9 undotree_RelativeTimestamp ..... |undotree_RelativeTimestamp|
|
||||
3.10 undotree_ShortIndicators ....... |undotree_ShortIndicators|
|
||||
3.11 undotree_HighlightChangedText .. |undotree_HighlightChangedText|
|
||||
3.12 undotree_HighlightSyntaxAdd .... |undotree_HighlightSyntaxAdd|
|
||||
undotree_HighlightSyntaxChange . |undotree_HighlightSyntaxChange|
|
||||
3.13 Undotree_CustomMap ............. |Undotree_CustomMap|
|
||||
3.14 undotree_HelpLine .............. |undotree_HelpLine|
|
||||
4. Bugs ................................. |undotree-bugs|
|
||||
5. Changelog ............................ |undotree-changelog|
|
||||
6. License .............................. |undotree-license|
|
||||
|
||||
==============================================================================
|
||||
1. Intro *undotree-intro*
|
||||
|
||||
The plug-in visualizes undo history and makes it easier to browse and switch
|
||||
between different undo branches. You might wonder what is undo "branches"?
|
||||
It's vim feature that allows you to go back to a state when it is overwritten
|
||||
by a latest edit. For most editors, if you make a change A, then B, then go
|
||||
back to A and make change C, normally you won't be able to go back to B
|
||||
because undo history is linear. That's not the case for Vim because it
|
||||
internally keeps all the edit history like a tree structure, and this plug-in
|
||||
exposes the tree to you so that you not only can switch back and forth but
|
||||
also can switch between branches.
|
||||
|
||||
Some people have questions about file contents being changed when switching
|
||||
between undo history states. Don't worry, undotree will NEVER save your data
|
||||
or write to disk. All it does is to change the current buffer little bit, just
|
||||
like those auto-completion plug-ins do. It just adds or removes something in
|
||||
the buffer temporarily, and if you don't like you can always go back to the
|
||||
last state easily. Let's say, you made some change but didn't save, then you
|
||||
use undotree and go back to an arbitrary version, your unsaved change doesn't
|
||||
get lost - it stores in the latest undo history node. Clicking that node on
|
||||
undotree will bring you back instantly. Play with undo/redo on other editors
|
||||
is always dangerous because when you step back and accidentally typed
|
||||
something, boom! You lose your edits. But don't worry, that won't happen in
|
||||
Vim. Then you might ask what if I make some changes without saving and switch
|
||||
back to an old version and then exit? Well, imaging what would happen if you
|
||||
don't have undotree? You lose your latest edits and the file on disk is your
|
||||
last saved version. This behaviour remains the same with undotree. So, if you
|
||||
saved, you won't lose anything.
|
||||
|
||||
We all know that usually undo/redo is only for the current edit session. It's
|
||||
stored in memory and once the process exits, the undo history is lost.
|
||||
Although undotree makes switching between history states easier, it doesn't do
|
||||
more than that. Sometimes it would be much safer or more convenient to keep
|
||||
the undo history across edit sessions. In this case you might need to enable a
|
||||
Vim feature called persistent undo. Let me explain how persistent undo works:
|
||||
instead of keeping undo history in RAM, persistent undo keeps undo history in
|
||||
file. Let's say you make a change A, then B, then go back to A and make change
|
||||
C, then you save the file. Now Vim save the file with content state C, and in
|
||||
the mean time it saves the entire undo history to a file including state A, B
|
||||
and C. Next time when you open the file, Vim will also restore undo history.
|
||||
So you can still go back to B. The history file is incremental, and every
|
||||
change will be recorded permanently, kind of like Git. You might think that's
|
||||
too much, well, undotree does provide a way to clean them up. If you need to
|
||||
enable persistent undo, type :h persistent-undo or follow the instructions
|
||||
below.
|
||||
|
||||
Undotree is written in pure Vim script and doesn't rely on any third party
|
||||
tools. It's lightweight, simple and fast. It only does what it supposed to do,
|
||||
and it only runs when you need it.
|
||||
|
||||
==============================================================================
|
||||
2. Usage *undotree-usage*
|
||||
|
||||
Use :UndotreeToggle to toggle the undo-tree panel. You may want to map this
|
||||
command to whatever hotkey by adding the following line to your vimrc, take F5
|
||||
for example.
|
||||
>
|
||||
nnoremap <F5> :UndotreeToggle<cr>
|
||||
<
|
||||
Markers
|
||||
|
||||
* Every change has a sequence number and it is displayed before timestamps.
|
||||
|
||||
* The current state is marked as > number <.
|
||||
|
||||
* The next state which will be restored by :redo or <ctrl-r> is marked as
|
||||
{ number }.
|
||||
|
||||
* The [ number ] marks the most recent change.
|
||||
|
||||
* The undo history is sorted by timestamps.
|
||||
|
||||
* Saved changes are marked as s and the big S indicates the most recent
|
||||
saved change.
|
||||
|
||||
* Press ? in undotree window for quick help.
|
||||
|
||||
Persistent undo
|
||||
|
||||
Usually I would like to store the undo files in a seperate place like below.
|
||||
>
|
||||
if has("persistent_undo")
|
||||
set undodir=$HOME."/.undodir"
|
||||
set undofile
|
||||
endif
|
||||
<
|
||||
==============================================================================
|
||||
3. Configuration *undotree-config*
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.1 g:undotree_WindowLayout *undotree_WindowLayout*
|
||||
|
||||
Set the undotree window layout.
|
||||
|
||||
Style 1
|
||||
>
|
||||
+----------+------------------------+
|
||||
| | |
|
||||
| | |
|
||||
| undotree | |
|
||||
| | |
|
||||
| | |
|
||||
+----------+ |
|
||||
| | |
|
||||
| diff | |
|
||||
| | |
|
||||
+----------+------------------------+
|
||||
<
|
||||
Style 2
|
||||
>
|
||||
+----------+------------------------+
|
||||
| | |
|
||||
| | |
|
||||
| undotree | |
|
||||
| | |
|
||||
| | |
|
||||
+----------+------------------------+
|
||||
| |
|
||||
| diff |
|
||||
| |
|
||||
+-----------------------------------+
|
||||
<
|
||||
Style 3
|
||||
>
|
||||
+------------------------+----------+
|
||||
| | |
|
||||
| | |
|
||||
| | undotree |
|
||||
| | |
|
||||
| | |
|
||||
| +----------+
|
||||
| | |
|
||||
| | diff |
|
||||
| | |
|
||||
+------------------------+----------+
|
||||
<
|
||||
Style 4
|
||||
>
|
||||
+------------------------+----------+
|
||||
| | |
|
||||
| | |
|
||||
| | undotree |
|
||||
| | |
|
||||
| | |
|
||||
+------------------------+----------+
|
||||
| |
|
||||
| diff |
|
||||
| |
|
||||
+-----------------------------------+
|
||||
<
|
||||
Default: 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.2 g:undotree_CustomUndotreeCmd *undotree_CustomUndotreeCmd*
|
||||
g:undotree_CustomDiffpanelCmd *undotree_CustomDiffpanelCmd*
|
||||
|
||||
Set up custom window layout.
|
||||
|
||||
Setting |undotree_CustomUndotreeCmd| will ignore |undotree_SplitWidth|, and
|
||||
setting |undotree_CustomDiffpanelCmd| will ignore |undotree_DiffpanelHeight|.
|
||||
|
||||
An |undotree_CustomUndotreeCmd| will always open the undotree window relative
|
||||
to the tracked window and |undotree_CustomDiffpanelCmd| will always open the
|
||||
diffpanel relative to the undotree window.
|
||||
|
||||
Useful when
|
||||
|
||||
* absolute positioning commands (|topleft|, |botright|) don't play well
|
||||
with other plugins
|
||||
|
||||
* you have a preferred split window layout and would like to use
|
||||
UndoTree relative to one specific window only
|
||||
|
||||
Examples:
|
||||
|
||||
* To recreate Style 1:
|
||||
>
|
||||
let g:undotree_CustomUndotreeCmd = 'topleft vertical 30 new'
|
||||
let g:undotree_CustomDiffpanelCmd = 'belowright 10 new'
|
||||
<
|
||||
* To recreate Style 2:
|
||||
>
|
||||
let g:undotree_CustomUndotreeCmd = 'topleft vertical 30 new'
|
||||
let g:undotree_CustomDiffpanelCmd = 'botright 10 new'
|
||||
<
|
||||
* A custom layout example:
|
||||
>
|
||||
+------------------------+----------+
|
||||
| | |
|
||||
| | w |
|
||||
| | i |
|
||||
| | n |
|
||||
| window_1 | d |
|
||||
| | o |
|
||||
| | w |
|
||||
| | | |
|
||||
| | 2 |
|
||||
| | |
|
||||
+------------------------+----------+
|
||||
| |
|
||||
| window_3 |
|
||||
| |
|
||||
+-----------------------------------+
|
||||
<
|
||||
Using the following setup wouldn't mess up the current layout as it
|
||||
does not use absolute positioning:
|
||||
>
|
||||
let g:undotree_CustomUndotreeCmd = 'vertical 32 new'
|
||||
let g:undotree_CustomDiffpanelCmd= 'belowright 12 new'
|
||||
<
|
||||
Issuing :UndotreeToggle now in window_1 would result in:
|
||||
>
|
||||
+--------+---------------+----------+
|
||||
| | | |
|
||||
| u | | w |
|
||||
| n | | i |
|
||||
| d | | n |
|
||||
| o | window_1 | d |
|
||||
| | | o |
|
||||
+--------+ | w |
|
||||
| | | | |
|
||||
| diff | | 2 |
|
||||
| | | |
|
||||
+--------+---------------+----------+
|
||||
| |
|
||||
| window_3 |
|
||||
| |
|
||||
+-----------------------------------+
|
||||
<
|
||||
Executing :UndotreeToggle again would turn off UndoTree (independently
|
||||
of which window was active at the time). Moving between window1, window_2
|
||||
and window_3 would result in showing the respective window's changelog
|
||||
in the undotree panel.
|
||||
|
||||
CAVEAT: To avoid the Vim's default behaviour of equalizing window sizes
|
||||
when closing a window, set the 'noequalalways' option.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.3 g:undotree_SplitWidth *undotree_SplitWidth*
|
||||
|
||||
Set the undotree window width.
|
||||
|
||||
Default: 30
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.4 g:undotree_DiffpanelHeight *undotree_DiffpanelHeight*
|
||||
|
||||
Set the diff window height.
|
||||
|
||||
Default: 10
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.5 g:undotree_DiffAutoOpen *undotree_DiffAutoOpen*
|
||||
|
||||
Set this to 1 to auto open the diff window.
|
||||
|
||||
Default: 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.6 g:undotree_SetFocusWhenToggle *undotree_SetFocusWhenToggle*
|
||||
|
||||
If set to 1, the undotree window will get focus after being opened, otherwise
|
||||
focus will stay in current window.
|
||||
|
||||
Default: 0
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.7 g:undotree_TreeNodeShape *undotree_TreeNodeShape*
|
||||
|
||||
Set the tree node shape.
|
||||
|
||||
Default: '*'
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.8 g:undotree_DiffCommand *undotree_DiffCommand*
|
||||
|
||||
Set the command used to get the diff output.
|
||||
|
||||
Default: "diff"
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.9 g:undotree_RelativeTimestamp *undotree_RelativeTimestamp*
|
||||
|
||||
Set to 1 to use relative timestamp.
|
||||
|
||||
Default: 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.10 g:undotree_ShortIndicators *undotree_ShortIndicators*
|
||||
|
||||
Set to 1 to get short timestamps when |undotree_RelativeTimestamp| is also
|
||||
enabled:
|
||||
>
|
||||
Before | After
|
||||
===========================
|
||||
(5 seconds ago) | (5 s)
|
||||
----------------|----------
|
||||
(1 minute ago) | (1 m)
|
||||
----------------|----------
|
||||
(2 minutes ago) | (2 m)
|
||||
----------------|----------
|
||||
(1 hour ago) | (1 h)
|
||||
----------------|----------
|
||||
(Original) | (Orig)
|
||||
<
|
||||
Default: 0
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.11 g:undotree_HighlightChangedText *undotree_HighlightChangedText*
|
||||
|
||||
Set to 1 to highlight the changed text.
|
||||
|
||||
Default: 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.12 g:undotree_HighlightSyntaxAdd *undotree_HighlightSyntaxAdd*
|
||||
g:undotree_HighlightSyntaxChange *undotree_HighlightSyntaxChange*
|
||||
|
||||
Set the highlight linked syntax type.
|
||||
You may chose your favorite through ":hi" command.
|
||||
|
||||
Default: "DiffAdd" and "DiffChange"
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.13 g:Undotree_CustomMap *Undotree_CustomMap*
|
||||
|
||||
There are two ways of changing the default key mappings:
|
||||
The first way is to define global mappings as the following example:
|
||||
>
|
||||
nmap <buffer> J <plug>UndotreeNextState
|
||||
nmap <buffer> K <plug>UndotreePreviousState
|
||||
<
|
||||
A better approach is to define the callback function g:Undotree_CustomMap().
|
||||
The function will be called after the undotree windows is initialized, so the
|
||||
key mappings only works on the undotree windows.
|
||||
>
|
||||
function g:Undotree_CustomMap()
|
||||
nmap <buffer> J <plug>UndotreeNextState
|
||||
nmap <buffer> K <plug>UndotreePreviousState
|
||||
endfunc
|
||||
<
|
||||
List of the commands available for redefinition.
|
||||
>
|
||||
<plug>UndotreeHelp
|
||||
<plug>UndotreeClose
|
||||
<plug>UndotreeFocusTarget
|
||||
<plug>UndotreeClearHistory
|
||||
<plug>UndotreeTimestampToggle
|
||||
<plug>UndotreeDiffToggle
|
||||
<plug>UndotreeNextState
|
||||
<plug>UndotreePreviousState
|
||||
<plug>UndotreeNextSavedState
|
||||
<plug>UndotreePreviousSavedState
|
||||
<plug>UndotreeRedo
|
||||
<plug>UndotreeUndo
|
||||
<plug>UndotreeEnter
|
||||
<
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.14 g:undotree_HelpLine *undotree_HelpLine*
|
||||
|
||||
Set to 0 to hide "Press ? for help".
|
||||
|
||||
Default: 1
|
||||
==============================================================================
|
||||
4. Bugs *undotree-bugs*
|
||||
|
||||
Post any issue and feature request here:
|
||||
https://github.com/mbbill/undotree/issues
|
||||
|
||||
==============================================================================
|
||||
5. Changelog *undotree-changelog*
|
||||
|
||||
Further changes will not be recorded. Please go to github page for more
|
||||
information.
|
||||
|
||||
4.4 (2017-10-15)
|
||||
- Autoload plugin functions
|
||||
|
||||
4.3 (2013-02-18)
|
||||
- Several fixes and enhancements.
|
||||
|
||||
4.2 (2012-11-24)
|
||||
- Fixed some small issue.
|
||||
|
||||
4.1 (2012-09-05)
|
||||
- Enhanced tree style.
|
||||
- Multi-window switching support.
|
||||
|
||||
4.0 (2012-08-30)
|
||||
- Live updated highlight for changed text.
|
||||
- Customizable key mappings.
|
||||
- Fixed some minor bugs.
|
||||
|
||||
3.1 (2012-08-25)
|
||||
- Add saved status.
|
||||
- Add relative timestamp.
|
||||
- Add ability of clear undo history.
|
||||
|
||||
3.0 (2012-08-24)
|
||||
- Add diff panel.
|
||||
- Performance improvement.
|
||||
|
||||
2.2 (2012-08-21)
|
||||
- Stable version.
|
||||
|
||||
2.1 (2012-08-20)
|
||||
- Fixed some annoying issues.
|
||||
|
||||
2.0 (2012-08-19)
|
||||
- Hotkey support.
|
||||
- Handle undo levels.
|
||||
- Auto refresh.
|
||||
- And so on.
|
||||
|
||||
1.0 (2012-08-18)
|
||||
- Initial upload
|
||||
|
||||
==============================================================================
|
||||
6. License *undotree-license*
|
||||
|
||||
BSD
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
166
bundle/undotree/plugin/undotree.vim
Normal file
166
bundle/undotree/plugin/undotree.vim
Normal file
@ -0,0 +1,166 @@
|
||||
"=================================================
|
||||
" File: plugin/undotree.vim
|
||||
" Description: Manage your undo history in a graph.
|
||||
" Author: Ming Bai <mbbill@gmail.com>
|
||||
" License: BSD
|
||||
|
||||
" Avoid installing twice.
|
||||
if exists('g:loaded_undotree')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_undotree = 0
|
||||
|
||||
" At least version 7.3 with 005 patch is needed for undo branches.
|
||||
" Refer to https://github.com/mbbill/undotree/issues/4 for details.
|
||||
" Thanks kien
|
||||
if v:version < 703
|
||||
command! -n=0 -bar UndotreeToggle :echoerr "undotree.vim needs Vim version >= 7.3"
|
||||
finish
|
||||
endif
|
||||
if (v:version == 703 && !has("patch005"))
|
||||
command! -n=0 -bar UndotreeToggle :echoerr "undotree.vim needs vim7.3 with patch005 applied."
|
||||
finish
|
||||
endif
|
||||
let g:loaded_undotree = 1 " Signal plugin availability with a value of 1.
|
||||
|
||||
"=================================================
|
||||
"Options:
|
||||
|
||||
" Window layout
|
||||
" style 1
|
||||
" +----------+------------------------+
|
||||
" | | |
|
||||
" | | |
|
||||
" | undotree | |
|
||||
" | | |
|
||||
" | | |
|
||||
" +----------+ |
|
||||
" | | |
|
||||
" | diff | |
|
||||
" | | |
|
||||
" +----------+------------------------+
|
||||
" Style 2
|
||||
" +----------+------------------------+
|
||||
" | | |
|
||||
" | | |
|
||||
" | undotree | |
|
||||
" | | |
|
||||
" | | |
|
||||
" +----------+------------------------+
|
||||
" | |
|
||||
" | diff |
|
||||
" | |
|
||||
" +-----------------------------------+
|
||||
" Style 3
|
||||
" +------------------------+----------+
|
||||
" | | |
|
||||
" | | |
|
||||
" | | undotree |
|
||||
" | | |
|
||||
" | | |
|
||||
" | +----------+
|
||||
" | | |
|
||||
" | | diff |
|
||||
" | | |
|
||||
" +------------------------+----------+
|
||||
" Style 4
|
||||
" +-----------------------++----------+
|
||||
" | | |
|
||||
" | | |
|
||||
" | | undotree |
|
||||
" | | |
|
||||
" | | |
|
||||
" +------------------------+----------+
|
||||
" | |
|
||||
" | diff |
|
||||
" | |
|
||||
" +-----------------------------------+
|
||||
if !exists('g:undotree_WindowLayout')
|
||||
let g:undotree_WindowLayout = 1
|
||||
endif
|
||||
|
||||
" e.g. using 'd' instead of 'days' to save some space.
|
||||
if !exists('g:undotree_ShortIndicators')
|
||||
let g:undotree_ShortIndicators = 0
|
||||
endif
|
||||
|
||||
" undotree window width
|
||||
if !exists('g:undotree_SplitWidth')
|
||||
if g:undotree_ShortIndicators == 1
|
||||
let g:undotree_SplitWidth = 24
|
||||
else
|
||||
let g:undotree_SplitWidth = 30
|
||||
endif
|
||||
endif
|
||||
|
||||
" diff window height
|
||||
if !exists('g:undotree_DiffpanelHeight')
|
||||
let g:undotree_DiffpanelHeight = 10
|
||||
endif
|
||||
|
||||
" auto open diff window
|
||||
if !exists('g:undotree_DiffAutoOpen')
|
||||
let g:undotree_DiffAutoOpen = 1
|
||||
endif
|
||||
|
||||
" if set, let undotree window get focus after being opened, otherwise
|
||||
" focus will stay in current window.
|
||||
if !exists('g:undotree_SetFocusWhenToggle')
|
||||
let g:undotree_SetFocusWhenToggle = 0
|
||||
endif
|
||||
|
||||
" tree node shape.
|
||||
if !exists('g:undotree_TreeNodeShape')
|
||||
let g:undotree_TreeNodeShape = '*'
|
||||
endif
|
||||
|
||||
if !exists('g:undotree_DiffCommand')
|
||||
let g:undotree_DiffCommand = "diff"
|
||||
endif
|
||||
|
||||
" relative timestamp
|
||||
if !exists('g:undotree_RelativeTimestamp')
|
||||
let g:undotree_RelativeTimestamp = 1
|
||||
endif
|
||||
|
||||
" Highlight changed text
|
||||
if !exists('g:undotree_HighlightChangedText')
|
||||
let g:undotree_HighlightChangedText = 1
|
||||
endif
|
||||
|
||||
" Highlight changed text using signs in the gutter
|
||||
if !exists('g:undotree_HighlightChangedWithSign')
|
||||
let g:undotree_HighlightChangedWithSign = 1
|
||||
endif
|
||||
|
||||
" Highlight linked syntax type.
|
||||
" You may chose your favorite through ":hi" command
|
||||
if !exists('g:undotree_HighlightSyntaxAdd')
|
||||
let g:undotree_HighlightSyntaxAdd = "DiffAdd"
|
||||
endif
|
||||
if !exists('g:undotree_HighlightSyntaxChange')
|
||||
let g:undotree_HighlightSyntaxChange = "DiffChange"
|
||||
endif
|
||||
if !exists('g:undotree_HighlightSyntaxDel')
|
||||
let g:undotree_HighlightSyntaxDel = "DiffDelete"
|
||||
endif
|
||||
|
||||
" Deprecates the old style configuration.
|
||||
if exists('g:undotree_SplitLocation')
|
||||
echo "g:undotree_SplitLocation is deprecated,
|
||||
\ please use g:undotree_WindowLayout instead."
|
||||
endif
|
||||
|
||||
" Show help line
|
||||
if !exists('g:undotree_HelpLine')
|
||||
let g:undotree_HelpLine = 1
|
||||
endif
|
||||
|
||||
"=================================================
|
||||
" User commands.
|
||||
command! -n=0 -bar UndotreeToggle :call undotree#UndotreeToggle()
|
||||
command! -n=0 -bar UndotreeHide :call undotree#UndotreeHide()
|
||||
command! -n=0 -bar UndotreeShow :call undotree#UndotreeShow()
|
||||
command! -n=0 -bar UndotreeFocus :call undotree#UndotreeFocus()
|
||||
|
||||
" vim: set et fdm=marker sts=4 sw=4:
|
37
bundle/undotree/syntax/undotree.vim
Normal file
37
bundle/undotree/syntax/undotree.vim
Normal file
@ -0,0 +1,37 @@
|
||||
"=================================================
|
||||
" File: undotree.vim
|
||||
" Description: undotree syntax
|
||||
" Author: Ming Bai <mbbill@gmail.com>
|
||||
" License: BSD
|
||||
|
||||
syn match UndotreeNode ' \zs\*\ze '
|
||||
syn match UndotreeNodeCurrent '\zs\*\ze.*>\d\+<'
|
||||
syn match UndotreeTimeStamp '(.*)$'
|
||||
syn match UndotreeFirstNode 'Original'
|
||||
syn match UndotreeBranch '[|/\\]'
|
||||
syn match UndotreeSeq ' \zs\d\+\ze '
|
||||
syn match UndotreeCurrent '>\d\+<'
|
||||
syn match UndotreeNext '{\d\+}'
|
||||
syn match UndotreeHead '\[\d\+]'
|
||||
syn match UndotreeHelp '^".*$' contains=UndotreeHelpKey,UndotreeHelpTitle
|
||||
syn match UndotreeHelpKey '^" \zs.\{-}\ze:' contained
|
||||
syn match UndotreeHelpTitle '===.*===' contained
|
||||
syn match UndotreeSavedSmall ' \zss\ze '
|
||||
syn match UndotreeSavedBig ' \zsS\ze '
|
||||
|
||||
hi def link UndotreeNode Question
|
||||
hi def link UndotreeNodeCurrent Statement
|
||||
hi def link UndotreeTimeStamp Function
|
||||
hi def link UndotreeFirstNode Function
|
||||
hi def link UndotreeBranch Constant
|
||||
hi def link UndotreeSeq Comment
|
||||
hi def link UndotreeCurrent Statement
|
||||
hi def link UndotreeNext Type
|
||||
hi def link UndotreeHead Identifier
|
||||
hi def link UndotreeHelp Comment
|
||||
hi def link UndotreeHelpKey Function
|
||||
hi def link UndotreeHelpTitle Type
|
||||
hi def link UndotreeSavedSmall WarningMsg
|
||||
hi def link UndotreeSavedBig MatchParen
|
||||
|
||||
" vim: set et fdm=marker sts=4 sw=4:
|
2
bundle/vim-mundo/.gitignore
vendored
Normal file
2
bundle/vim-mundo/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
**/doc/**/tags
|
||||
*.pyc
|
32
bundle/vim-mundo/COPYRIGHT
Normal file
32
bundle/vim-mundo/COPYRIGHT
Normal file
@ -0,0 +1,32 @@
|
||||
Short version for non-laywers:
|
||||
The vim-mundo project is licensed under GPLv2 terms or any later version.
|
||||
|
||||
Longer version:
|
||||
vim-mundo
|
||||
Copyright (C) 2013-2017 Dane Summers
|
||||
Copyright (C) 2014-2017 Hyeon Kim
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
The vim-mundo project includes packages written by third parties. The
|
||||
following third party packages are included, and carry their own copyright
|
||||
notices and license terms:
|
||||
|
||||
* This project is forked from gundo.vim <https://bitbucket.org/sjl/gundo.vim>
|
||||
which is licensed under GPLv2 or any later version.
|
||||
|
||||
* The initial version of graphing codes was all taken from
|
||||
Mercurial <https://www.mercurial-scm.org/> which is licensed under GPLv2 or
|
||||
any later version.
|
339
bundle/vim-mundo/LICENSE
Normal file
339
bundle/vim-mundo/LICENSE
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
113
bundle/vim-mundo/README.md
Normal file
113
bundle/vim-mundo/README.md
Normal file
@ -0,0 +1,113 @@
|
||||
vim-mundo
|
||||
=========
|
||||
A Vim plugin to visualizes the Vim [undo tree].
|
||||
|
||||
<img src="https://simnalamburt.github.io/vim-mundo/screenshot.png">
|
||||
|
||||
* [Official webpage]
|
||||
* [Introductory Video]
|
||||
|
||||
<br>
|
||||
|
||||
### How is this different than other plugins?
|
||||
Mundo is a fork of [Gundo], and it has bunch of improvements.
|
||||
|
||||
* Several new features:
|
||||
* Ability to search undo history using <kbd>/</kbd>.
|
||||
* An 'in line' diff mode.
|
||||
* Navigation keys <kbd>J</kbd> and <kbd>K</kbd> to move thru written undos.
|
||||
* Merged upstream [pull requests]:
|
||||
* [Fix paths with spaces][pr-29]
|
||||
* [Display timestamps in ISO format][pr-28]
|
||||
* [Real time updates][i-40]
|
||||
* [Show changes saved to disk][i-34]
|
||||
* [Python NoneType errors][i-38]
|
||||
* [open vimdiff of current buffer][i-28]
|
||||
* [Add global_disable option][i-33]
|
||||
* [Reduce verbosity][i-31]
|
||||
* [Neovim] support
|
||||
|
||||
#### What's your further plan?
|
||||
* Make faster
|
||||
* Automated test
|
||||
|
||||
<br>
|
||||
|
||||
### Requirements
|
||||
* Vim ≥ *7.3* *or* [Neovim]
|
||||
* `+python3` or `+python` compile option
|
||||
* Python ≥ *2.4*
|
||||
|
||||
Recommended vim settings:
|
||||
```vim
|
||||
" Enable persistent undo so that undo history persists across vim sessions
|
||||
set undofile
|
||||
set undodir=~/.vim/undo
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### Installation
|
||||
|
||||
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:
|
||||
|
||||
#### Pathogen
|
||||
|
||||
$ git clone https://github.com/simnalamburt/vim-mundo ~/.vim/bundle/mundo.vim
|
||||
|
||||
#### Vundle
|
||||
|
||||
```vim
|
||||
Plugin 'simnalamburt/vim-mundo'
|
||||
```
|
||||
|
||||
#### NeoBundle
|
||||
|
||||
```vim
|
||||
NeoBundle 'simnalamburt/vim-mundo'
|
||||
```
|
||||
|
||||
#### Vim-Plug
|
||||
|
||||
```vim
|
||||
Plug 'simnalamburt/vim-mundo'
|
||||
```
|
||||
|
||||
#### Manual (not recommended)
|
||||
|
||||
[Download](releases) the plugin and extract it in `~/.vim/` (or
|
||||
`%PROGRAMFILES%/Vim/vimfiles` on Windows).
|
||||
|
||||
#### Unit tests
|
||||
Tests unit tests can be run with [nose]:
|
||||
```shell
|
||||
cd autoload
|
||||
nosetests
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
--------
|
||||
|
||||
*vim-mundo* is primarily distributed under the terms of the [GNU General Public
|
||||
License, version 2] or any later version. See [COPYRIGHT] for details.
|
||||
|
||||
[pull requests]: https://github.com/sjl/gundo.vim/pulls
|
||||
[undo tree]: https://neovim.io/doc/user/undo.html#undo-tree
|
||||
[Gundo]: https://github.com/sjl/gundo.vim
|
||||
[Official webpage]: https://simnalamburt.github.io/vim-mundo
|
||||
[Introductory Video]: https://simnalamburt.github.io/vim-mundo/screencast.mp4
|
||||
[Neovim]: https://neovim.io
|
||||
[pr-29]: https://github.com/sjl/gundo.vim/pull/29
|
||||
[pr-28]: https://github.com/sjl/gundo.vim/pull/28
|
||||
[i-34]: https://bitbucket.org/sjl/gundo.vim/issue/34/show-changes-that-were-saved-onto-disk
|
||||
[i-38]: https://bitbucket.org/sjl/gundo.vim/issue/38/python-errors-nonetype-not-iterable-with
|
||||
[i-40]: https://bitbucket.org/sjl/gundo.vim/issue/40/feature-request-live-reload
|
||||
[i-28]: https://bitbucket.org/sjl/gundo.vim/issue/28/feature-request-open-vimdiff-of-current#comment-3129981
|
||||
[i-33]: https://bitbucket.org/sjl/gundo.vim/issue/33/let-g-gundo_disable-0-is-not-available
|
||||
[i-31]: https://bitbucket.org/sjl/gundo.vim/issue/31/reduce-verbosity-of-the-list
|
||||
[nose]: https://nose.readthedocs.org/en/latest/
|
||||
[GNU General Public License, version 2]: LICENSE
|
||||
[COPYRIGHT]: COPYRIGHT
|
35
bundle/vim-mundo/autoload/airline/extensions/mundo.vim
Normal file
35
bundle/vim-mundo/autoload/airline/extensions/mundo.vim
Normal file
@ -0,0 +1,35 @@
|
||||
scriptencoding utf-8
|
||||
|
||||
function! airline#extensions#mundo#inactive_statusline(...)
|
||||
let builder = a:1
|
||||
if getwinvar(a:2.winnr, '&filetype') == 'Mundo'
|
||||
return -1
|
||||
endif
|
||||
if getwinvar(a:2.winnr, '&filetype') == 'MundoDiff'
|
||||
return 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! airline#extensions#mundo#statusline(...)
|
||||
let builder = a:1
|
||||
if &filetype == 'Mundo'
|
||||
call builder.add_section('airline_a',
|
||||
\ get(g:, 'mundo_tree_statusline', 'Mundo'))
|
||||
call builder.split()
|
||||
call builder.add_section('airline_z', '%p%%')
|
||||
return 1
|
||||
endif
|
||||
if &filetype == 'MundoDiff'
|
||||
call builder.add_section('airline_a',
|
||||
\ get(g:, 'mundo_preview_statusline', 'Mundo Diff'))
|
||||
call builder.split()
|
||||
return 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! airline#extensions#mundo#init(...)
|
||||
call airline#add_statusline_func('airline#extensions#mundo#statusline')
|
||||
call airline#add_inactive_statusline_func(
|
||||
\ 'airline#extensions#mundo#inactive_statusline')
|
||||
endfunction
|
||||
|
16
bundle/vim-mundo/autoload/graphlog_test.py
Normal file
16
bundle/vim-mundo/autoload/graphlog_test.py
Normal file
@ -0,0 +1,16 @@
|
||||
import nose
|
||||
from nose.tools import *
|
||||
from mock import patch
|
||||
import mundo.graphlog as graphlog
|
||||
from mundo.node import Nodes
|
||||
|
||||
@patch('mundo.util.vim')
|
||||
def test_generate(mock_vim):
|
||||
eq_(graphlog.generate(
|
||||
False,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
False,
|
||||
Nodes()
|
||||
), [['o ', '[0] Original ']])
|
547
bundle/vim-mundo/autoload/mundo.py
Normal file
547
bundle/vim-mundo/autoload/mundo.py
Normal file
@ -0,0 +1,547 @@
|
||||
# vim: set fdm=marker ts=4 sw=4 et:
|
||||
# ============================================================================
|
||||
# File: mundo.py
|
||||
# Description: vim global plugin to visualize your undo tree
|
||||
# Maintainer: Hyeon Kim <simnalamburt@gmail.com>
|
||||
# License: GPLv2+ -- look it up.
|
||||
# Notes: Much of this code was thieved from Mercurial, and the rest was
|
||||
# heavily inspired by scratch.vim and histwin.vim.
|
||||
#
|
||||
# ============================================================================
|
||||
|
||||
import re
|
||||
import tempfile
|
||||
import vim
|
||||
|
||||
from mundo.node import Nodes
|
||||
import mundo.util as util
|
||||
import mundo.graphlog as graphlog
|
||||
|
||||
# Python Vim utility functions --------------------------------------------#{{{
|
||||
|
||||
MISSING_BUFFER = "Cannot find Mundo's target buffer (%s)"
|
||||
MISSING_WINDOW = "Cannot find window (%s) for Mundo's target buffer (%s)"
|
||||
|
||||
def _check_sanity():
|
||||
""" Check to make sure we're not crazy.
|
||||
|
||||
Ensures that:
|
||||
* The target buffer exists, is loaded and is present in the tab.
|
||||
* That neovim is not in terminal mode.
|
||||
"""
|
||||
global nodesData
|
||||
|
||||
if not nodesData:
|
||||
nodesData = Nodes()
|
||||
|
||||
# Check that the target buffer exists, is loaded and is present in the tab
|
||||
b = int(vim.eval('g:mundo_target_n'))
|
||||
|
||||
if not vim.eval('bufloaded(%d)' % int(b)):
|
||||
vim.command('echo "%s"' % (MISSING_BUFFER % b))
|
||||
return False
|
||||
|
||||
w = int(vim.eval('bufwinnr(%d)' % int(b)))
|
||||
|
||||
if w == -1:
|
||||
vim.command('echo "%s"' % (MISSING_WINDOW % (w, b)))
|
||||
return False
|
||||
|
||||
# Check if we are in terminal mode.
|
||||
mode = vim.eval('mode()')
|
||||
|
||||
if mode == 't':
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
INLINE_HELP = '''\
|
||||
" Mundo (%d) - Press ? for Help:
|
||||
" j/k - Next/Prev undo state.
|
||||
" J/K - Next/Prev write state.
|
||||
" i - Toggle 'inline diff' mode.
|
||||
" / - Find changes that match string.
|
||||
" n/N - Next/Prev undo that matches search.
|
||||
" P - Play current state to selected undo.
|
||||
" d - Vert diff of undo with current state.
|
||||
" p - Diff of selected undo and current state.
|
||||
" r - Diff of selected undo and prior undo.
|
||||
" q - Quit!
|
||||
" <cr> - Revert to selected state.
|
||||
|
||||
'''
|
||||
|
||||
# }}}
|
||||
|
||||
nodesData = Nodes()
|
||||
|
||||
# from profilehooks import profile
|
||||
# @profile(immediate=True)
|
||||
def MundoRenderGraph(force=False):# {{{
|
||||
""" Renders the undo graph if necessary, updating it to reflect changes in
|
||||
the target buffer's undo tree.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
force : bool
|
||||
If True, the graph will always be rendered. If False, then the
|
||||
graph may not be rendered - when is already current for example.
|
||||
"""
|
||||
if not _check_sanity():
|
||||
return
|
||||
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
|
||||
first_visible_line = int(vim.eval("line('w0')"))
|
||||
last_visible_line = int(vim.eval("line('w$')"))
|
||||
|
||||
verbose = vim.eval('g:mundo_verbose_graph') == "1"
|
||||
target = int(vim.eval('g:mundo_target_n'))
|
||||
|
||||
header = []
|
||||
if int(vim.eval('g:mundo_header')):
|
||||
if int(vim.eval('g:mundo_help')):
|
||||
header = (INLINE_HELP % target).splitlines()
|
||||
else:
|
||||
header = [(INLINE_HELP % target).splitlines()[0], '\n']
|
||||
|
||||
show_inline_undo = int(vim.eval("g:mundo_inline_undo")) == 1
|
||||
mundo_last_visible_line = int(vim.eval("g:mundo_last_visible_line"))
|
||||
mundo_first_visible_line = int(vim.eval("g:mundo_first_visible_line"))
|
||||
|
||||
if not force and not nodesData.is_outdated() and (
|
||||
not show_inline_undo or
|
||||
(
|
||||
mundo_first_visible_line == first_visible_line and
|
||||
mundo_last_visible_line == last_visible_line
|
||||
)
|
||||
):
|
||||
return
|
||||
|
||||
result = graphlog.generate(
|
||||
verbose,
|
||||
len(header)+1,
|
||||
first_visible_line,
|
||||
last_visible_line,
|
||||
show_inline_undo,
|
||||
nodesData
|
||||
)
|
||||
vim.command("let g:mundo_last_visible_line=%s"%last_visible_line)
|
||||
vim.command("let g:mundo_first_visible_line=%s"%first_visible_line)
|
||||
|
||||
output = []
|
||||
# right align the dag and flip over the y axis:
|
||||
flip_dag = int(vim.eval("g:mundo_mirror_graph")) == 1
|
||||
dag_width = 1
|
||||
for line in result:
|
||||
if len(line[0]) > dag_width:
|
||||
dag_width = len(line[0])
|
||||
for line in result:
|
||||
if flip_dag:
|
||||
dag_line = (line[0][::-1]).replace("/","\\")
|
||||
output.append("%*s %s"% (dag_width,dag_line,line[1]))
|
||||
else:
|
||||
output.append("%-*s %s"% (dag_width,line[0],line[1]))
|
||||
|
||||
vim.command('call s:MundoOpenGraph()')
|
||||
vim.command('setlocal modifiable')
|
||||
lines = (header + output)
|
||||
lines = [line.rstrip('\n') for line in lines]
|
||||
vim.current.buffer[:] = lines
|
||||
vim.command('setlocal nomodifiable')
|
||||
|
||||
i = 1
|
||||
for line in output:
|
||||
try:
|
||||
line.split('[')[0].index('@')
|
||||
i += 1
|
||||
break
|
||||
except ValueError:
|
||||
pass
|
||||
i += 1
|
||||
vim.command('%d' % (i+len(header)-1))
|
||||
# }}}
|
||||
|
||||
def MundoRenderPreview():# {{{
|
||||
""" Opens the preview window if necessary and renders a preview diff. """
|
||||
if not _check_sanity():
|
||||
return
|
||||
|
||||
target_state = MundoGetTargetState()
|
||||
target_n = int(vim.eval('g:mundo_target_n'))
|
||||
|
||||
# If there's no target state or the buffer has changed, update the cached
|
||||
# undo tree data, redraw the graph and abort preview rendering
|
||||
if target_state is None or nodesData.target_n != target_n:
|
||||
nodesData.make_nodes()
|
||||
MundoRenderGraph(True)
|
||||
return
|
||||
|
||||
util._goto_window_for_buffer(target_n)
|
||||
nodes, nmap = nodesData.make_nodes()
|
||||
node_after = nmap[target_state]
|
||||
node_before = node_after.parent
|
||||
|
||||
vim.command('call s:MundoOpenPreview()')
|
||||
util._output_preview_text(nodesData.preview_diff(node_before, node_after))
|
||||
|
||||
# Mark the preview as up-to-date
|
||||
vim.command('call mundo#MundoPreviewOutdated(0)')
|
||||
# }}}
|
||||
|
||||
def MundoGetTargetState():# {{{
|
||||
""" Get the current undo number that mundo is at. """
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
target_line = vim.eval("getline('.')")
|
||||
matches = re.match('^[^\[]* \[([0-9]+)\] .*$', target_line)
|
||||
if matches:
|
||||
return int(matches.group(1))
|
||||
return 0
|
||||
# }}}
|
||||
|
||||
def GetNextLine(direction,move_count,write,start="line('.')"):# {{{
|
||||
""" Recursively finds the line number resulting from undo graph traversal
|
||||
according to the given parameters.
|
||||
"""
|
||||
start_line_no = int(vim.eval(start))
|
||||
start_line = vim.eval("getline(%d)" % start_line_no)
|
||||
mundo_verbose_graph = vim.eval('g:mundo_verbose_graph')
|
||||
if mundo_verbose_graph != "0":
|
||||
distance = 2
|
||||
|
||||
# If we're in between two nodes we move by one less to get back on track.
|
||||
if start_line.find('[') == -1:
|
||||
distance = distance - 1
|
||||
else:
|
||||
distance = 1
|
||||
nextline = vim.eval("getline(%d)" % (start_line_no+direction))
|
||||
idx1 = nextline.find('@')
|
||||
idx2 = nextline.find('o')
|
||||
idx3 = nextline.find('w')
|
||||
# if the next line is not a revision - then go down one more.
|
||||
if (idx1+idx2+idx3) == -3:
|
||||
distance = distance + 1
|
||||
|
||||
next_line = start_line_no + distance*direction
|
||||
if move_count > 1:
|
||||
return GetNextLine(direction,move_count-1,write,str(next_line))
|
||||
elif write:
|
||||
newline = vim.eval("getline(%d)" % (next_line))
|
||||
if newline.find('w ') == -1:
|
||||
# make sure that if we can't go up/down anymore that we quit out.
|
||||
if direction < 0 and next_line == 1:
|
||||
return next_line
|
||||
if direction > 0 and next_line >= len(vim.current.window.buffer):
|
||||
return next_line
|
||||
return GetNextLine(direction,1,write,str(next_line))
|
||||
return next_line
|
||||
# }}}
|
||||
|
||||
def MundoMove(direction,move_count=1,relative=True,write=False):# {{{
|
||||
"""
|
||||
Move within the undo graph in the direction specified (or to the specific
|
||||
undo node specified).
|
||||
|
||||
Parameters:
|
||||
|
||||
direction - -1/1 (up/down). when 'relative' if False, the undo node to
|
||||
move to.
|
||||
move_count - how many times to perform the operation (irrelevent for
|
||||
relative == False).
|
||||
relative - whether to move up/down, or to jump to a specific undo node.
|
||||
|
||||
write - If True, move to the next written undo.
|
||||
"""
|
||||
if relative:
|
||||
target_n = GetNextLine(direction,move_count,write)
|
||||
else:
|
||||
updown = 1
|
||||
if MundoGetTargetState() < direction:
|
||||
updown = -1
|
||||
target_n = GetNextLine(updown,abs(MundoGetTargetState()-direction),write)
|
||||
|
||||
# Bound the movement to the graph.
|
||||
help_lines = 0
|
||||
if int(vim.eval('g:mundo_header')):
|
||||
help_lines = 3
|
||||
elif int(vim.eval('g:mundo_help')):
|
||||
help_lines = len(INLINE_HELP.split('\n'))
|
||||
if target_n <= help_lines:
|
||||
vim.command("call cursor(%d, 0)" % help_lines)
|
||||
else:
|
||||
vim.command("call cursor(%d, 0)" % target_n)
|
||||
|
||||
line = vim.eval("getline('.')")
|
||||
|
||||
# Move to the node, whether it's an @, o, or w
|
||||
idx1 = line.find('@ ')
|
||||
idx2 = line.find('o ')
|
||||
idx3 = line.find('w ')
|
||||
idxs = []
|
||||
if idx1 != -1:
|
||||
idxs.append(idx1)
|
||||
if idx2 != -1:
|
||||
idxs.append(idx2)
|
||||
if idx3 != -1:
|
||||
idxs.append(idx3)
|
||||
if len(idxs)==0:
|
||||
minidx=0
|
||||
else:
|
||||
minidx=min(idxs)
|
||||
if idx1 == minidx:
|
||||
vim.command("call cursor(0, %d + 1)" % idx1)
|
||||
elif idx2 == minidx:
|
||||
vim.command("call cursor(0, %d + 1)" % idx2)
|
||||
else:
|
||||
vim.command("call cursor(0, %d + 1)" % idx3)
|
||||
|
||||
# Mark the preview as outdated
|
||||
vim.command('call mundo#MundoPreviewOutdated(1)')
|
||||
# }}}
|
||||
|
||||
def MundoSearch():# {{{
|
||||
try:
|
||||
search = vim.eval("input('/')")
|
||||
except:
|
||||
return
|
||||
|
||||
if len(search) == 0:
|
||||
return
|
||||
|
||||
vim.command('let @/="%s"' % search.replace("\\", "\\\\").replace('"', '\\"'))
|
||||
MundoNextMatch()
|
||||
# }}}
|
||||
|
||||
def MundoPrevMatch():# {{{
|
||||
MundoMatch(-1)
|
||||
# }}}
|
||||
|
||||
def MundoNextMatch():# {{{
|
||||
MundoMatch(1)
|
||||
# }}}
|
||||
|
||||
def MundoMatch(down):# {{{
|
||||
""" Jump to the next node that matches the current pattern. If there is a
|
||||
next node, search from the next node to the end of the list of changes.
|
||||
Stop on a match. """
|
||||
if not _check_sanity():
|
||||
return
|
||||
# save the current window number (should be the navigation window)
|
||||
# then generate the undo nodes, and then go back to the current window.
|
||||
util._goto_window_for_buffer(int(vim.eval('g:mundo_target_n')))
|
||||
|
||||
nodes, nmap = nodesData.make_nodes()
|
||||
total = len(nodes) - 1
|
||||
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
mundo_node = MundoGetTargetState()
|
||||
|
||||
found_version = -1
|
||||
if total > 0:
|
||||
therange = range(mundo_node-1,-1,-1)
|
||||
if down < 0:
|
||||
therange = range(mundo_node+1,total+1)
|
||||
for version in therange:
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
undochanges = nodesData.preview_diff(nmap[version].parent, nmap[version])
|
||||
# Look thru all of the changes, ignore the first two b/c those are the
|
||||
# diff timestamp fields (not relevent):
|
||||
for change in undochanges[3:]:
|
||||
match_index = vim.eval('match("%s",@/)'% change.replace("\\","\\\\").replace('"','\\"'))
|
||||
# only consider the matches that are actual additions or
|
||||
# subtractions
|
||||
if int(match_index) >= 0 and (change.startswith('-') or change.startswith('+')):
|
||||
found_version = version
|
||||
break
|
||||
# found something, lets get out of here:
|
||||
if found_version != -1:
|
||||
break
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
if found_version >= 0:
|
||||
MundoMove(found_version,1,False)
|
||||
# }}}
|
||||
|
||||
def MundoRenderPatchdiff():# {{{
|
||||
""" Call MundoRenderChangePreview and display a vert diffpatch with the
|
||||
current file. """
|
||||
if MundoRenderChangePreview():
|
||||
# if there are no lines, do nothing (show a warning).
|
||||
util._goto_window_for_buffer('__Mundo_Preview__')
|
||||
if vim.current.buffer[:] == ['']:
|
||||
# restore the cursor position before exiting.
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
vim.command('unsilent echo "No difference between current file and undo number!"')
|
||||
return False
|
||||
|
||||
# quit out of mundo main screen
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
vim.command('quit')
|
||||
|
||||
# save the __Mundo_Preview__ buffer to a temp file.
|
||||
util._goto_window_for_buffer('__Mundo_Preview__')
|
||||
(handle,filename) = tempfile.mkstemp()
|
||||
vim.command('silent! w %s' % (filename))
|
||||
# exit the __Mundo_Preview__ window
|
||||
vim.command('bdelete')
|
||||
# diff the temp file
|
||||
vim.command('silent! keepalt vert diffpatch %s' % (filename))
|
||||
vim.command('set buftype=nofile bufhidden=delete')
|
||||
return True
|
||||
return False
|
||||
# }}}
|
||||
|
||||
def MundoGetChangesForLine():# {{{
|
||||
if not _check_sanity():
|
||||
return False
|
||||
|
||||
target_state = MundoGetTargetState()
|
||||
|
||||
# Check that there's an undo state. There may not be if we're talking about
|
||||
# a buffer with no changes yet.
|
||||
if target_state == None:
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
return False
|
||||
else:
|
||||
target_state = int(target_state)
|
||||
|
||||
util._goto_window_for_buffer(int(vim.eval('g:mundo_target_n')))
|
||||
|
||||
nodes, nmap = nodesData.make_nodes()
|
||||
|
||||
node_after = nmap[target_state]
|
||||
node_before = nmap[nodesData.current()]
|
||||
return nodesData.change_preview_diff(node_before, node_after)
|
||||
# }}}
|
||||
|
||||
def MundoRenderChangePreview():# {{{
|
||||
""" Render a diff of the target buffer and the selected undo
|
||||
tree node. Returns True on success, False otherwise.
|
||||
"""
|
||||
if not _check_sanity():
|
||||
return
|
||||
|
||||
vim.command('call s:MundoOpenPreview()')
|
||||
util._output_preview_text(MundoGetChangesForLine())
|
||||
util._goto_window_for_buffer('__Mundo__')
|
||||
|
||||
# Mark the preview as up-to-date
|
||||
vim.command('call mundo#MundoPreviewOutdated(0)')
|
||||
|
||||
return True
|
||||
# }}}
|
||||
|
||||
def MundoRenderToggleInlineDiff():# {{{
|
||||
""" Toggles g:mundo_inline_undo and redraws the graph window. """
|
||||
show_inline = int(vim.eval('g:mundo_inline_undo'))
|
||||
if show_inline == 0:
|
||||
vim.command("let g:mundo_inline_undo=1")
|
||||
else:
|
||||
vim.command("let g:mundo_inline_undo=0")
|
||||
line = int(vim.eval("line('.')"))
|
||||
nodesData.clear_oneline_diffs()
|
||||
MundoRenderGraph(True)
|
||||
vim.command("call cursor(%d,0)" % line)
|
||||
# }}}
|
||||
|
||||
def MundoToggleHelp():# {{{
|
||||
""" Toggles g:mundo_help and redraws the graph window. """
|
||||
show_help = int(vim.eval('g:mundo_help'))
|
||||
if show_help == 0:
|
||||
vim.command("let g:mundo_help=1")
|
||||
else:
|
||||
vim.command("let g:mundo_help=0")
|
||||
line = int(vim.eval("line('.')"))
|
||||
column = int(vim.eval("col('.')"))
|
||||
old_line_count = int(vim.eval("line('$')"))
|
||||
MundoRenderGraph(True)
|
||||
new_line_count = int(vim.eval("line('$')"))
|
||||
vim.command(
|
||||
"call cursor(%d, %d)" % (line + new_line_count - old_line_count,
|
||||
column)
|
||||
)
|
||||
|
||||
# Mundo undo/redo}}}
|
||||
|
||||
def MundoRevert():# {{{
|
||||
""" Reverts the target buffer to the state associated with a selected node
|
||||
in the undo graph.
|
||||
"""
|
||||
if not _check_sanity():
|
||||
return
|
||||
|
||||
target_n = MundoGetTargetState()
|
||||
back = int(vim.eval('g:mundo_target_n'))
|
||||
|
||||
util._goto_window_for_buffer(back)
|
||||
util._undo_to(target_n)
|
||||
|
||||
MundoRenderGraph()
|
||||
|
||||
if int(vim.eval('g:mundo_return_on_revert')):
|
||||
util._goto_window_for_buffer(back)
|
||||
|
||||
if int(vim.eval('g:mundo_close_on_revert')):
|
||||
vim.command('MundoToggle')
|
||||
# }}}
|
||||
|
||||
def MundoPlayTo():# {{{
|
||||
""" Replays changes between the current state and a selected state in
|
||||
real-time.
|
||||
"""
|
||||
if not _check_sanity():
|
||||
return
|
||||
|
||||
target_n = MundoGetTargetState()
|
||||
back = int(vim.eval('g:mundo_target_n'))
|
||||
delay = int(vim.eval('g:mundo_playback_delay'))
|
||||
|
||||
util._goto_window_for_buffer(back)
|
||||
util.normal('zn')
|
||||
|
||||
nodes, nmap = nodesData.make_nodes()
|
||||
start = nmap[nodesData.current()]
|
||||
end = nmap[target_n]
|
||||
|
||||
def _walk_branch(origin, dest):# {{{
|
||||
rev = origin.n < dest.n
|
||||
nodes = []
|
||||
|
||||
if origin.n > dest.n:
|
||||
current, final = origin, dest
|
||||
else:
|
||||
current, final = dest, origin
|
||||
|
||||
while current.n > final.n:
|
||||
nodes.append(current)
|
||||
current = current.parent
|
||||
|
||||
if current.n != final.n:
|
||||
return None
|
||||
|
||||
nodes.append(current)
|
||||
|
||||
if rev:
|
||||
return reversed(nodes)
|
||||
else:
|
||||
return nodes
|
||||
# }}}
|
||||
|
||||
branch = _walk_branch(start, end)
|
||||
|
||||
if not branch:
|
||||
vim.command('unsilent echo "No path to that node from here!"')
|
||||
util.normal('zN')
|
||||
return
|
||||
|
||||
for node in branch:
|
||||
util._undo_to(node.n)
|
||||
MundoRenderGraph()
|
||||
util.normal('zz')
|
||||
util._goto_window_for_buffer(back)
|
||||
vim.command('redraw | sleep %dm' % delay)
|
||||
|
||||
util.normal('zN')
|
||||
# }}}
|
||||
|
||||
# vim: set ts=4 sw=4 tw=79 fdm=marker et :
|
561
bundle/vim-mundo/autoload/mundo.vim
Normal file
561
bundle/vim-mundo/autoload/mundo.vim
Normal file
@ -0,0 +1,561 @@
|
||||
" ============================================================================
|
||||
" File: mundo.vim
|
||||
" Description: vim global plugin to visualize your undo tree
|
||||
" Maintainer: Hyeon Kim <simnalamburt@gmail.com>
|
||||
" License: GPLv2+ -- look it up.
|
||||
" Notes: Much of this code was thiefed from Mercurial, and the rest was
|
||||
" heavily inspired by scratch.vim and histwin.vim.
|
||||
"
|
||||
" ============================================================================
|
||||
|
||||
|
||||
let s:save_cpo = &cpoptions
|
||||
set cpoptions&vim
|
||||
|
||||
"{{{ Init
|
||||
|
||||
" Initialise global vars
|
||||
let s:auto_preview_timer = -1"{{{
|
||||
let s:preview_outdated = 1
|
||||
let s:has_supported_python = 0
|
||||
let s:has_timers = 0
|
||||
let s:init_error = 'Initialisation failed due to an unknown error. '
|
||||
\ . 'Please submit a bug report :)'
|
||||
|
||||
" This has to be outside of a function, otherwise it just picks up the CWD
|
||||
let s:plugin_path = escape(expand('<sfile>:p:h'), '\')"}}}
|
||||
|
||||
" Default to placeholder functions for exposed methods
|
||||
function! mundo#MundoToggle() abort "{{{
|
||||
call mundo#util#Echo('WarningMsg',
|
||||
\ 'Mundo init error: ' . s:init_error)
|
||||
endfunction
|
||||
|
||||
function! mundo#MundoShow() abort
|
||||
call mundo#util#Echo('WarningMsg',
|
||||
\ 'Mundo init error: ' . s:init_error)
|
||||
endfunction
|
||||
|
||||
function! mundo#MundoHide() abort
|
||||
call mundo#util#Echo('WarningMsg',
|
||||
\ 'Mundo init error: ' . s:init_error)
|
||||
endfunction
|
||||
"}}}
|
||||
|
||||
" Check vim version
|
||||
if v:version <? '703'"{{{
|
||||
let s:init_error = 'Vim version 7.03+ or later is required.'
|
||||
let &cpoptions = s:save_cpo
|
||||
finish
|
||||
elseif v:version >=? '800' && has('timers')
|
||||
let s:has_timers = 1
|
||||
endif"}}}
|
||||
|
||||
" Check python version
|
||||
if g:mundo_prefer_python3 && has('python3')"{{{
|
||||
let s:has_supported_python = 2
|
||||
elseif has('python')"
|
||||
let s:has_supported_python = 1
|
||||
elseif has('python3')"
|
||||
let s:has_supported_python = 2
|
||||
endif
|
||||
|
||||
if !s:has_supported_python
|
||||
let s:init_error = 'A supported python version was not found.'
|
||||
let &cpoptions = s:save_cpo
|
||||
finish
|
||||
endif"}}}
|
||||
|
||||
" Python init methods
|
||||
function! s:InitPythonModule(python)"{{{
|
||||
exe a:python .' import sys'
|
||||
exe a:python .' if sys.version_info[:2] < (2, 4): '.
|
||||
\ 'vim.command("let s:has_supported_python = 0")'
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoSetupPythonPath()"{{{
|
||||
if g:mundo_python_path_setup == 0
|
||||
let g:mundo_python_path_setup = 1
|
||||
call s:MundoPython('sys.path.insert(1, "'. s:plugin_path .'")')
|
||||
call s:MundoPython('sys.path.insert(1, "'. s:plugin_path .'/mundo")')
|
||||
end
|
||||
endfunction"}}}
|
||||
"}}}
|
||||
|
||||
"{{{ Mundo buffer settings
|
||||
|
||||
function! s:MundoMakeMapping(mapping, action)
|
||||
exec 'nnoremap <script> <silent> <buffer> ' . a:mapping .' '. a:action
|
||||
endfunction
|
||||
|
||||
function! s:MundoMapGraph()"{{{
|
||||
for key in keys(g:mundo_mappings)
|
||||
let l:value = g:mundo_mappings[key]
|
||||
if l:value == "move_older"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoMove(1,'. v:count .')')<CR>")
|
||||
elseif l:value == "move_newer"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoMove(-1,'. v:count .')')<CR>")
|
||||
elseif l:value == "preview"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoRenderPreview(1)<CR>:<C-u> call <sid>MundoPythonRestoreView('MundoRevert()')<CR>")
|
||||
elseif l:value == "move_older_write"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoMove(1,'.v:count.',True,True)')<CR>")
|
||||
elseif l:value == "move_newer_write"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoMove(-1,'.v:count.',True,True)')<CR>")
|
||||
elseif l:value == "move_top"
|
||||
call s:MundoMakeMapping(key, "gg:<C-u>call <sid>MundoPython('MundoMove(1,'.v:count.')')<CR>")
|
||||
elseif l:value == "move_bottom"
|
||||
call s:MundoMakeMapping(key, "G:<C-u>call <sid>MundoPython('MundoMove(0,0)')<CR>:<C-u>call <sid>MundoRefresh()<CR>")
|
||||
elseif l:value == "play_to"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPythonRestoreView('MundoPlayTo()')<CR>zz")
|
||||
elseif l:value == "diff"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPythonRestoreView('MundoRenderPatchdiff()')<CR>")
|
||||
elseif l:value == "toggle_inline"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPythonRestoreView('MundoRenderToggleInlineDiff()')<CR>")
|
||||
elseif l:value == "search"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoSearch()')<CR>")
|
||||
elseif l:value == "next_match"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoNextMatch()')<CR>")
|
||||
elseif l:value == "previous_match"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoPrevMatch()')<CR>")
|
||||
elseif l:value == "diff_current_buffer"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPythonRestoreView('MundoRenderChangePreview()')<CR>")
|
||||
elseif l:value == "diff"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoRenderPreview(1)<CR>")
|
||||
elseif l:value == "toggle_help"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoPython('MundoToggleHelp()')<CR>")
|
||||
elseif l:value == "quit"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoClose()<CR>")
|
||||
elseif l:value == "mouse_click"
|
||||
call s:MundoMakeMapping(key, ":<C-u>call <sid>MundoMouseDoubleClick()<CR>")
|
||||
endif
|
||||
endfor
|
||||
|
||||
cabbrev <script> <silent> <buffer> q call <sid>MundoClose()
|
||||
cabbrev <script> <silent> <buffer> quit call <sid>MundoClose()
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoMapPreview()"{{{
|
||||
nnoremap <script> <silent> <buffer> q :<C-u>call <sid>MundoClose()<CR>
|
||||
cabbrev <script> <silent> <buffer> q call <sid>MundoClose()
|
||||
cabbrev <script> <silent> <buffer> quit call <sid>MundoClose()
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoSettingsGraph()"{{{
|
||||
setlocal buftype=nofile
|
||||
setlocal bufhidden=hide
|
||||
setlocal noswapfile
|
||||
setlocal nobuflisted
|
||||
setlocal nomodifiable
|
||||
setlocal filetype=Mundo
|
||||
setlocal nolist
|
||||
setlocal nonumber
|
||||
setlocal norelativenumber
|
||||
setlocal nowrap
|
||||
call s:MundoSyntaxGraph()
|
||||
call s:MundoMapGraph()
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoSettingsPreview()"{{{
|
||||
setlocal buftype=nofile
|
||||
setlocal bufhidden=hide
|
||||
setlocal noswapfile
|
||||
setlocal nobuflisted
|
||||
setlocal nomodifiable
|
||||
setlocal filetype=MundoDiff
|
||||
setlocal syntax=diff
|
||||
setlocal nonumber
|
||||
setlocal norelativenumber
|
||||
setlocal nowrap
|
||||
setlocal foldlevel=20
|
||||
setlocal foldmethod=diff
|
||||
call s:MundoMapPreview()
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoSyntaxGraph()"{{{
|
||||
let b:current_syntax = 'mundo'
|
||||
syn match MundoCurrentLocation '@'
|
||||
syn match MundoHelp '\v^".*$'
|
||||
syn match MundoNumberField '\v\[[0-9]+\]'
|
||||
syn match MundoNumber '\v[0-9]+' contained containedin=MundoNumberField
|
||||
syn region MundoDiff start=/\v<ago> / end=/$/
|
||||
syn match MundoDiffAdd '\v\+[^+-]+\+' contained containedin=MundoDiff
|
||||
syn match MundoDiffDelete '\v-[^+-]+-' contained containedin=MundoDiff
|
||||
hi def link MundoCurrentLocation Keyword
|
||||
hi def link MundoHelp Comment
|
||||
hi def link MundoNumberField Comment
|
||||
hi def link MundoNumber Identifier
|
||||
hi def link MundoDiffAdd DiffAdd
|
||||
hi def link MundoDiffDelete DiffDelete
|
||||
endfunction"}}}
|
||||
|
||||
"}}}
|
||||
|
||||
"{{{ Mundo buffer/window management
|
||||
|
||||
function! s:MundoResizeBuffers(backto)"{{{
|
||||
call mundo#util#GoToBuffer('__Mundo__')
|
||||
exe "vertical resize " . g:mundo_width
|
||||
|
||||
call mundo#util#GoToBuffer('__Mundo_Preview__')
|
||||
exe "resize " . g:mundo_preview_height
|
||||
|
||||
exe a:backto . "wincmd w"
|
||||
endfunction"}}}
|
||||
|
||||
" Open the graph window. Assumes that the preview window is open.
|
||||
function! s:MundoOpenGraph()"{{{
|
||||
if !mundo#util#GoToBuffer("__Mundo__")
|
||||
call assert_true(mundo#util#GoToBuffer('__Mundo_Preview__'))
|
||||
let existing_mundo_buffer = bufnr("__Mundo__")
|
||||
|
||||
if existing_mundo_buffer == -1
|
||||
" Create buffer
|
||||
silent new __Mundo__
|
||||
|
||||
if g:mundo_preview_bottom
|
||||
execute 'wincmd ' . (g:mundo_right ? 'L' : 'H')
|
||||
endif
|
||||
else
|
||||
" Open a window for existing buffer
|
||||
if g:mundo_preview_bottom
|
||||
let pos = (g:mundo_right ? 'botright' : 'topleft')
|
||||
silent execute pos.' vsplit +buffer' . existing_mundo_buffer
|
||||
else
|
||||
silent execute 'split +buffer' . existing_mundo_buffer
|
||||
endif
|
||||
endif
|
||||
|
||||
call s:MundoResizeBuffers(winnr())
|
||||
endif
|
||||
|
||||
if exists("g:mundo_tree_statusline")
|
||||
let &l:statusline = g:mundo_tree_statusline
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoOpenPreview()"{{{
|
||||
if !mundo#util#GoToBuffer("__Mundo_Preview__")
|
||||
let existing_preview_buffer = bufnr("__Mundo_Preview__")
|
||||
|
||||
if existing_preview_buffer == -1
|
||||
" Create buffer
|
||||
if g:mundo_preview_bottom
|
||||
silent botright keepalt new __Mundo_Preview__
|
||||
else
|
||||
let pos = (g:mundo_right ? 'botright' : 'topleft')
|
||||
silent execute pos.' keepalt vnew __Mundo_Preview__'
|
||||
endif
|
||||
else
|
||||
" Open a window for existing buffer
|
||||
if g:mundo_preview_bottom
|
||||
silent execute 'botright keepalt split +buffer' .
|
||||
\ existing_preview_buffer
|
||||
else
|
||||
let pos = (g:mundo_right ? 'botright' : 'topleft')
|
||||
silent execute pos.' keepalt vsplit +buffer' .
|
||||
\ existing_preview_buffer
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if exists("g:mundo_preview_statusline")
|
||||
let &l:statusline = g:mundo_preview_statusline
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
" Quits *all* open Mundo graph and preview windows.
|
||||
function! s:MundoClose() abort
|
||||
let [l:tabid, l:winid] = win_id2tabwin(win_getid())
|
||||
|
||||
" Close all graph and preview windows
|
||||
while mundo#util#GoToBufferGlobal('__Mundo__') ||
|
||||
\ mundo#util#GoToBufferGlobal('__Mundo_Preview__')
|
||||
quit
|
||||
endwhile
|
||||
|
||||
" Attempt to return to previous window / tab or target buffer
|
||||
if win_gotoid(l:winid)
|
||||
return
|
||||
elseif l:tabid != 0 && l:tabid <= tabpagenr('$')
|
||||
execute 'normal! ' . l:tabid . 'gt'
|
||||
endif
|
||||
|
||||
call mundo#util#GoToBuffer(get(g:, 'mundo_target_n', -1))
|
||||
endfunction
|
||||
|
||||
" Returns 1 if the current buffer is a valid target buffer for Mundo, or a
|
||||
" (falsy) string indicating the reason if otherwise.
|
||||
function! s:MundoValidateBuffer()"{{{
|
||||
if !&modifiable
|
||||
let reason = 'is not modifiable'
|
||||
elseif &previewwindow
|
||||
let reason = 'is a preview window'
|
||||
elseif &buftype == 'help' || &buftype == 'quickfix' || &buftype == 'terminal'
|
||||
let reason = 'is a '.&buftype.' window'
|
||||
else
|
||||
return 1
|
||||
endif
|
||||
|
||||
call mundo#util#Echo('None', 'Current buffer ('.bufnr('').') is not a '
|
||||
\ .'valid target for Mundo (Reason: '.reason.')')
|
||||
return 0
|
||||
endfunction "}}}
|
||||
|
||||
" Returns True if the graph or preview windows are open in the current tab.
|
||||
function! s:MundoIsVisible()"{{{
|
||||
return bufwinnr(bufnr("__Mundo__")) != -1 ||
|
||||
\ bufwinnr(bufnr("__Mundo_Preview__")) != -1
|
||||
endfunction"}}}
|
||||
|
||||
" Open/reopen Mundo for the current buffer, initialising the python module if
|
||||
" necessary.
|
||||
function! s:MundoOpen() abort "{{{
|
||||
" Validate current buffer
|
||||
if !s:MundoValidateBuffer()
|
||||
return
|
||||
endif
|
||||
|
||||
let g:mundo_target_n = bufnr('')
|
||||
call s:MundoClose()
|
||||
|
||||
" Initialise python module if necessary
|
||||
if !exists('g:mundo_py_loaded')
|
||||
call s:MundoSetupPythonPath()
|
||||
|
||||
if s:has_supported_python == 2
|
||||
exe 'py3file ' . escape(s:plugin_path, ' ') . '/mundo.py'
|
||||
call s:InitPythonModule('python3')
|
||||
else
|
||||
exe 'pyfile ' . escape(s:plugin_path, ' ') . '/mundo.py'
|
||||
call s:InitPythonModule('python')
|
||||
endif
|
||||
|
||||
let g:mundo_py_loaded = 1
|
||||
endif
|
||||
|
||||
" Save and reset `splitbelow` to avoid window positioning problems
|
||||
let saved_splitbelow = &splitbelow
|
||||
let &splitbelow = 0
|
||||
|
||||
" Temporarily disable automatic previews until Mundo is opened
|
||||
let saved_auto_preview = g:mundo_auto_preview
|
||||
let g:mundo_auto_preview = 0
|
||||
|
||||
" Create / open graph and preview windows
|
||||
call s:MundoOpenPreview()
|
||||
call mundo#util#GoToBuffer(g:mundo_target_n)
|
||||
call s:MundoOpenGraph()
|
||||
|
||||
" Render the graph and preview, ensure the cursor is on a graph node
|
||||
call s:MundoPythonRestoreView('MundoRenderGraph(True)')
|
||||
call s:MundoRenderPreview()
|
||||
call s:MundoPython('MundoMove(0,0)')
|
||||
|
||||
" Restore `splitbelow` and automatic preview option
|
||||
let &splitbelow = saved_splitbelow
|
||||
let g:mundo_auto_preview = saved_auto_preview
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoToggle()"{{{
|
||||
if s:MundoIsVisible()
|
||||
call s:MundoClose()
|
||||
else
|
||||
call s:MundoOpen()
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoShow()"{{{
|
||||
if !s:MundoIsVisible()
|
||||
call s:MundoOpen()
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoHide()"{{{
|
||||
call s:MundoSetupPythonPath()
|
||||
if s:MundoIsVisible()
|
||||
call s:MundoClose()
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
"}}}
|
||||
|
||||
"{{{ Mundo mouse handling
|
||||
|
||||
function! s:MundoMouseDoubleClick()"{{{
|
||||
let start_line = getline('.')
|
||||
|
||||
if stridx(start_line, '[') == -1
|
||||
return
|
||||
else
|
||||
call <sid>MundoPythonRestoreView('MundoRevert()')
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
"}}}
|
||||
|
||||
"{{{ Mundo rendering
|
||||
|
||||
function! s:MundoPython(fn)"{{{
|
||||
exec "python".(s:has_supported_python == 2 ? '3' : '')." ". a:fn
|
||||
endfunction"}}}
|
||||
|
||||
" Wrapper for MundoPython() that restores the window state and prevents other
|
||||
" Mundo autocommands (with the exception of BufNewFile) from triggering.
|
||||
function! s:MundoPythonRestoreView(fn)"{{{
|
||||
" Store view data, mode, window and 'evntignore' value
|
||||
let currentmode = mode()
|
||||
let currentWin = winnr()
|
||||
let winView = winsaveview()
|
||||
let eventignoreBack = &eventignore
|
||||
set eventignore=BufLeave,BufEnter,CursorHold,CursorMoved,TextChanged
|
||||
\,InsertLeave
|
||||
|
||||
" Call python function
|
||||
call s:MundoPython(a:fn)
|
||||
|
||||
" Restore view data
|
||||
execute currentWin .'wincmd w'
|
||||
call winrestview(winView)
|
||||
exec 'set eventignore='.eventignoreBack
|
||||
|
||||
" Re-select visual selection
|
||||
if currentmode == 'v' || currentmode == 'V' || currentmode == ''
|
||||
execute 'normal! gv'
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
" Accepts an optional integer that forces rendering if nonzero.
|
||||
function! s:MundoRenderPreview(...)"{{{
|
||||
if !s:preview_outdated && (a:0 < 1 || !a:1)
|
||||
return
|
||||
endif
|
||||
|
||||
call s:MundoPythonRestoreView('MundoRenderPreview()')
|
||||
endfunction"}}}
|
||||
|
||||
"}}}
|
||||
|
||||
"{{{ Misc
|
||||
|
||||
" automatically reload Mundo buffer if open
|
||||
function! s:MundoRefresh()"{{{
|
||||
" abort if Mundo is closed or cursor is in the preview window
|
||||
let mundoWin = bufwinnr('__Mundo__')
|
||||
let mundoPreWin = bufwinnr('__Mundo_Preview__')
|
||||
let currentWin = bufwinnr('%')
|
||||
|
||||
if mundoWin == -1 || mundoPreWin == -1 || mundoPreWin == currentWin
|
||||
return
|
||||
endif
|
||||
|
||||
" Disable the automatic preview delay if vim lacks support for timers
|
||||
if g:mundo_auto_preview_delay > 0 && !s:has_timers
|
||||
let g:mundo_auto_preview_delay = 0
|
||||
call mundo#util#Echo('WarningMsg',
|
||||
\ 'The "g:mundo_auto_preview_delay" option requires'
|
||||
\ .' support for timers. Please upgrade to either vim 8.0+'
|
||||
\ .' (with +timers) or neovim to use this feature. Press '
|
||||
\ .'any key to continue.')
|
||||
|
||||
" Prevent the warning being cleared
|
||||
call getchar()
|
||||
endif
|
||||
|
||||
" Handle normal refresh
|
||||
if g:mundo_auto_preview_delay <= 0
|
||||
call s:MundoPythonRestoreView('MundoRenderGraph()')
|
||||
|
||||
if g:mundo_auto_preview && currentWin == mundoWin && mode() == 'n'
|
||||
call s:MundoRenderPreview()
|
||||
endif
|
||||
return
|
||||
endif
|
||||
|
||||
" Handle delayed refresh
|
||||
call s:MundoRestartRefreshTimer()
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoRestartRefreshTimer()"{{{
|
||||
call s:MundoStopRefreshTimer()
|
||||
let s:auto_preview_timer = timer_start(
|
||||
\ get(g:, 'mundo_auto_preview_delay', 0),
|
||||
\ function('s:MundoRefreshDelayed')
|
||||
\ )
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoStopRefreshTimer()"{{{
|
||||
if s:auto_preview_timer != -1
|
||||
call timer_stop(s:auto_preview_timer)
|
||||
let s:auto_preview_timer = -1
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:MundoRefreshDelayed(...)"{{{
|
||||
" abort if Mundo is closed or cursor is in the preview window
|
||||
let mundoWin = bufwinnr('__Mundo__')
|
||||
let mundoPreWin = bufwinnr('__Mundo_Preview__')
|
||||
let currentWin = bufwinnr('%')
|
||||
|
||||
if mundoWin == -1 || mundoPreWin == -1 || mundoPreWin == currentWin
|
||||
return
|
||||
endif
|
||||
|
||||
" Update graph
|
||||
call s:MundoPythonRestoreView('MundoRenderGraph()')
|
||||
|
||||
" Update preview
|
||||
if currentWin != mundoWin || !g:mundo_auto_preview
|
||||
return
|
||||
endif
|
||||
|
||||
if mode() != 'n'
|
||||
call s:MundoRestartRefreshTimer()
|
||||
return
|
||||
endif
|
||||
|
||||
call s:MundoRenderPreview()
|
||||
endfunction"}}}
|
||||
|
||||
" Mark the preview as being up-to-date (0) or outdated (1)
|
||||
function! mundo#MundoPreviewOutdated(outdated)"{{{
|
||||
if s:preview_outdated && !a:outdated
|
||||
call s:MundoStopRefreshTimer()
|
||||
endif
|
||||
|
||||
let s:preview_outdated = a:outdated
|
||||
endfunction"}}}
|
||||
|
||||
augroup MundoAug
|
||||
autocmd!
|
||||
autocmd BufEnter __Mundo__ call mundo#MundoPreviewOutdated(1)
|
||||
autocmd BufLeave __Mundo__
|
||||
\ if g:mundo_auto_preview |
|
||||
\ call s:MundoRenderPreview() |
|
||||
\ call s:MundoStopRefreshTimer() |
|
||||
\ endif |
|
||||
autocmd BufEnter __Mundo__ call s:MundoSettingsGraph()
|
||||
autocmd BufEnter __Mundo_Preview__ call s:MundoSettingsPreview()
|
||||
autocmd CursorHold,CursorMoved,TextChanged,InsertLeave *
|
||||
\ call s:MundoRefresh()
|
||||
augroup END
|
||||
|
||||
"}}}
|
||||
|
||||
" Exposed functions{{{
|
||||
|
||||
function! mundo#MundoToggle()"{{{
|
||||
call s:MundoToggle()
|
||||
endfunction"}}}
|
||||
|
||||
function! mundo#MundoShow()"{{{
|
||||
call s:MundoShow()
|
||||
endfunction"}}}
|
||||
|
||||
function! mundo#MundoHide()"{{{
|
||||
call s:MundoHide()
|
||||
endfunction"}}}
|
||||
|
||||
"}}}
|
||||
|
||||
let &cpoptions = s:save_cpo
|
||||
unlet s:save_cpo
|
0
bundle/vim-mundo/autoload/mundo/__init__.py
Normal file
0
bundle/vim-mundo/autoload/mundo/__init__.py
Normal file
105
bundle/vim-mundo/autoload/mundo/diff.py
Normal file
105
bundle/vim-mundo/autoload/mundo/diff.py
Normal file
@ -0,0 +1,105 @@
|
||||
import difflib
|
||||
import itertools
|
||||
|
||||
# one line diff functions.
|
||||
def one_line_diff_str(before,after,mx=15,pre=2):
|
||||
"""
|
||||
Return a summary of the differences between two strings, concatenated.
|
||||
|
||||
Parameters:
|
||||
|
||||
before - string before.
|
||||
after - after string.
|
||||
mx - the max number of strings.
|
||||
pre - number of characters to show before diff (context)
|
||||
|
||||
Returns a string no longer than 'mx'.
|
||||
"""
|
||||
old = one_line_diff(before,after)
|
||||
result = ''
|
||||
firstEl = True
|
||||
# TODO instead of using +addition+ and -subtraction- it'd be nice to be able
|
||||
# to highlight the change w/o requiring the +/- chars.
|
||||
for v in old:
|
||||
# if the first element doesn't have a change, then don't include it.
|
||||
v = escape_returns(v)
|
||||
if firstEl:
|
||||
firstEl = False
|
||||
# add in pre character context:
|
||||
if not (v.startswith('+') or v.startswith('-')) and result == '':
|
||||
v = v[-pre:]
|
||||
# when we're going to be bigger than our max limit, lets ensure that the
|
||||
# trailing +/- appears in the text:
|
||||
if len(result) + len(v) > mx:
|
||||
if v.startswith('+') or v.startswith('-'):
|
||||
result += v[:mx - len(result) - 1]
|
||||
result += v[0]
|
||||
break
|
||||
result += v
|
||||
return result
|
||||
|
||||
def escape_returns(result):
|
||||
return result.replace('\n','\\n').replace('\r','\\r').replace('\t','\\t')
|
||||
|
||||
def one_line_diff(before, after):
|
||||
"""
|
||||
Return a summary of the differences between two arbitrary strings.
|
||||
|
||||
Returns a list of strings, summarizing all the changes.
|
||||
"""
|
||||
a, b, result = [], [], []
|
||||
for line in itertools.chain(itertools.islice(
|
||||
difflib.unified_diff(before.splitlines(),
|
||||
after.splitlines()), 2, None), ['@@']):
|
||||
if line.startswith('@@'):
|
||||
result.extend(one_line_diff_raw('\n'.join(a), '\n'.join(b)))
|
||||
a, b = [], []
|
||||
continue
|
||||
if not line.startswith('+'):
|
||||
a.append(line[1:])
|
||||
if not line.startswith('-'):
|
||||
b.append(line[1:])
|
||||
if after.endswith('\n') and not before.endswith('\n'):
|
||||
if result:
|
||||
result[-1] = result[-1][:-1] + '\n+'
|
||||
else:
|
||||
result = ['+\n+']
|
||||
return result
|
||||
|
||||
def one_line_diff_raw(before,after):
|
||||
s = difflib.SequenceMatcher(None,before,after)
|
||||
results = []
|
||||
for tag, i1, i2, j1, j2 in s.get_opcodes():
|
||||
#print ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" % (tag, i1, i2, before[i1:i2], j1, j2, after[j1:j2]))
|
||||
if tag == 'equal':
|
||||
_append_result(results,{
|
||||
'equal': after[j1:j2]
|
||||
})
|
||||
if tag == 'insert':
|
||||
_append_result(results,{
|
||||
'plus': after[j1:j2]
|
||||
})
|
||||
elif tag == 'delete':
|
||||
_append_result(results,{
|
||||
'minus': before[i1:i2]
|
||||
})
|
||||
elif tag == 'replace':
|
||||
_append_result(results,{
|
||||
'minus': before[j1:j2],
|
||||
'plus': after[j1:j2]
|
||||
})
|
||||
final_results = []
|
||||
# finally, create a human readable string of information.
|
||||
for v in results:
|
||||
if 'minus' in v and 'plus' in v and len(v['minus']) > 0 and len(v['plus']) > 0:
|
||||
final_results.append("-%s-+%s+"% (v['minus'],v['plus']))
|
||||
elif 'minus' in v and len(v['minus']) > 0:
|
||||
final_results.append("-%s-"% (v['minus']))
|
||||
elif 'plus' in v and len(v['plus']) > 0:
|
||||
final_results.append("+%s+"% (v['plus']))
|
||||
elif 'equal' in v:
|
||||
final_results.append("%s"% (v['equal']))
|
||||
return final_results
|
||||
|
||||
def _append_result(results,val):
|
||||
results.append(val)
|
248
bundle/vim-mundo/autoload/mundo/graphlog.py
Normal file
248
bundle/vim-mundo/autoload/mundo/graphlog.py
Normal file
@ -0,0 +1,248 @@
|
||||
import time
|
||||
import util
|
||||
|
||||
|
||||
# Mercurial's graphlog code -------------------------------------------------------
|
||||
def asciiedges(seen, rev, parents):
|
||||
"""adds edge info to changelog DAG walk suitable for ascii()"""
|
||||
if rev not in seen:
|
||||
seen.append(rev)
|
||||
nodeidx = seen.index(rev)
|
||||
|
||||
knownparents = []
|
||||
newparents = []
|
||||
for parent in parents:
|
||||
if parent in seen:
|
||||
knownparents.append(parent)
|
||||
else:
|
||||
newparents.append(parent)
|
||||
|
||||
ncols = len(seen)
|
||||
seen[nodeidx:nodeidx + 1] = newparents
|
||||
edges = [(nodeidx, seen.index(p)) for p in knownparents]
|
||||
|
||||
if len(newparents) > 0:
|
||||
edges.append((nodeidx, nodeidx))
|
||||
if len(newparents) > 1:
|
||||
edges.append((nodeidx, nodeidx + 1))
|
||||
|
||||
nmorecols = len(seen) - ncols
|
||||
return nodeidx, edges, ncols, nmorecols
|
||||
|
||||
|
||||
def get_nodeline_edges_tail(
|
||||
node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
|
||||
if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
|
||||
# Still going in the same non-vertical direction.
|
||||
if n_columns_diff == -1:
|
||||
start = max(node_index + 1, p_node_index)
|
||||
tail = ["|", " "] * (start - node_index - 1)
|
||||
tail.extend(["/", " "] * (n_columns - start))
|
||||
return tail
|
||||
else:
|
||||
return ["\\", " "] * (n_columns - node_index - 1)
|
||||
else:
|
||||
return ["|", " "] * (n_columns - node_index - 1)
|
||||
|
||||
|
||||
def draw_edges(edges, nodeline, interline):
|
||||
for (start, end) in edges:
|
||||
if start == end + 1:
|
||||
interline[2 * end + 1] = "/"
|
||||
elif start == end - 1:
|
||||
interline[2 * start + 1] = "\\"
|
||||
elif start == end:
|
||||
interline[2 * start] = "|"
|
||||
else:
|
||||
nodeline[2 * end] = "+"
|
||||
if start > end:
|
||||
(start, end) = (end, start)
|
||||
for i in range(2 * start + 1, 2 * end):
|
||||
if nodeline[i] != "+":
|
||||
nodeline[i] = "-"
|
||||
|
||||
|
||||
def fix_long_right_edges(edges):
|
||||
for (i, (start, end)) in enumerate(edges):
|
||||
if end > start:
|
||||
edges[i] = (start, end + 1)
|
||||
|
||||
|
||||
def ascii(state, type, char, text, coldata, verbose):
|
||||
"""prints an ASCII graph of the DAG
|
||||
|
||||
takes the following arguments (one call per node in the graph):
|
||||
|
||||
- Somewhere to keep the needed state in (init to asciistate())
|
||||
- Column of the current node in the set of ongoing edges.
|
||||
- Type indicator of node data == ASCIIDATA.
|
||||
- Payload: (char, lines):
|
||||
- Character to use as node's symbol.
|
||||
- List of lines to display as the node's text.
|
||||
- Edges; a list of (col, next_col) indicating the edges between
|
||||
the current node and its parents.
|
||||
- Number of columns (ongoing edges) in the current revision.
|
||||
- The difference between the number of columns (ongoing edges)
|
||||
in the next revision and the number of columns (ongoing edges)
|
||||
in the current revision. That is: -1 means one column removed;
|
||||
0 means no columns added or removed; 1 means one column added.
|
||||
- Verbosity: if enabled then the graph prints an extra '|'
|
||||
between each line of information.
|
||||
|
||||
Returns a string representing the output.
|
||||
"""
|
||||
|
||||
idx, edges, ncols, coldiff = coldata
|
||||
assert -2 < coldiff < 2
|
||||
if coldiff == -1:
|
||||
# Transform
|
||||
#
|
||||
# | | | | | |
|
||||
# o | | into o---+
|
||||
# |X / |/ /
|
||||
# | | | |
|
||||
fix_long_right_edges(edges)
|
||||
|
||||
# fix_nodeline_tail says whether to rewrite
|
||||
#
|
||||
# | | o | | | | o | |
|
||||
# | | |/ / | | |/ /
|
||||
# | o | | into | o / / # <--- fixed nodeline tail
|
||||
# | |/ / | |/ /
|
||||
# o | | o | |
|
||||
fix_nodeline_tail = len(text) <= 2
|
||||
|
||||
# nodeline is the line containing the node character (typically o)
|
||||
nodeline = ["|", " "] * idx
|
||||
nodeline.extend([char, " "])
|
||||
|
||||
nodeline.extend(
|
||||
get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
|
||||
state[0], fix_nodeline_tail))
|
||||
|
||||
# shift_interline is the line containing the non-vertical
|
||||
# edges between this entry and the next
|
||||
shift_interline = ["|", " "] * idx
|
||||
if coldiff == -1:
|
||||
n_spaces = 1
|
||||
edge_ch = "/"
|
||||
elif coldiff == 0:
|
||||
n_spaces = 2
|
||||
edge_ch = "|"
|
||||
else:
|
||||
n_spaces = 3
|
||||
edge_ch = "\\"
|
||||
shift_interline.extend(n_spaces * [" "])
|
||||
shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
|
||||
|
||||
# draw edges from the current node to its parents
|
||||
draw_edges(edges, nodeline, shift_interline)
|
||||
|
||||
# lines is the list of all graph lines to print
|
||||
lines = [nodeline]
|
||||
lines.append(shift_interline)
|
||||
|
||||
# make sure that there are as many graph lines as there are
|
||||
# log strings
|
||||
if any("/" in s for s in lines) or verbose:
|
||||
while len(text) < len(lines):
|
||||
text.append('')
|
||||
if len(lines) < len(text):
|
||||
extra_interline = ["|", " "] * (ncols + coldiff)
|
||||
while len(lines) < len(text):
|
||||
lines.append(extra_interline)
|
||||
|
||||
indentation_level = max(ncols, ncols + coldiff)
|
||||
result = []
|
||||
for (line, logstr) in zip(lines, text):
|
||||
graph = "%-*s" % (2 * indentation_level, "".join(line))
|
||||
if not graph.isspace():
|
||||
result.append([graph, logstr])
|
||||
|
||||
# ... and start over
|
||||
state[0] = coldiff
|
||||
state[1] = idx
|
||||
return result
|
||||
|
||||
|
||||
def generate(verbose, num_header_lines, first_visible_line, last_visible_line, inline_graph, nodesData):
|
||||
"""
|
||||
Generate an array of the graph, and text describing the node of the graph.
|
||||
"""
|
||||
seen, state = [], [0, 0]
|
||||
result = []
|
||||
current = nodesData.current()
|
||||
|
||||
nodes, nmap = nodesData.make_nodes()
|
||||
|
||||
for node in nodes:
|
||||
node.children = [n for n in nodes if n.parent == node]
|
||||
|
||||
def walk_nodes(nodes):
|
||||
for node in nodes:
|
||||
if node.parent:
|
||||
yield (node, [node.parent])
|
||||
else:
|
||||
yield (node, [])
|
||||
|
||||
dag = sorted(nodes, key=lambda n: int(n.n), reverse=True)
|
||||
dag = walk_nodes(dag)
|
||||
|
||||
line_number = num_header_lines
|
||||
for idx, part in list(enumerate(dag)):
|
||||
node, parents = part
|
||||
if node.time:
|
||||
age_label = age(int(node.time))
|
||||
else:
|
||||
age_label = 'Original'
|
||||
line = '[%s] %s' % (node.n, age_label)
|
||||
if node.n == current:
|
||||
char = '@'
|
||||
elif node.saved:
|
||||
char = 'w'
|
||||
else:
|
||||
char = 'o'
|
||||
show_inine_diff = inline_graph and line_number >= first_visible_line and line_number <= last_visible_line
|
||||
preview_diff = nodesData.preview_diff(node.parent, node, False, show_inine_diff)
|
||||
line = '[%s] %-10s %s' % (node.n, age_label, preview_diff)
|
||||
new_lines = ascii(state, 'C', char, [line], asciiedges(seen, node, parents), verbose)
|
||||
line_number += len(new_lines)
|
||||
result.extend(new_lines)
|
||||
util._undo_to(current)
|
||||
return result
|
||||
|
||||
# Mercurial age function -----------------------------------------------------------
|
||||
agescales = [("yr", 3600 * 24 * 365),
|
||||
("mon", 3600 * 24 * 30),
|
||||
("wk", 3600 * 24 * 7),
|
||||
("dy", 3600 * 24),
|
||||
("hr", 3600),
|
||||
("min", 60)]
|
||||
|
||||
|
||||
def age(ts):
|
||||
'''turn a timestamp into an age string.'''
|
||||
|
||||
def plural(t, c):
|
||||
if c == 1:
|
||||
return t
|
||||
return t + "s"
|
||||
|
||||
def fmt(t, c):
|
||||
return "%d %s" % (int(c), plural(t, c))
|
||||
|
||||
now = time.time()
|
||||
then = ts
|
||||
if then > now:
|
||||
return 'in the future'
|
||||
|
||||
delta = max(1, int(now - then))
|
||||
if delta > agescales[0][1] * 2:
|
||||
return time.strftime('%Y-%m-%d', time.gmtime(float(ts)))
|
||||
|
||||
for t, s in agescales:
|
||||
n = delta // s
|
||||
if n >= 2 or s == 1:
|
||||
return '%s ago' % fmt(t, n)
|
||||
|
||||
return "<1 min ago"
|
219
bundle/vim-mundo/autoload/mundo/node.py
Normal file
219
bundle/vim-mundo/autoload/mundo/node.py
Normal file
@ -0,0 +1,219 @@
|
||||
import diff
|
||||
import difflib
|
||||
import itertools
|
||||
import time
|
||||
import util
|
||||
|
||||
# Python undo tree data structures and functions ----------------------------------
|
||||
class Node(object):
|
||||
def __init__(self, n, parent, time, curhead, saved):
|
||||
self.n = int(n)
|
||||
self.parent = parent
|
||||
self.children = []
|
||||
self.curhead = curhead
|
||||
self.saved = saved
|
||||
self.time = time
|
||||
|
||||
def __repr__(self):
|
||||
return "[n=%s,parent=%s,time=%s,curhead=%s,saved=%s]" % \
|
||||
(self.n,self.parent,self.time,self.curhead,self.saved)
|
||||
|
||||
class Nodes(object):
|
||||
def __init__(self):
|
||||
self.clear_cache()
|
||||
|
||||
def clear_cache(self):
|
||||
self.changedtick = None
|
||||
self.lines = {}
|
||||
self.nodes_made = None
|
||||
self.target_n = None
|
||||
self.seq_last = None
|
||||
|
||||
self.clear_oneline_diffs()
|
||||
|
||||
def clear_oneline_diffs(self):
|
||||
self.diffs = {}
|
||||
self.diff_has_oneline = {}
|
||||
|
||||
def _validate_cache(self):
|
||||
""" Checks if the targeted buffer number has changed, and if so
|
||||
clears all cached data and stores the new target buffer number.
|
||||
"""
|
||||
target_n = int(util.vim().eval('g:mundo_target_n'))
|
||||
|
||||
if self.target_n != target_n:
|
||||
self.clear_cache()
|
||||
self.clear_oneline_diffs()
|
||||
self.target_n = target_n
|
||||
|
||||
def _make_nodes(self, alts, nodes, parent=None):
|
||||
p = parent
|
||||
|
||||
for alt in alts:
|
||||
if not alt:
|
||||
continue
|
||||
|
||||
curhead = 'curhead' in alt
|
||||
saved = 'save' in alt
|
||||
node = Node(n=alt['seq'], parent=p, time=alt['time'],
|
||||
curhead=curhead, saved=saved)
|
||||
nodes.append(node)
|
||||
|
||||
if alt.get('alt'):
|
||||
self._make_nodes(alt['alt'], nodes, p)
|
||||
|
||||
p = node
|
||||
|
||||
def is_outdated(self):
|
||||
""" Checks if the target buffer undo tree has changed since the last
|
||||
update. Note that this moves to the target buffer.
|
||||
"""
|
||||
util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n')))
|
||||
return self.changedtick != util.vim().eval('b:changedtick')
|
||||
|
||||
def make_nodes(self):
|
||||
# Clear cache if it is invalid
|
||||
self._validate_cache()
|
||||
|
||||
# If the current changedtick is unchanged, we don't need to do
|
||||
# anything:
|
||||
if not self.is_outdated():
|
||||
return self.nodes_made
|
||||
|
||||
ut = util.vim().eval('undotree()')
|
||||
|
||||
# TODO only compute new values (not all values)
|
||||
nodes = []
|
||||
root = Node(0, None, False, 0, 0)
|
||||
self._make_nodes(ut['entries'], nodes, root)
|
||||
nodes.append(root)
|
||||
nmap = dict((node.n, node) for node in nodes)
|
||||
|
||||
# cache values for later use
|
||||
self.seq_last = ut['seq_last']
|
||||
self.nodes_made = (nodes, nmap)
|
||||
self.changedtick = util.vim().eval('b:changedtick')
|
||||
|
||||
return self.nodes_made
|
||||
|
||||
def current(self):
|
||||
""" Return the number of the current change. """
|
||||
self._validate_cache()
|
||||
nodes, nmap = self.make_nodes()
|
||||
_curhead_l = list(itertools.dropwhile(lambda n: not n.curhead, nodes))
|
||||
|
||||
if _curhead_l:
|
||||
current = _curhead_l[0].parent.n
|
||||
else:
|
||||
current = int(util.vim().eval('changenr()'))
|
||||
|
||||
return current
|
||||
|
||||
def _fmt_time(self,t):
|
||||
return time.strftime('%Y-%m-%d %I:%M:%S %p', time.localtime(float(t)))
|
||||
|
||||
def _get_lines(self,node):
|
||||
n = 0
|
||||
|
||||
if node:
|
||||
n = node.n
|
||||
if n not in self.lines:
|
||||
util._undo_to(n)
|
||||
self.lines[n] = util.vim().current.buffer[:]
|
||||
|
||||
return self.lines[n]
|
||||
|
||||
def change_preview_diff(self, before, after):
|
||||
self._validate_cache()
|
||||
key = "%s-%s-cpd"%(before.n,after.n)
|
||||
|
||||
if key in self.diffs:
|
||||
return self.diffs[key]
|
||||
|
||||
util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n')))
|
||||
before_lines = self._get_lines(before)
|
||||
after_lines = self._get_lines(after)
|
||||
|
||||
before_name = str(before.n or 'Original')
|
||||
before_time = before.time and self._fmt_time(before.time) or ''
|
||||
after_name = str(after.n or 'Original')
|
||||
after_time = after.time and self._fmt_time(after.time) or ''
|
||||
|
||||
util._undo_to(self.current())
|
||||
|
||||
self.diffs[key] = list(difflib.unified_diff(before_lines, after_lines,
|
||||
before_name, after_name,
|
||||
before_time, after_time))
|
||||
return self.diffs[key]
|
||||
|
||||
def preview_diff(self, before, after, unified=True, inline=False):
|
||||
"""
|
||||
Generate a diff comparing two versions of a file.
|
||||
|
||||
Parameters:
|
||||
|
||||
current - ?
|
||||
before
|
||||
after
|
||||
unified - If True, generate a unified diff
|
||||
inline - Generate a one line summary line.
|
||||
"""
|
||||
self._validate_cache()
|
||||
|
||||
bn = 0
|
||||
an = 0
|
||||
|
||||
if not after.n: # we're at the original file
|
||||
pass
|
||||
elif not before.n: # we're at a pseudo-root state
|
||||
an = after.n
|
||||
else:
|
||||
bn = before.n
|
||||
an = after.n
|
||||
|
||||
key = "%s-%s-pd-%s"%(bn,an,unified)
|
||||
needs_oneline = inline and key not in self.diff_has_oneline
|
||||
|
||||
if key in self.diffs and not needs_oneline:
|
||||
return self.diffs[key]
|
||||
|
||||
if not after.n: # we're at the original file
|
||||
before_lines = []
|
||||
after_lines = self._get_lines(None)
|
||||
|
||||
before_name = 'n/a'
|
||||
before_time = ''
|
||||
after_name = 'Original'
|
||||
after_time = ''
|
||||
elif not before.n: # we're at a pseudo-root state
|
||||
before_lines = self._get_lines(None)
|
||||
after_lines = self._get_lines(after)
|
||||
|
||||
before_name = 'Original'
|
||||
before_time = ''
|
||||
after_name = str(after.n)
|
||||
after_time = self._fmt_time(after.time)
|
||||
else:
|
||||
before_lines = self._get_lines(before)
|
||||
after_lines = self._get_lines(after)
|
||||
|
||||
before_name = str(before.n)
|
||||
before_time = self._fmt_time(before.time)
|
||||
after_name = str(after.n)
|
||||
after_time = self._fmt_time(after.time)
|
||||
|
||||
if unified:
|
||||
self.diffs[key] = list(
|
||||
difflib.unified_diff(before_lines, after_lines, before_name,
|
||||
after_name, before_time, after_time)
|
||||
)
|
||||
elif inline:
|
||||
maxwidth = int(util.vim().eval("winwidth(0)"))
|
||||
self.diffs[key] = diff.one_line_diff_str(
|
||||
'\n'.join(before_lines),'\n'.join(after_lines), maxwidth
|
||||
)
|
||||
self.diff_has_oneline[key] = True
|
||||
else:
|
||||
self.diffs[key] = ""
|
||||
|
||||
return self.diffs[key]
|
50
bundle/vim-mundo/autoload/mundo/util.py
Normal file
50
bundle/vim-mundo/autoload/mundo/util.py
Normal file
@ -0,0 +1,50 @@
|
||||
# import vim
|
||||
|
||||
normal = lambda s: vim().command('normal %s' % s)
|
||||
normal_silent = lambda s: vim().command('silent! normal %s' % s)
|
||||
|
||||
|
||||
def vim():
|
||||
""" call Vim.
|
||||
|
||||
This is wrapped so that it can easily be mocked.
|
||||
"""
|
||||
import vim
|
||||
return vim
|
||||
|
||||
def _goto_window_for_buffer(expr):
|
||||
""" Moves the cursor to the first window associated with buffer b in the
|
||||
current tab page (only).
|
||||
|
||||
Arguments
|
||||
---------
|
||||
expr : int or str
|
||||
The target buffer - either a buffer number (int) or a file-pattern
|
||||
(str). See :h bufwinnr for a more detailed description.
|
||||
"""
|
||||
if not isinstance(expr, int) and not isinstance(expr, str):
|
||||
raise TypeError('b has invalid type, str or int expected.')
|
||||
|
||||
if isinstance(expr, str):
|
||||
expr = "'{0}'".format(expr)
|
||||
|
||||
winnr = int(vim().eval('bufwinnr({0})'.format(expr)))
|
||||
assert winnr != -1
|
||||
vim().command('%dwincmd w' % int(winnr))
|
||||
|
||||
|
||||
# Rendering utility functions
|
||||
def _output_preview_text(lines):
|
||||
""" Output a list of lines to the mundo preview window. """
|
||||
_goto_window_for_buffer('__Mundo_Preview__')
|
||||
vim().command('setlocal modifiable')
|
||||
vim().current.buffer[:] = [line.rstrip() for line in lines]
|
||||
vim().command('setlocal nomodifiable')
|
||||
|
||||
|
||||
def _undo_to(n):
|
||||
n = int(n)
|
||||
if n == 0:
|
||||
vim().command('silent earlier %s' % (int(vim().eval('&undolevels')) + 1))
|
||||
else:
|
||||
vim().command('silent undo %d' % int(n))
|
116
bundle/vim-mundo/autoload/mundo/util.vim
Normal file
116
bundle/vim-mundo/autoload/mundo/util.vim
Normal file
@ -0,0 +1,116 @@
|
||||
" ============================================================================
|
||||
" File: util.vim
|
||||
" Description: Defines utility functions and default option values for Mundo.
|
||||
" Maintainer: Hyeon Kim <simnalamburt@gmail.com>
|
||||
" License: GPLv2+
|
||||
" ============================================================================
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
if exists('g:Mundo_PluginLoaded')
|
||||
let &cpo = s:save_cpo
|
||||
finish
|
||||
endif
|
||||
|
||||
" Utility functions{{{
|
||||
|
||||
" Moves to the first window in the current tab corresponding to expr. Accepts
|
||||
" an integer buffer number or a string file-pattern; for a detailed description
|
||||
" see :h bufname. Returns 1 if successful, 0 otherwise.
|
||||
function! mundo#util#GoToBuffer(expr)"{{{
|
||||
let l:winnr = bufwinnr(bufnr(a:expr))
|
||||
|
||||
if l:winnr == -1
|
||||
return 0
|
||||
elseif l:winnr != winnr()
|
||||
exe l:winnr . "wincmd w"
|
||||
endif
|
||||
|
||||
return 1
|
||||
endfunction"}}}
|
||||
|
||||
" Similar to MundoGoToBuffer, but considers windows in all tabs.
|
||||
" Prioritises matches in the current tab.
|
||||
function! mundo#util#GoToBufferGlobal(expr)"{{{
|
||||
if mundo#util#GoToBuffer(a:expr)
|
||||
return 1
|
||||
endif
|
||||
|
||||
let l:bufWinIDs = win_findbuf(bufnr(a:expr))
|
||||
|
||||
if len(l:bufWinIDs) <= 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
call win_gotoid(l:bufWinIDs[0])
|
||||
return 1
|
||||
endfunction"}}}
|
||||
|
||||
" Prints a highlighted string.
|
||||
function! mundo#util#Echo(higroup, text)"{{{
|
||||
execute 'echohl ' . a:higroup
|
||||
execute 'unsilent echomsg ' . '"' . escape(a:text, '"') . '"'
|
||||
echohl None
|
||||
endfunction"}}}
|
||||
|
||||
" Set var to val only if var has not been set by the user. Optionally takes a
|
||||
" deprecated option name and shows a warning if a variable with this name exists.
|
||||
function! mundo#util#set_default(var, val, ...)"{{{
|
||||
if !exists(a:var)
|
||||
let {a:var} = a:val
|
||||
return 1
|
||||
endif
|
||||
|
||||
let old_var = get(a:000, 0, '')
|
||||
|
||||
if exists(old_var)
|
||||
call mundo#util#Echo(
|
||||
\ 'WarningMsg',
|
||||
\ "{".old_var."}is deprecated! "
|
||||
\ ."Please change your setting to {"
|
||||
\ .split(old_var,':')[0]
|
||||
\ .':'
|
||||
\ .substitute(split(old_var,':')[1],'gundo_','mundo_','g')
|
||||
\ .'}'
|
||||
)
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
"}}}
|
||||
|
||||
"}}}
|
||||
|
||||
" Placeholder functions for deprecated Gundo commands{{{
|
||||
|
||||
function! mundo#util#Toggle()
|
||||
return mundo#util#Echo('WarningMsg', 'GundoToggle commands are '
|
||||
\ . 'deprecated. Please change to their corresponding '
|
||||
\ . 'MundoToggle command.')
|
||||
endf
|
||||
|
||||
function! mundo#util#Show()
|
||||
return mundo#util#Echo('WarningMsg', 'GundoToggle commands are '
|
||||
\ . 'deprecated. Please change to their corresponding '
|
||||
\ . 'MundoShow command.')
|
||||
endf
|
||||
|
||||
function! mundo#util#Hide()
|
||||
return mundo#util#Echo('WarningMsg', 'GundoToggle commands are '
|
||||
\ . 'deprecated. Please change to their corresponding '
|
||||
\ . 'MundoHide command.')
|
||||
endf
|
||||
|
||||
function! mundo#util#RenderGraph()
|
||||
return mundo#util#Echo('WarningMsg', 'GundoToggle commands are '
|
||||
\ . 'deprecated. Please change to their corresponding '
|
||||
\ . 'MundoRenderGraph command.')
|
||||
endf
|
||||
|
||||
"}}}
|
||||
|
||||
let g:Mundo_PluginLoaded = 1
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
23
bundle/vim-mundo/autoload/utils_test.py
Normal file
23
bundle/vim-mundo/autoload/utils_test.py
Normal file
@ -0,0 +1,23 @@
|
||||
import nose
|
||||
from nose.tools import *
|
||||
import mundo.diff as difflib
|
||||
|
||||
def test_one_line_diff():
|
||||
eq_(difflib.one_line_diff('', ''), [])
|
||||
eq_(difflib.one_line_diff('', 'a'), ['+a+'])
|
||||
eq_(difflib.one_line_diff('a', 'b'), ['-a-+b+'])
|
||||
eq_(difflib.one_line_diff('', 'a\nb\nc\n'), ['+a\nb\nc\n+'])
|
||||
eq_(difflib.one_line_diff('one\ntwo', 'two\nthree'), ['-one\n-', 'two', '+\nthree+'])
|
||||
eq_(difflib.one_line_diff('b\nd\ne\nf', 'm\nn\no\np\n'), ['-b-+m+', '\n', '-d-+n+', '\n', '-e-+o+', '\n', '-f-+p\n+'])
|
||||
eq_(difflib.one_line_diff('m\nd\ne\nf', 'moon\nn\no\np\n'), ['m', '+oon+', '\n', '-\n-+n+', '\n', '+o+', '\n', '+p\n+'])
|
||||
eq_(difflib.one_line_diff('m\nbagman', 'm\nbadger'), ['m\nba', '+d+', 'g', '-an-+er+'])
|
||||
eq_(difflib.one_line_diff('', '1234567890abcdefghij'), ['+1234567890abcdefghij+'])
|
||||
|
||||
def test_one_line_diff_str():
|
||||
eq_(difflib.one_line_diff_str('', ''), '')
|
||||
eq_(difflib.one_line_diff_str('one\ntwo', 'two\nthree'), '-one\\n-two+\\nt+')
|
||||
eq_(difflib.one_line_diff_str('m\nd\ne\nf', 'moon\nn\no\np\n'), 'm+oon+\\n-\\n-+n+')
|
||||
eq_(difflib.one_line_diff_str('m\nbagman', 'm\nbadger'), 'ba+d+g-an-+er+')
|
||||
# when the '+' is over the cuttoff, it should be appended:
|
||||
eq_(difflib.one_line_diff_str('', '1234567890abcdefghij'), '+1234567890abc+')
|
||||
eq_(difflib.one_line_diff_str('one\n\ntwo', 'one\n\ntwo\n\nthree\n\nfour'), 'wo+\\n\\nthree\\n+')
|
419
bundle/vim-mundo/doc/mundo.txt
Normal file
419
bundle/vim-mundo/doc/mundo.txt
Normal file
@ -0,0 +1,419 @@
|
||||
*mundo.txt* Graph your undo tree so you can actually USE it.
|
||||
|
||||
Making Vim's undo tree usable by humans.
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *Mundo-contents*
|
||||
|
||||
1. Intro ........................... |MundoIntro|
|
||||
2. Usage ........................... |MundoUsage|
|
||||
3. Configuration ................... |MundoConfig|
|
||||
3.1 mundo_width ............... |mundo_width|
|
||||
3.2 mundo_preview_height ...... |mundo_preview_height|
|
||||
3.3 mundo_preview_bottom ...... |mundo_preview_bottom|
|
||||
3.4 mundo_right ............... |mundo_right|
|
||||
3.5 mundo_help ................ |mundo_help|
|
||||
3.6 mundo_disable ............. |mundo_disable|
|
||||
3.7 mundo_mappings ............ |mundo_mappings|
|
||||
3.8 mundo_close_on_revert ..... |mundo_close_on_revert|
|
||||
3.9 mundo_preview_statusline .. |mundo_preview_statusline|
|
||||
mundo_tree_statusline ..... |mundo_tree_statusline|
|
||||
3.10 mundo_auto_preview ........ |mundo_auto_preview|
|
||||
3.11 mundo_auto_preview_delay .. |mundo_auto_preview_delay|
|
||||
3.12 mundo_verbose_graph ....... |mundo_verbose_graph|
|
||||
3.13 mundo_playback_delay ...... |mundo_playback_delay|
|
||||
3.14 mundo_mirror_graph ........ |mundo_mirror_graph|
|
||||
3.15 mundo_inline_undo ......... |mundo_inline_undo|
|
||||
3.16 mundo_return_on_revert .... |mundo_return_on_revert|
|
||||
3.17 mundo_header .............. |mundo_header|
|
||||
4. License ......................... |MundoLicense|
|
||||
5. Bugs ............................ |MundoBugs|
|
||||
6. Contributing .................... |MundoContributing|
|
||||
7. Changelog ....................... |MundoChangelog|
|
||||
8. Credits ......................... |MundoCredits|
|
||||
|
||||
==============================================================================
|
||||
1. Intro *MundoIntro*
|
||||
|
||||
You know that Vim lets you undo changes like any text editor. What you might
|
||||
not know is that it doesn't just keep a list of your changes -- it keeps
|
||||
a goddamed |:undo-tree| of them.
|
||||
|
||||
Say you make a change (call it X), undo that change, and then make another
|
||||
change (call it Y). With most editors, change X is now gone forever. With Vim
|
||||
you can get it back.
|
||||
|
||||
The problem is that trying to do this in the real world is painful. Vim gives
|
||||
you an |:undolist| command that shows you the leaves of the tree. Good luck
|
||||
finding the change you want in that list.
|
||||
|
||||
Mundo is a plugin to make browsing this ridiculously powerful undo tree less
|
||||
painful.
|
||||
|
||||
==============================================================================
|
||||
2. Usage *MundoUsage*
|
||||
|
||||
We'll get to the technical details later, but if you're a human the first
|
||||
thing you need to do is add a mapping to your |:vimrc| to toggle the undo
|
||||
graph: >
|
||||
|
||||
nnoremap <F5> :MundoToggle<CR>
|
||||
|
||||
Change the mapped key to suit your taste. We'll stick with F5 because that's
|
||||
what the author uses.
|
||||
|
||||
Now you can press F5 to toggle the undo graph and preview pane, which will
|
||||
look something like this: >
|
||||
|
||||
Undo graph File
|
||||
+-----------------------------------+------------------------------------+
|
||||
| " Mundo for something.txt [1] |one |
|
||||
| " j/k - move between undo states |two |
|
||||
| " <cr> - revert to that state |three |
|
||||
| |five |
|
||||
| @ [5] 3 hours ago | |
|
||||
| | | |
|
||||
| | o [4] 4 hours ago | |
|
||||
| | | | |
|
||||
| o | [3] 4 hours ago | |
|
||||
| | | | |
|
||||
| w | [2] 4 hours ago | |
|
||||
| |/ | |
|
||||
| o [1] 4 hours ago | |
|
||||
| | | |
|
||||
| o [0] Original | |
|
||||
+-----------------------------------+ |
|
||||
| --- 3 2010-10-12 06:27:35 PM | |
|
||||
| +++ 5 2010-10-12 07:38:37 PM | |
|
||||
| @@ -1,3 +1,4 | |
|
||||
| one | |
|
||||
| two | |
|
||||
| three | |
|
||||
| +five | |
|
||||
+-----------------------------------+------------------------------------+
|
||||
Preview pane
|
||||
|
||||
Your current position in the undo tree is marked with an '@' character. Undo
|
||||
positions that were saved to disk are marked with a 'w'. Other nodes are marked
|
||||
with an 'o' character.
|
||||
|
||||
When you toggle open the graph Mundo will put your cursor on your current
|
||||
position in the tree. You can move up and down the graph with the j and
|
||||
k keys.
|
||||
|
||||
You can move to the top of the graph (the newest state) with gg and to the
|
||||
bottom of the graph (the oldest state) with G.
|
||||
|
||||
As you move between undo states the preview pane will show you a unified diff
|
||||
of the change that state made.
|
||||
|
||||
Pressing enter on a state (or double clicking on it) will revert the contents
|
||||
of the file to match that state.
|
||||
|
||||
You can use p on a state to make the preview window show the diff between
|
||||
your current state and the selected state, instead of a preview of what the
|
||||
selected state changed.
|
||||
|
||||
Pressing P while on a state will initiate "play to" mode targeted at that
|
||||
state. This will replay all the changes between your current state and the
|
||||
target, with a slight pause after each change. It's mostly useless, but can be
|
||||
fun to watch and see where your editing lags -- that might be a good place to
|
||||
define a new mapping to speed up your editing.
|
||||
|
||||
Pressing q while in the undo graph will close it. You can also just press your
|
||||
toggle mapping key.
|
||||
|
||||
==============================================================================
|
||||
3. Configuration *MundoConfig*
|
||||
|
||||
You can tweak the behavior of Mundo by setting a few variables in your :vimrc
|
||||
file. For example: >
|
||||
|
||||
let g:mundo_width = 60
|
||||
let g:mundo_preview_height = 40
|
||||
let g:mundo_right = 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.1 g:mundo_width *mundo_width*
|
||||
|
||||
Set the horizontal width of the Mundo graph (and preview).
|
||||
|
||||
Default: 45
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.2 g:mundo_preview_height *mundo_preview_height*
|
||||
|
||||
Set the vertical height of the Mundo preview.
|
||||
|
||||
Default: 15
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.3 g:mundo_preview_bottom *mundo_preview_bottom*
|
||||
|
||||
Force the preview window below current windows instead of below the graph.
|
||||
This gives the preview window more space to show the unified diff.
|
||||
|
||||
Example:
|
||||
|
||||
+--------+ +--------+
|
||||
!g! ! ! !g!
|
||||
!g! ! or ! !g!
|
||||
!g!______! !______!g!
|
||||
!g!pppppp! !pppppp!g!
|
||||
+--------+ +--------+
|
||||
|
||||
Default: 0
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.4 g:mundo_right *mundo_right*
|
||||
|
||||
Set this to 1 to make the Mundo graph (and preview) open on the right side
|
||||
instead of the left.
|
||||
|
||||
Default: 0 (off, open on the left side)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.5 g:mundo_help *mundo_help*
|
||||
|
||||
Set this to 1 to make help text expanded by default.
|
||||
|
||||
Default: 0 (non-expanded help)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.6 g:mundo_disable *mundo_disable*
|
||||
|
||||
Set this to 1 to disable Mundo entirely.
|
||||
|
||||
Useful if you use the same ~/.vim folder on multiple machines, and some of
|
||||
them may not have Python support.
|
||||
|
||||
Default: 0 (Mundo is enabled as usual)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.7 g:mundo_mappings *mundo_mappings*
|
||||
*mundo_map_move_older*
|
||||
*mundo_map_move_newer*
|
||||
*mundo_map_up_down*
|
||||
|
||||
To override any mappings within mundo set the value of the normal mode keys you
|
||||
would like to use instead (copy the defaults below and adjust as preferred)
|
||||
|
||||
Note: mundo_map_move_older, mundo_map_move_newer, mundo_map_up_down options have
|
||||
been deprecated in favor of settings here. Although they continue to work, they
|
||||
will eventually be removed!
|
||||
|
||||
Defaults:
|
||||
|
||||
let g:mundo_mappings = {
|
||||
\ '<CR>': 'preview',
|
||||
\ 'o': 'preview',
|
||||
\ 'j': 'move_older',
|
||||
\ 'k': 'move_newer',
|
||||
\ '<down>': 'move_older',
|
||||
\ '<up>': 'move_newer',
|
||||
\ 'J': 'move_older_write',
|
||||
\ 'K': 'move_newer_write',
|
||||
\ 'gg': 'move_top',
|
||||
\ 'G': 'move_bottom',
|
||||
\ 'P': 'play_to',
|
||||
\ 'd': 'diff',
|
||||
\ 'i': 'toggle_inline',
|
||||
\ '/': 'search',
|
||||
\ 'n': 'next_match',
|
||||
\ 'N': 'previous_match',
|
||||
\ 'p': 'diff_current_buffer',
|
||||
\ 'r': 'diff',
|
||||
\ '?': 'toggle_help',
|
||||
\ 'q': 'quit',
|
||||
\ '<2-LeftMouse>': 'mouse_click' }
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.8 g:mundo_close_on_revert *mundo_close_on_revert*
|
||||
|
||||
Set this to 1 to automatically close the Mundo windows when reverting.
|
||||
|
||||
Default: 0 (windows do not automatically close)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.9 g:mundo_preview_statusline *mundo_preview_statusline*
|
||||
g:mundo_tree_statusline *mundo_tree_statusline*
|
||||
|
||||
Set these to a string to display it as the status line for each Mundo window.
|
||||
|
||||
Default: unset (windows use the default statusline)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.10 g:mundo_auto_preview *mundo_auto_preview*
|
||||
|
||||
Set this to 0 to disable automatically rendering preview diffs as you move
|
||||
through the undo tree (you can still render a specific diff with r). This can
|
||||
be useful on large files and undo trees to speed up Mundo.
|
||||
|
||||
Default: 1 (automatically preview diffs)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
3.11 g:mundo_auto_preview_delay *mundo_auto_preview_delay*
|
||||
|
||||
This is the delay in milliseconds before a preview diff is automatically
|
||||
rendered. The delay is reset whenever the cursor moves. Use this to speed up
|
||||
undo tree traversal when automatic previews are enabled. Set this to 0 to
|
||||
disable the feature.
|
||||
|
||||
Default: 250
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.12 g:mundo_verbose_graph *mundo_verbose_graph*
|
||||
|
||||
Set this to 0 to create shorter graphs: the 'o' characters will only be used
|
||||
when multiple branches exist, and extra lines of '|' are suppressed making for
|
||||
a graph half as long.
|
||||
|
||||
Default: 1 (verbose graphs)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.13 g:mundo_playback_delay *mundo_playback_delay*
|
||||
|
||||
This is the delay in milliseconds between each change when running 'play to'
|
||||
mode. Set this to a higher number for a slower playback or to a lower number
|
||||
for a faster playback.
|
||||
|
||||
Default: 60
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.14 g:mundo_mirror_graph *mundo_mirror_graph*
|
||||
|
||||
Set this to 0 to align the graph to the left; set to 1 to align to the right.
|
||||
|
||||
Default: 1 (mirror graph)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.15 g:mundo_inline_undo *mundo_inline_undo*
|
||||
|
||||
When enabled, a small one line diff is displayed to the right of the graph
|
||||
undo. Although not as detailed as a full diff provided in the preview window,
|
||||
it provides a quick summary of the diff w/o having to navigate.
|
||||
|
||||
Default: 0 (no inline graph)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.16 g:mundo_return_on_revert *mundo_return_on_revert*
|
||||
|
||||
Set this to 0 to keep focus in the Mundo window after a revert.
|
||||
|
||||
Default: 1
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
3.17 g:mundo_header *mundo_header*
|
||||
|
||||
Set this to 0 to hide the mundo header.
|
||||
|
||||
Default: 1 (display mundo header)
|
||||
|
||||
==============================================================================
|
||||
4. License *MundoLicense*
|
||||
|
||||
GPLv2+. Look it up.
|
||||
|
||||
==============================================================================
|
||||
5. Bugs *MundoBugs*
|
||||
|
||||
If you find a bug please post it on the issue tracker:
|
||||
|
||||
https://github.com/simnalamburt/vim-mundo/issues
|
||||
|
||||
==============================================================================
|
||||
6. Contributing *MundoContributing*
|
||||
|
||||
Think you can make this plugin better? Awesome. Fork it on BitBucket or GitHub
|
||||
and send a pull request.
|
||||
|
||||
Version numbers should roughly follow Semantic Versioning.
|
||||
|
||||
GitHub: https://github.com/simnalamburt/vim-mundo
|
||||
|
||||
==============================================================================
|
||||
7. Changelog *MundoChangelog*
|
||||
|
||||
|
||||
v3.2.0
|
||||
* Adds g:mundo_mappings setting.
|
||||
* Deprecates g:mundo_map_move_older, g:mundo_map_move_newer, g:mundo_map_up_down
|
||||
v3.1.0
|
||||
* Adds g:mundo_map_up_down setting.
|
||||
* Adds g:mundo_auto_preview_delay setting.
|
||||
* Adds validation for target buffers.
|
||||
* Adds 'G' mapping to graph.
|
||||
* Fix a runtime error when entering embedded terminal windows in neovim.
|
||||
* Fix multiple issues associated with Mundo windows in different tabs.
|
||||
* Fix default option values overriding user-set values in certain cases.
|
||||
* Fix cursor initially being positioned above the graph.
|
||||
* Fix some mappings not working correctly when preceded with a count.
|
||||
* Fix some graph mappings moving the cursor to the target buffer.
|
||||
* Fix airline plugin ignoring custom status lines.
|
||||
* Fix Escape and Ctrl+c not being handled correctly in the search prompt.
|
||||
* Fix MundoGetTargetState returning invalid results with some inline diffs.
|
||||
* Reduced delay associated with animated playback for neovim.
|
||||
* Code cleanup and refactoring.
|
||||
v3.0.1
|
||||
* Made inline diff mode much faster(e.g. 300x)
|
||||
* Fix inline diffs not updating after scroll.
|
||||
* Fix help toggle mode.
|
||||
v3.0.0
|
||||
* Rename plugin
|
||||
* Add one line diff in __Mundo__ window.
|
||||
* Adds g:mundo_mirror_graph setting.
|
||||
* Adds g:mundo_return_on_revert setting.
|
||||
* Adds ability to toggle help on/off in __Mundo__ window.
|
||||
* Adds J and K commands (navigate between written undos)
|
||||
* Adds /, n and N commands (search undos)
|
||||
* Adds g:mundo_verbose_graph setting.
|
||||
* Adds g:mundo_mirror_graph setting.
|
||||
* Show written undos in the Mundo graph.
|
||||
* Adds live reload of Mundo as you edit.
|
||||
v2.5.0
|
||||
* Fix the help window to take custom mappings into account.
|
||||
* Add g:mundo_playback_delay option.
|
||||
v2.4.0
|
||||
* Add auto preview option.
|
||||
* Add 'r' mapping to preview current state.
|
||||
* Add public mundo#MundoShow() and mundo#MundoHide() functions.
|
||||
v2.3.0
|
||||
* Add statusline configuration.
|
||||
v2.2.2
|
||||
* More performance improvements.
|
||||
v2.2.1
|
||||
* Refactoring and performance improvements.
|
||||
v2.2.0
|
||||
* Add the g:mundo_close_on_revert setting.
|
||||
* Fix a bug with the splitbelow setting.
|
||||
v2.1.1
|
||||
* Fix a bug with the movement key mappings.
|
||||
* Warnings about having an incompatible Vim and/or Python installation
|
||||
v2.1.0
|
||||
are now deferred until the first time you try to use Mundo, instead
|
||||
of being displayed on launch.
|
||||
* The <j> and <k> mappings are now configurable with
|
||||
g:mundo_map_move_older and g:mundo_map_move_newer.
|
||||
* The o, <Up> and <Down> keys are now mapped in the Mundo pane.
|
||||
* Improve and add several unit tests for Mundo.
|
||||
v2.0.0
|
||||
* Make MundoToggle close the Mundo windows if they're visible but not the
|
||||
current window, instead of moving to them.
|
||||
* Add the g:mundo_help setting.
|
||||
* Add the g:mundo_disable setting.
|
||||
* Add the 'p' mapping to preview the result of reverting to the selected
|
||||
state.
|
||||
* Fix movement commands with counts in the graph.
|
||||
v1.0.0
|
||||
* Initial stable release.
|
||||
|
||||
==============================================================================
|
||||
8. Credits *MundoCredits*
|
||||
|
||||
The graphing code was all taken from Mercurial, hence the GPLv2+ license.
|
||||
|
||||
The plugin was heavily inspired by histwin.vim, and the code for scratch.vim
|
||||
helped the author get started.
|
||||
|
||||
==============================================================================
|
140
bundle/vim-mundo/plugin/mundo.vim
Normal file
140
bundle/vim-mundo/plugin/mundo.vim
Normal file
@ -0,0 +1,140 @@
|
||||
" ============================================================================
|
||||
" File: mundo.vim
|
||||
" Description: vim global plugin to visualize your undo tree
|
||||
" Maintainer: Hyeon Kim <simnalamburt@gmail.com>
|
||||
" License: GPLv2+ -- look it up.
|
||||
" Notes: Much of this code was thiefed from Mercurial, and the rest was
|
||||
" heavily inspired by scratch.vim and histwin.vim.
|
||||
"
|
||||
" ============================================================================
|
||||
|
||||
if !exists('g:mundo_debug') && (exists('g:mundo_disable') &&
|
||||
\ g:mundo_disable == 1 || exists('loaded_mundo') || &cp)"{{{
|
||||
finish
|
||||
endif
|
||||
|
||||
let loaded_mundo = 1"}}}
|
||||
|
||||
" Default option values{{{
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_auto_preview', 1,
|
||||
\ 'g:gundo_auto_preview')
|
||||
|
||||
call mundo#util#set_default('g:mundo_auto_preview_delay', 250)
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_close_on_revert', 0,
|
||||
\ 'g:gundo_close_on_revert')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_first_visible_line', 0,
|
||||
\ 'g:gundo_first_visible_line')
|
||||
|
||||
call mundo#util#set_default('g:mundo_header', 1)
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_help', 0,
|
||||
\ 'g:gundo_help')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_inline_undo', 0,
|
||||
\ 'g:gundo_inline_undo')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_last_visible_line', 0,
|
||||
\ 'g:gundo_last_visible_line')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_map_move_newer', 'k',
|
||||
\ 'g:gundo_map_move_newer')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_map_move_older', 'j',
|
||||
\ 'g:gundo_map_move_older')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_map_up_down', 1,
|
||||
\ 'g:gundo_map_up_down')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_mirror_graph', 0,
|
||||
\ 'g:gundo_mirror_graph')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_playback_delay', 60,
|
||||
\ 'g:gundo_playback_delay')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_prefer_python3', 0,
|
||||
\ 'g:gundo_prefer_python3')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_preview_bottom', 0,
|
||||
\ 'g:gundo_preview_bottom')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_preview_height', 15,
|
||||
\ 'g:gundo_preview_height')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_python_path_setup', 0,
|
||||
\ 'g:gundo_python_path_setup')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_return_on_revert', 1,
|
||||
\ 'g:gundo_return_on_revert')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_right', 0,
|
||||
\ 'g:gundo_right')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_verbose_graph', 1,
|
||||
\ 'g:gundo_verbose_graph')
|
||||
|
||||
call mundo#util#set_default(
|
||||
\ 'g:mundo_width', 45,
|
||||
\ 'g:gundo_width')
|
||||
|
||||
" Set up the default mappings, unless a g:mundo_mappings has already been
|
||||
" provided
|
||||
if mundo#util#set_default('g:mundo_mappings', {})
|
||||
let g:mundo_mappings = {
|
||||
\ '<CR>': 'preview',
|
||||
\ 'o': 'preview',
|
||||
\ 'J': 'move_older_write',
|
||||
\ 'K': 'move_newer_write',
|
||||
\ 'gg': 'move_top',
|
||||
\ 'G': 'move_bottom',
|
||||
\ 'P': 'play_to',
|
||||
\ 'd': 'diff',
|
||||
\ 'i': 'toggle_inline',
|
||||
\ '/': 'search',
|
||||
\ 'n': 'next_match',
|
||||
\ 'N': 'previous_match',
|
||||
\ 'p': 'diff_current_buffer',
|
||||
\ 'r': 'diff',
|
||||
\ '?': 'toggle_help',
|
||||
\ 'q': 'quit',
|
||||
\ '<2-LeftMouse>': 'mouse_click' }
|
||||
let g:mundo_mappings[g:mundo_map_move_older] = 'move_older'
|
||||
let g:mundo_mappings[g:mundo_map_move_newer] = 'move_newer'
|
||||
if g:mundo_map_up_down
|
||||
let g:mundo_mappings['<down>'] = 'move_older'
|
||||
let g:mundo_mappings['<up>'] = 'move_newer'
|
||||
endif
|
||||
endif
|
||||
"}}}
|
||||
|
||||
"{{{ Create commands
|
||||
|
||||
command! -nargs=0 MundoToggle call mundo#MundoToggle()
|
||||
command! -nargs=0 MundoShow call mundo#MundoShow()
|
||||
command! -nargs=0 MundoHide call mundo#MundoHide()
|
||||
command! -nargs=0 GundoToggle call mundo#util#MundoToggle()
|
||||
command! -nargs=0 GundoShow call mundo#util#MundoShow()
|
||||
command! -nargs=0 GundoHide call mundo#util#MundoHide()
|
||||
command! -nargs=0 GundoRenderGraph call mundo#util#MundoRenderGraph()
|
||||
|
||||
"}}}
|
2
bundle/vim-mundo/requirements.txt
Normal file
2
bundle/vim-mundo/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
nose
|
||||
mock
|
24
bundle/vim-mundo/tests/README.md
Normal file
24
bundle/vim-mundo/tests/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
Mundo Tests
|
||||
========
|
||||
This is Mundo's test suite. In case you didn't know, unit testing vim plugins
|
||||
is a horrible experience.
|
||||
|
||||
Mundo bundles Luc Hermitte's [UT] framework to make the process less painful.
|
||||
|
||||
[UT]: https://github.com/LucHermitte/vim-UT
|
||||
|
||||
To run a test, `cd` into the `tests` directory and use:
|
||||
|
||||
```sh
|
||||
./run-tests.sh [[some-test.vim] ...]
|
||||
```
|
||||
|
||||
The script will run the console vim command with its own vimrc and .vim
|
||||
directory, so none of your other plugins should interfere. The result of the
|
||||
tests will be shown in the quickfix window of this vim instance.
|
||||
|
||||
The `q` key will be remapped to perform `:qa!` so you can close everything
|
||||
quickly if it all looks good.
|
||||
|
||||
The `run-tests.sh` script is still a work in progress. I need to figure out
|
||||
a good way of collecting results. Suggestions and/or patches are very welcome.
|
@ -0,0 +1 @@
|
||||
../../../../bundled/ut/autoload/lh/UT.vim
|
147
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/askvim.vim
Normal file
147
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/askvim.vim
Normal file
@ -0,0 +1,147 @@
|
||||
"=============================================================================
|
||||
" $Id: askvim.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/askvim.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 17th Apr 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (17th Apr 2007)
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Defines functions that asks vim what it is relinquish to tell us
|
||||
" - menu
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.0.0:
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#askvim#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#askvim#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # Public {{{2
|
||||
" Function: lh#askvim#exe(command) {{{3
|
||||
function! lh#askvim#Exe(command)
|
||||
echomsg 'lh#askvim#Exe() is deprecated, use lh#askvim#exe()'
|
||||
return lh#askvim#exe(a:command)
|
||||
endfunction
|
||||
|
||||
function! lh#askvim#exe(command)
|
||||
let save_a = @a
|
||||
try
|
||||
silent! redir @a
|
||||
silent! exe a:command
|
||||
redir END
|
||||
finally
|
||||
" Always restore everything
|
||||
let res = @a
|
||||
let @a = save_a
|
||||
return res
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
|
||||
" Function: lh#askvim#menu(menuid) {{{3
|
||||
function! s:AskOneMenu(menuact, res)
|
||||
let sKnown_menus = lh#askvim#exe(a:menuact)
|
||||
let lKnown_menus = split(sKnown_menus, '\n')
|
||||
" echo string(lKnown_menus)
|
||||
|
||||
" 1- search for the menuid
|
||||
" todo: fix the next line to correctly interpret "stuff\.stuff" and
|
||||
" "stuff\\.stuff".
|
||||
let menuid_parts = split(a:menuact, '\.')
|
||||
|
||||
let simplifiedKnown_menus = deepcopy(lKnown_menus)
|
||||
call map(simplifiedKnown_menus, 'substitute(v:val, "&", "", "g")')
|
||||
" let idx = lh#list#match(simplifiedKnown_menus, '^\d\+\s\+'.menuid_parts[-1])
|
||||
let idx = match(simplifiedKnown_menus, '^\d\+\s\+'.menuid_parts[-1])
|
||||
if idx == -1
|
||||
" echo "not found"
|
||||
return
|
||||
endif
|
||||
" echo "l[".idx."]=".lKnown_menus[idx]
|
||||
|
||||
if empty(a:res)
|
||||
let a:res.priority = matchstr(lKnown_menus[idx], '\d\+\ze\s\+.*')
|
||||
let a:res.name = matchstr(lKnown_menus[idx], '\d\+\s\+\zs.*')
|
||||
let a:res.actions = {}
|
||||
" else
|
||||
" what if the priority isn't the same?
|
||||
endif
|
||||
|
||||
" 2- search for the menu definition
|
||||
let idx += 1
|
||||
while idx != len(lKnown_menus)
|
||||
echo "l[".idx."]=".lKnown_menus[idx]
|
||||
" should not happen
|
||||
if lKnown_menus[idx] =~ '^\d\+' | break | endif
|
||||
|
||||
" :h showing-menus
|
||||
" -> The format of the result of the call to Exe() seems to be:
|
||||
" ^ssssMns-sACTION$
|
||||
" s == 1 whitespace
|
||||
" M == mode (inrvcs)
|
||||
" n == noremap(*)/script(&)
|
||||
" - == disable(-)/of not
|
||||
let act = {}
|
||||
let menu_def = matchlist(lKnown_menus[idx],
|
||||
\ '^\s*\([invocs]\)\([&* ]\) \([- ]\) \(.*\)$')
|
||||
if len(menu_def) > 4
|
||||
let act.mode = menu_def[1]
|
||||
let act.nore_script = menu_def[2]
|
||||
let act.disabled = menu_def[3]
|
||||
let act.action = menu_def[4]
|
||||
else
|
||||
echomsg string(menu_def)
|
||||
echoerr "lh#askvim#menu(): Cannot decode ``".lKnown_menus[idx]."''"
|
||||
endif
|
||||
|
||||
let a:res.actions["mode_" . act.mode] = act
|
||||
|
||||
let idx += 1
|
||||
endwhile
|
||||
|
||||
" n- Return the result
|
||||
return a:res
|
||||
endfunction
|
||||
|
||||
function! lh#askvim#menu(menuid, modes)
|
||||
let res = {}
|
||||
let i = 0
|
||||
while i != strlen(a:modes)
|
||||
call s:AskOneMenu(a:modes[i].'menu '.a:menuid, res)
|
||||
let i += 1
|
||||
endwhile
|
||||
return res
|
||||
endfunction
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,97 @@
|
||||
"=============================================================================
|
||||
" $Id: buffer.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/buffer.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 23rd Jan 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Defines functions that help finding windows and handling buffers.
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v 1.0.0 First Version
|
||||
" (*) Functions moved from searchInRuntimeTime
|
||||
" v 2.2.0
|
||||
" (*) new function: lh#buffer#list()
|
||||
" TODO:
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
" ## Functions {{{1
|
||||
"------------------------------------------------------------------------
|
||||
" # Debug {{{2
|
||||
function! lh#buffer#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#buffer#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # Public {{{2
|
||||
|
||||
" Function: lh#buffer#find({filename}) {{{3
|
||||
" If {filename} is opened in a window, jump to this window, otherwise return -1
|
||||
" Moved from searchInRuntimeTime.vim
|
||||
function! lh#buffer#find(filename)
|
||||
let b = bufwinnr(a:filename)
|
||||
if b == -1 | return b | endif
|
||||
exe b.'wincmd w'
|
||||
return b
|
||||
endfunction
|
||||
function! lh#buffer#Find(filename)
|
||||
return lh#buffer#find(a:filename)
|
||||
endfunction
|
||||
|
||||
" Function: lh#buffer#jump({filename},{cmd}) {{{3
|
||||
function! lh#buffer#jump(filename, cmd)
|
||||
if lh#buffer#find(a:filename) != -1 | return | endif
|
||||
exe a:cmd . ' ' . a:filename
|
||||
endfunction
|
||||
function! lh#buffer#Jump(filename, cmd)
|
||||
return lh#buffer#jump(a:filename, a:cmd)
|
||||
endfunction
|
||||
|
||||
" Function: lh#buffer#scratch({bname},{where}) {{{3
|
||||
function! lh#buffer#scratch(bname, where)
|
||||
try
|
||||
silent exe a:where.' sp '.a:bname
|
||||
catch /.*/
|
||||
throw "Can't open a buffer named '".a:bname."'!"
|
||||
endtry
|
||||
setlocal bt=nofile bh=wipe nobl noswf ro
|
||||
endfunction
|
||||
function! lh#buffer#Scratch(bname, where)
|
||||
return lh#buffer#scratch(a:bname, a:where)
|
||||
endfunction
|
||||
|
||||
" Function: lh#buffer#list() {{{3
|
||||
function! lh#buffer#list()
|
||||
let all = range(0, bufnr('$'))
|
||||
" let res = lh#list#transform_if(all, [], 'v:1_', 'buflisted')
|
||||
let res = lh#list#copy_if(all, [], 'buflisted')
|
||||
return res
|
||||
endfunction
|
||||
" Ex: echo lh#list#transform(lh#buffer#list(), [], "bufname")
|
||||
"=============================================================================
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,268 @@
|
||||
"=============================================================================
|
||||
" $Id: dialog.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/buffer/dialog.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 21st Sep 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: «description»
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v 1.0.0 First Version
|
||||
" (*) Functions imported from Mail_mutt_alias.vim
|
||||
" TODO:
|
||||
" (*) --abort-- line
|
||||
" (*) custom messages
|
||||
" (*) do not mess with search history
|
||||
" (*) support any &magic
|
||||
" (*) syntax
|
||||
" (*) add number/letters
|
||||
" (*) tag with '[x] ' instead of '* '
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
|
||||
"=============================================================================
|
||||
" ## Globals {{{1
|
||||
let s:LHdialog = {}
|
||||
|
||||
"=============================================================================
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#buffer#dialog#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#buffer#dialog#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
|
||||
"=============================================================================
|
||||
" # Dialog functions {{{2
|
||||
"------------------------------------------------------------------------
|
||||
function! s:Mappings(abuffer)
|
||||
" map <enter> to edit a file, also dbl-click
|
||||
exe "nnoremap <silent> <buffer> <esc> :silent call ".a:abuffer.action."(-1, ".a:abuffer.id.")<cr>"
|
||||
exe "nnoremap <silent> <buffer> q :call lh#buffer#dialog#select(-1, ".a:abuffer.id.")<cr>"
|
||||
exe "nnoremap <silent> <buffer> <cr> :call lh#buffer#dialog#select(line('.'), ".a:abuffer.id.")<cr>"
|
||||
" nnoremap <silent> <buffer> <2-LeftMouse> :silent call <sid>GrepEditFileLine(line("."))<cr>
|
||||
" nnoremap <silent> <buffer> Q :call <sid>Reformat()<cr>
|
||||
" nnoremap <silent> <buffer> <Left> :set tabstop-=1<cr>
|
||||
" nnoremap <silent> <buffer> <Right> :set tabstop+=1<cr>
|
||||
if a:abuffer.support_tagging
|
||||
nnoremap <silent> <buffer> t :silent call <sid>ToggleTag(line("."))<cr>
|
||||
nnoremap <silent> <buffer> <space> :silent call <sid>ToggleTag(line("."))<cr>
|
||||
endif
|
||||
nnoremap <silent> <buffer> <tab> :silent call <sid>NextChoice('')<cr>
|
||||
nnoremap <silent> <buffer> <S-tab> :silent call <sid>NextChoice('b')<cr>
|
||||
exe "nnoremap <silent> <buffer> h :silent call <sid>ToggleHelp(".a:abuffer.id.")<cr>"
|
||||
endfunction
|
||||
|
||||
"----------------------------------------
|
||||
" Tag / untag the current choice {{{
|
||||
function! s:ToggleTag(lineNum)
|
||||
if a:lineNum > s:Help_NbL()
|
||||
" If tagged
|
||||
if (getline(a:lineNum)[0] == '*')
|
||||
let b:NbTags = b:NbTags - 1
|
||||
silent exe a:lineNum.'s/^\* / /e'
|
||||
else
|
||||
let b:NbTags = b:NbTags + 1
|
||||
silent exe a:lineNum.'s/^ /* /e'
|
||||
endif
|
||||
" Move after the tag ; there is something with the two previous :s. They
|
||||
" don't leave the cursor at the same position.
|
||||
silent! normal! 3|
|
||||
call s:NextChoice('') " move to the next choice
|
||||
endif
|
||||
endfunction
|
||||
" }}}
|
||||
|
||||
function! s:Help_NbL()
|
||||
" return 1 + nb lines of BuildHelp
|
||||
return 2 + len(b:dialog['help_'.b:dialog.help_type])
|
||||
endfunction
|
||||
"----------------------------------------
|
||||
" Go to the Next (/previous) possible choice. {{{
|
||||
function! s:NextChoice(direction)
|
||||
" echomsg "next!"
|
||||
call search('^[ *]\s*\zs\S\+', a:direction)
|
||||
endfunction
|
||||
" }}}
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
|
||||
function! s:RedisplayHelp(dialog)
|
||||
silent! 2,$g/^@/d_
|
||||
normal! gg
|
||||
for help in a:dialog['help_'.a:dialog.help_type]
|
||||
silent put=help
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! lh#buffer#dialog#update(dialog)
|
||||
set noro
|
||||
exe (s:Help_NbL()+1).',$d_'
|
||||
for choice in a:dialog.choices
|
||||
silent $put=' '.choice
|
||||
endfor
|
||||
set ro
|
||||
endfunction
|
||||
|
||||
function! s:Display(dialog, atitle)
|
||||
set noro
|
||||
0 put = a:atitle
|
||||
call s:RedisplayHelp(a:dialog)
|
||||
for choice in a:dialog.choices
|
||||
silent $put=' '.choice
|
||||
endfor
|
||||
set ro
|
||||
exe s:Help_NbL()+1
|
||||
endfunction
|
||||
|
||||
function! s:ToggleHelp(bufferId)
|
||||
call lh#buffer#find(a:bufferId)
|
||||
call b:dialog.toggle_help()
|
||||
endfunction
|
||||
|
||||
function! lh#buffer#dialog#toggle_help() dict
|
||||
let self.help_type
|
||||
\ = (self.help_type == 'short')
|
||||
\ ? 'long'
|
||||
\ : 'short'
|
||||
call s:RedisplayHelp(self)
|
||||
endfunction
|
||||
|
||||
function! lh#buffer#dialog#new(bname, title, where, support_tagging, action, choices)
|
||||
" The ID will be the buffer id
|
||||
let res = {}
|
||||
let where_it_started = getpos('.')
|
||||
let where_it_started[0] = bufnr('%')
|
||||
let res.where_it_started = where_it_started
|
||||
|
||||
try
|
||||
call lh#buffer#scratch(a:bname, a:where)
|
||||
catch /.*/
|
||||
echoerr v:exception
|
||||
return res
|
||||
endtry
|
||||
let res.id = bufnr('%')
|
||||
let b:NbTags = 0
|
||||
let b:dialog = res
|
||||
let s:LHdialog[res.id] = res
|
||||
let res.help_long = []
|
||||
let res.help_short = []
|
||||
let res.help_type = 'short'
|
||||
let res.support_tagging = a:support_tagging
|
||||
let res.action = a:action
|
||||
let res.choices = a:choices
|
||||
|
||||
" Long help
|
||||
call lh#buffer#dialog#add_help(res, '@| <cr>, <double-click> : select this', 'long')
|
||||
call lh#buffer#dialog#add_help(res, '@| <esc>, q : Abort', 'long')
|
||||
if a:support_tagging
|
||||
call lh#buffer#dialog#add_help(res, '@| <t>, <space> : Tag/Untag the current item', 'long')
|
||||
endif
|
||||
call lh#buffer#dialog#add_help(res, '@| <up>/<down>, <tab>, +/- : Move between entries', 'long')
|
||||
call lh#buffer#dialog#add_help(res, '@|', 'long')
|
||||
" call lh#buffer#dialog#add_help(res, '@| h : Toggle help', 'long')
|
||||
call lh#buffer#dialog#add_help(res, '@+'.repeat('-', winwidth(bufwinnr(res.id))-3), 'long')
|
||||
" Short Help
|
||||
" call lh#buffer#dialog#add_help(res, '@| h : Toggle help', 'short')
|
||||
call lh#buffer#dialog#add_help(res, '@+'.repeat('-', winwidth(bufwinnr(res.id))-3), 'short')
|
||||
|
||||
let res.toggle_help = function("lh#buffer#dialog#toggle_help")
|
||||
let title = '@ ' . a:title
|
||||
let helpstr = '| Toggle (h)elp'
|
||||
let title = title
|
||||
\ . repeat(' ', winwidth(bufwinnr(res.id))-strlen(title)-strlen(helpstr)-1)
|
||||
\ . helpstr
|
||||
call s:Display(res, title)
|
||||
|
||||
call s:Mappings(res)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! lh#buffer#dialog#add_help(abuffer, text, help_type)
|
||||
call add(a:abuffer['help_'.a:help_type],a:text)
|
||||
endfunction
|
||||
|
||||
"=============================================================================
|
||||
function! lh#buffer#dialog#quit()
|
||||
let bufferId = b:dialog.where_it_started[0]
|
||||
echohl WarningMsg
|
||||
echo "Abort"
|
||||
echohl None
|
||||
quit
|
||||
call lh#buffer#find(bufferId)
|
||||
endfunction
|
||||
|
||||
" Function: lh#buffer#dialog#select(line, bufferId [,overriden-action])
|
||||
function! lh#buffer#dialog#select(line, bufferId, ...)
|
||||
if a:line == -1
|
||||
call lh#buffer#dialog#quit()
|
||||
return
|
||||
" elseif a:line <= s:Help_NbL() + 1
|
||||
elseif a:line <= s:Help_NbL()
|
||||
echoerr "Unselectable item"
|
||||
return
|
||||
else
|
||||
let dialog = s:LHdialog[a:bufferId]
|
||||
let results = { 'dialog' : dialog, 'selection' : [] }
|
||||
|
||||
if b:NbTags == 0
|
||||
" -1 because first index is 0
|
||||
" let results = [ dialog.choices[a:line - s:Help_NbL() - 1] ]
|
||||
let results.selection = [ a:line - s:Help_NbL() - 1 ]
|
||||
else
|
||||
silent g/^* /call add(results.selection, line('.')-s:Help_NbL()-1)
|
||||
endif
|
||||
endif
|
||||
|
||||
if a:0 > 0 " action overriden
|
||||
exe 'call '.dialog.action.'(results, a:000)'
|
||||
else
|
||||
exe 'call '.dialog.action.'(results)'
|
||||
endif
|
||||
endfunction
|
||||
function! lh#buffer#dialog#Select(line, bufferId, ...)
|
||||
echomsg "lh#buffer#dialog#Select() is deprecated, use lh#buffer#dialog#select() instead"
|
||||
if a:0 > 0 " action overriden
|
||||
exe 'call lh#buffer#dialog#select(a:line, a:bufferId, a:1)'
|
||||
else
|
||||
exe 'call lh#buffer#dialog#select(a:line, a:bufferId)'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! Action(results)
|
||||
let dialog = a:results.dialog
|
||||
let choices = dialog.choices
|
||||
for r in a:results.selection
|
||||
echomsg '-> '.choices[r]
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,224 @@
|
||||
"=============================================================================
|
||||
" $Id: command.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/command.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 08th Jan 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (08th Jan 2007)
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Helpers to define commands that:
|
||||
" - support subcommands
|
||||
" - support autocompletion
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.0.0:
|
||||
" Code move from other plugins
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
" ## Debug {{{1
|
||||
function! lh#command#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#command#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
|
||||
" Tool functions {{{2
|
||||
" Function: lh#command#Fargs2String(aList) {{{3
|
||||
" @param[in,out] aList list of params from <f-args>
|
||||
" @see tests/lh/test-Fargs2String.vim
|
||||
function! lh#command#Fargs2String(aList)
|
||||
if empty(a:aList) | return '' | endif
|
||||
|
||||
let quote_char = a:aList[0][0]
|
||||
let res = a:aList[0]
|
||||
call remove(a:aList, 0)
|
||||
if quote_char !~ '["'."']"
|
||||
return res
|
||||
endif
|
||||
" else
|
||||
let end_string = '[^\\]\%(\\\\\)*'.quote_char.'$'
|
||||
while !empty(a:aList) && res !~ end_string
|
||||
let res .= ' ' . a:aList[0]
|
||||
call remove(a:aList, 0)
|
||||
endwhile
|
||||
return res
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Experimental Functions {{{1
|
||||
|
||||
" Internal functions {{{2
|
||||
" Function: s:SaveData({Data}) {{{3
|
||||
" @param Data Command definition
|
||||
" Saves {Data} as s:Data{s:data_id++}. The definition will be used by
|
||||
" automatically generated commands.
|
||||
" @return s:data_id
|
||||
let s:data_id = 0
|
||||
function! s:SaveData(Data)
|
||||
if has_key(a:Data, "command_id")
|
||||
" Avoid data duplication
|
||||
return a:Data.command_id
|
||||
else
|
||||
let s:Data{s:data_id} = a:Data
|
||||
let id = s:data_id
|
||||
let s:data_id += 1
|
||||
let a:Data.command_id = id
|
||||
return id
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" BTWComplete(ArgLead, CmdLine, CursorPos): Auto-complete {{{3
|
||||
function! lh#command#complete(ArgLead, CmdLine, CursorPos)
|
||||
let tmp = substitute(a:CmdLine, '\s*\S*', 'Z', 'g')
|
||||
let pos = strlen(tmp)
|
||||
if 0
|
||||
call confirm( "AL = ". a:ArgLead."\nCL = ". a:CmdLine."\nCP = ".a:CursorPos
|
||||
\ . "\ntmp = ".tmp."\npos = ".pos
|
||||
\, '&Ok', 1)
|
||||
endif
|
||||
|
||||
if 2 == pos
|
||||
" First argument: a command
|
||||
return s:commands
|
||||
elseif 3 == pos
|
||||
" Second argument: first arg of the command
|
||||
if -1 != match(a:CmdLine, '^BTW\s\+echo')
|
||||
return s:functions . "\n" . s:variables
|
||||
elseif -1 != match(a:CmdLine, '^BTW\s\+\%(help\|?\)')
|
||||
elseif -1 != match(a:CmdLine, '^BTW\s\+\%(set\|add\)\%(local\)\=')
|
||||
" Adds a filter
|
||||
" let files = globpath(&rtp, 'compiler/BT-*')
|
||||
" let files = files . globpath(&rtp, 'compiler/BT_*')
|
||||
" let files = files . globpath(&rtp, 'compiler/BT/*')
|
||||
let files = s:FindFilter('*')
|
||||
let files = substitute(files,
|
||||
\ '\(^\|\n\).\{-}compiler[\\/]BTW[-_\\/]\(.\{-}\)\.vim\>\ze\%(\n\|$\)',
|
||||
\ '\1\2', 'g')
|
||||
return files
|
||||
elseif -1 != match(a:CmdLine, '^BTW\s\+remove\%(local\)\=')
|
||||
" Removes a filter
|
||||
return substitute(s:FiltersList(), ',', '\n', 'g')
|
||||
endif
|
||||
endif
|
||||
" finally: unknown
|
||||
echoerr 'BTW: unespected parameter ``'. a:ArgLead ."''"
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:BTW(command, ...)
|
||||
" todo: check a:0 > 1
|
||||
if 'set' == a:command | let g:BTW_build_tool = a:1
|
||||
if exists('b:BTW_build_tool')
|
||||
let b:BTW_build_tool = a:1
|
||||
endif
|
||||
elseif 'setlocal' == a:command | let b:BTW_build_tool = a:1
|
||||
elseif 'add' == a:command | call s:AddFilter('g', a:1)
|
||||
elseif 'addlocal' == a:command | call s:AddFilter('b', a:1)
|
||||
" if exists('b:BTW_filters_list') " ?????
|
||||
" call s:AddFilter('b', a:1)
|
||||
" endif
|
||||
elseif 'remove' == a:command | call s:RemoveFilter('g', a:1)
|
||||
elseif 'removelocal' == a:command | call s:RemoveFilter('b', a:1)
|
||||
elseif 'rebuild' == a:command " wait for s:ReconstructToolsChain()
|
||||
elseif 'echo' == a:command | exe "echo s:".a:1
|
||||
" echo s:{a:f1} ## don't support «echo s:f('foo')»
|
||||
elseif 'reloadPlugin' == a:command
|
||||
let g:force_reload_BuildToolsWrapper = 1
|
||||
let g:BTW_BTW_in_use = 1
|
||||
exe 'so '.s:sfile
|
||||
unlet g:force_reload_BuildToolsWrapper
|
||||
unlet g:BTW_BTW_in_use
|
||||
return
|
||||
elseif a:command =~ '\%(help\|?\)'
|
||||
call s:Usage()
|
||||
return
|
||||
endif
|
||||
call s:ReconstructToolsChain()
|
||||
endfunction
|
||||
|
||||
" ##############################################################
|
||||
" Public functions {{{2
|
||||
|
||||
function! s:FindSubcommand(definition, subcommand)
|
||||
for arg in a:definition.arguments
|
||||
if arg.name == a:subcommand
|
||||
return arg
|
||||
endif
|
||||
endfor
|
||||
throw "NF"
|
||||
endfunction
|
||||
|
||||
function! s:execute_function(definition, params)
|
||||
if len(a:params) < 1
|
||||
throw "(lh#command) Not enough arguments"
|
||||
endif
|
||||
let l:Fn = a:definition.action
|
||||
echo "calling ".string(l:Fn)
|
||||
echo "with ".string(a:params)
|
||||
" call remove(a:params, 0)
|
||||
call l:Fn(a:params)
|
||||
endfunction
|
||||
|
||||
function! s:execute_sub_commands(definition, params)
|
||||
try
|
||||
if len(a:params) < 1
|
||||
throw "(lh#command) Not enough arguments"
|
||||
endif
|
||||
let subcommand = s:FindSubcommand(a:definition, a:params[0])
|
||||
call remove(a:params, 0)
|
||||
call s:int_execute(subcommand, a:params)
|
||||
catch /NF.*/
|
||||
throw "(lh#command) Unexpected subcommand `".a:params[0]."'."
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:int_execute(definition, params)
|
||||
echo "params=".string(a:params)
|
||||
call s:execute_{a:definition.arg_type}(a:definition, a:params)
|
||||
endfunction
|
||||
|
||||
function! s:execute(definition, ...)
|
||||
try
|
||||
let params = copy(a:000)
|
||||
call s:int_execute(a:definition, params)
|
||||
catch /(lh#command).*/
|
||||
echoerr v:exception . " in `".a:definition.name.' '.join(a:000, ' ')."'"
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! lh#command#new(definition)
|
||||
let cmd_name = a:definition.name
|
||||
" Save the definition as an internal script variable
|
||||
let id = s:SaveData(a:definition)
|
||||
exe "command! -nargs=* ".cmd_name." :call s:execute(s:Data".id.", <f-args>)"
|
||||
endfunction
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,93 @@
|
||||
"=============================================================================
|
||||
" $Id: common.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/common.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 07th Oct 2006
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (08th Feb 2008)
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Some common functions for:
|
||||
" - displaying error messages
|
||||
" - checking dependencies
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.1.1
|
||||
" - New function: lh#common#echomsg_multilines()
|
||||
" - lh#common#warning_msg() supports multilines messages
|
||||
"
|
||||
" v2.0.0:
|
||||
" - Code moved from other plugins
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
" Functions {{{1
|
||||
|
||||
" Function: lh#common#echomsg_multilines {{{2
|
||||
function! lh#common#echomsg_multilines(text)
|
||||
let lines = split(a:text, "[\n\r]")
|
||||
for line in lines
|
||||
echomsg line
|
||||
endfor
|
||||
endfunction
|
||||
function! lh#common#echomsgMultilines(text)
|
||||
return lh#common#echomsg_multilines(a:text)
|
||||
endfunction
|
||||
|
||||
" Function: lh#common#error_msg {{{2
|
||||
function! lh#common#error_msg(text)
|
||||
if has('gui_running')
|
||||
call confirm(a:text, '&Ok', '1', 'Error')
|
||||
else
|
||||
" echohl ErrorMsg
|
||||
echoerr a:text
|
||||
" echohl None
|
||||
endif
|
||||
endfunction
|
||||
function! lh#common#ErrorMsg(text)
|
||||
return lh#common#error_msg(a:text)
|
||||
endfunction
|
||||
|
||||
" Function: lh#common#warning_msg {{{2
|
||||
function! lh#common#warning_msg(text)
|
||||
echohl WarningMsg
|
||||
" echomsg a:text
|
||||
call lh#common#echomsg_multilines(a:text)
|
||||
echohl None
|
||||
endfunction
|
||||
function! lh#common#WarningMsg(text)
|
||||
return lh#common#warning_msg(a:text)
|
||||
endfunction
|
||||
|
||||
" Dependencies {{{2
|
||||
function! lh#common#check_deps(Symbol, File, path, plugin) " {{{3
|
||||
if !exists(a:Symbol)
|
||||
exe "runtime ".a:path.a:File
|
||||
if !exists(a:Symbol)
|
||||
call lh#common#error_msg( a:plugin.': Requires <'.a:File.'>')
|
||||
return 0
|
||||
endif
|
||||
endif
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! lh#common#CheckDeps(Symbol, File, path, plugin) " {{{3
|
||||
echomsg "lh#common#CheckDeps() is deprecated, use lh#common#check_deps() instead."
|
||||
return lh#common#check_deps(a:Symbol, a:File, a:path, a:plugin)
|
||||
endfunction
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,49 @@
|
||||
"=============================================================================
|
||||
" $Id: encoding.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/encoding.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 21st Feb 2008
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Defines functions that help managing various encodings
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.0.7:
|
||||
" (*) lh#encoding#Iconv() copied from map-tools
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
|
||||
" Function: lh#encoding#iconv(expr, from, to) " {{{3
|
||||
" Unlike |iconv()|, this wrapper returns {expr} when we know no convertion can
|
||||
" be acheived.
|
||||
function! lh#encoding#iconv(expr, from, to)
|
||||
" call Dfunc("s:ICONV(".a:expr.','.a:from.','.a:to.')')
|
||||
if has('multi_byte') &&
|
||||
\ ( has('iconv') || has('iconv/dyn') ||
|
||||
\ ((a:from=~'latin1\|utf-8') && (a:to=~'latin1\|utf-8')))
|
||||
" call confirm('encoding: '.&enc."\nto:".a:to, "&Ok", 1)
|
||||
" call Dret("s:ICONV convert=".iconv(a:expr, a:from, a:to))
|
||||
return iconv(a:expr,a:from,a:to)
|
||||
else
|
||||
" Cannot convert
|
||||
" call Dret("s:ICONV no convert=".a:expr)
|
||||
return a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,75 @@
|
||||
"=============================================================================
|
||||
" $Id: env.vim 244 2010-09-19 22:38:24Z luc.hermitte $
|
||||
" File: autoload/lh/env.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 19th Jul 2010
|
||||
" Last Update: $Date: 2010-09-19 18:38:24 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Functions related to environment (variables)
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop this file into {rtp}/autoload/lh
|
||||
" Requires Vim7+
|
||||
" History:
|
||||
" v2.2.1 First Version
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
" ## Misc Functions {{{1
|
||||
" # Version {{{2
|
||||
let s:k_version = 221
|
||||
function! lh#env#version()
|
||||
return s:k_version
|
||||
endfunction
|
||||
|
||||
" # Debug {{{2
|
||||
let s:verbose = 0
|
||||
function! lh#env#verbose(...)
|
||||
if a:0 > 0 | let s:verbose = a:1 | endif
|
||||
return s:verbose
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#env#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Exported functions {{{1
|
||||
function! lh#env#expand_all(string)
|
||||
let res = ''
|
||||
let tail = a:string
|
||||
while !empty(tail)
|
||||
let [ all, head, var, tail; dummy ] = matchlist(tail, '\(.\{-}\)\%(${\(.\{-}\)}\)\=\(.*\)')
|
||||
if empty(var)
|
||||
let res .= tail
|
||||
break
|
||||
else
|
||||
let res .= head
|
||||
let val = eval('$'.var)
|
||||
let res .= val
|
||||
endif
|
||||
endwhile
|
||||
return res
|
||||
endfunction
|
||||
"------------------------------------------------------------------------
|
||||
" ## Internal functions {{{1
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,68 @@
|
||||
"=============================================================================
|
||||
" $Id: event.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/event.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 15th Feb 2008
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Function to help manage vim |autocommand-events|
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.0.6:
|
||||
" Creation
|
||||
" TODO:
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#event#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#event#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # Event Registration {{{2
|
||||
function! s:RegisteredOnce(cmd, group)
|
||||
" We can't delete the current augroup autocommand => increment a counter
|
||||
if !exists('s:'.a:group) || s:{a:group} == 0
|
||||
let s:{a:group} = 1
|
||||
exe a:cmd
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#event#register_for_one_execution_at(event, cmd, group)
|
||||
let group = a:group.'_once'
|
||||
let s:{group} = 0
|
||||
exe 'augroup '.group
|
||||
au!
|
||||
exe 'au '.a:event.' '.expand('%:p').' call s:RegisteredOnce('.string(a:cmd).','.string(group).')'
|
||||
augroup END
|
||||
endfunction
|
||||
function! lh#event#RegisterForOneExecutionAt(event, cmd, group)
|
||||
return lh#event#register_for_one_execution_at(a:event, a:cmd, a:group)
|
||||
endfunction
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,214 @@
|
||||
"=============================================================================
|
||||
" $Id: function.vim 161 2010-05-07 01:04:44Z luc.hermitte $
|
||||
" File: autoload/lh/function.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.0
|
||||
" Created: 03rd Nov 2008
|
||||
" Last Update: $Date: 2010-05-06 21:04:44 -0400 (Thu, 06 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Implements:
|
||||
" - lh#function#bind()
|
||||
" - lh#function#execute()
|
||||
" - lh#function#prepare()
|
||||
" - a binded function type
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.2.0: first implementation
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#function#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#function#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
" # Function: s:Join(arguments...) {{{2
|
||||
function! s:Join(args)
|
||||
let res = ''
|
||||
if len(a:args) > 0
|
||||
let res = string(a:args[0])
|
||||
let i = 1
|
||||
while i != len(a:args)
|
||||
let res.=','.string(a:args[i])
|
||||
let i += 1
|
||||
endwhile
|
||||
endif
|
||||
return res
|
||||
endfunction
|
||||
|
||||
" # Function: s:DoBindList(arguments...) {{{2
|
||||
function! s:DoBindList(formal, real)
|
||||
let args = []
|
||||
for arg in a:formal
|
||||
if type(arg)==type('string') && arg =~ '^v:\d\+_$'
|
||||
let new = a:real[matchstr(arg, 'v:\zs\d\+\ze_')-1]
|
||||
elseif type(arg)==type('string')
|
||||
let new = eval(s:DoBindEvaluatedString(arg, a:real))
|
||||
else
|
||||
let new = arg
|
||||
endif
|
||||
call add(args, new)
|
||||
unlet new
|
||||
unlet arg
|
||||
endfor
|
||||
return args
|
||||
endfunction
|
||||
|
||||
" # Function: s:DoBindString(arguments...) {{{2
|
||||
function! s:DoBindString(expr, real)
|
||||
let expr = substitute(a:expr, '\<v:\(\d\+\)_\>', a:real.'[\1-1]', 'g')
|
||||
return expr
|
||||
endfunction
|
||||
|
||||
function! s:ToString(expr)
|
||||
return type(a:expr) != type('')
|
||||
\ ? string(a:expr)
|
||||
\ : (a:expr)
|
||||
endfunction
|
||||
|
||||
function! s:DoBindEvaluatedString(expr, real)
|
||||
let expr = a:expr
|
||||
let p = 0
|
||||
while 1
|
||||
let p = match(expr, '\<v:\d\+_\>', p)
|
||||
if -1 == p | break | endif
|
||||
let e = matchend(expr, '\<v:\d\+_\>', p)
|
||||
let n = eval(expr[p+2 : e-2])
|
||||
" let new = (type(a:real[n-1])==type('') && a:real[n-1]=~ '\<v:\d\+_\>')
|
||||
" \ ? a:real[n-1]
|
||||
" \ : string(a:real[n-1])
|
||||
let new = s:ToString(a:real[n-1])
|
||||
" let new = string(a:real[n-1]) " -> bind_counpound vars
|
||||
let expr = ((p>0) ? (expr[0:p-1]) : '') . new . expr[e : -1]
|
||||
" echo expr
|
||||
let p += len(new)
|
||||
" silent! unlet new
|
||||
endwhile
|
||||
|
||||
return expr
|
||||
endfunction
|
||||
|
||||
" # Function: s:Execute(arguments...) {{{2
|
||||
function! s:Execute(args) dict
|
||||
if type(self.function) == type(function('exists'))
|
||||
let args = s:DoBindList(self.args, a:args)
|
||||
" echomsg '##'.string(self.function).'('.join(args, ',').')'
|
||||
let res = eval(string(self.function).'('.s:Join(args).')')
|
||||
elseif type(self.function) == type('string')
|
||||
let expr = s:DoBindString(self.function, 'a:args')
|
||||
let res = eval(expr)
|
||||
elseif type(self.function) == type({})
|
||||
return self.function.execute(a:args)
|
||||
else
|
||||
throw "lh#functor#execute: unpected function type: ".type(self.function)
|
||||
endif
|
||||
return res
|
||||
endfunction
|
||||
|
||||
" # Function: lh#function#prepare(function, arguments_list) {{{2
|
||||
function! lh#function#prepare(Fn, arguments_list)
|
||||
if type(a:Fn) == type(function('exists'))
|
||||
let expr = string(a:Fn).'('.s:Join(a:arguments_list).')'
|
||||
return expr
|
||||
elseif type(a:Fn) == type('string')
|
||||
if a:Fn =~ '^[a-zA-Z0-9_#]\+$'
|
||||
let expr = string(function(a:Fn)).'('.s:Join(a:arguments_list).')'
|
||||
return expr
|
||||
else
|
||||
let expr = s:DoBindString(a:Fn, 'a:000')
|
||||
return expr
|
||||
endif
|
||||
else
|
||||
throw "lh#function#prepare(): {Fn} argument of type ".type(a:Fn). " is unsupported"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" # Function: lh#function#execute(function, arguments...) {{{2
|
||||
function! lh#function#execute(Fn, ...)
|
||||
if type(a:Fn) == type({}) && has_key(a:Fn, 'execute')
|
||||
return a:Fn.execute(a:000)
|
||||
else
|
||||
let expr = lh#function#prepare(a:Fn, a:000)
|
||||
return eval(expr)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" # Function: lh#function#bind(function, arguments...) {{{2
|
||||
function! lh#function#bind(Fn, ...)
|
||||
let args = copy(a:000)
|
||||
if type(a:Fn) == type('string') && a:Fn =~ '^[a-zA-Z0-9_#]\+$'
|
||||
\ && exists('*'.a:Fn)
|
||||
let Fn = function(a:Fn)
|
||||
elseif type(a:Fn) == type({})
|
||||
" echo string(a:Fn).'('.string(a:000).')'
|
||||
" Rebinding another binded function
|
||||
" TASSERT has_key(a:Fn, 'function')
|
||||
" TASSERT has_key(a:Fn, 'execute')
|
||||
" TASSERT has_key(a:Fn, 'args')
|
||||
let Fn = a:Fn.function
|
||||
let N = len(a:Fn.args)
|
||||
if N != 0 " args to rebind
|
||||
let i = 0
|
||||
let t_args = [] " necessary to avoid type changes
|
||||
while i != N
|
||||
silent! unlet arg
|
||||
let arg = a:Fn.args[i]
|
||||
if arg =~ 'v:\d\+_$'
|
||||
let arg2 = eval(s:DoBindString(arg, string(args)))
|
||||
" echo arg."-(".string(args).")->".string(arg2)
|
||||
unlet arg
|
||||
let arg = arg2
|
||||
unlet arg2
|
||||
endif
|
||||
call add(t_args, arg)
|
||||
let i += 1
|
||||
endwhile
|
||||
unlet a:Fn.args
|
||||
let a:Fn.args = t_args
|
||||
else " expression to fix
|
||||
" echo Fn
|
||||
" echo s:DoBindString(Fn, string(args))
|
||||
" echo eval(string(s:DoBindString(Fn, string(args))))
|
||||
let Fn = (s:DoBindEvaluatedString(Fn, args))
|
||||
endif
|
||||
let args = a:Fn.args
|
||||
else
|
||||
let Fn = a:Fn
|
||||
endif
|
||||
|
||||
let binded_fn = {
|
||||
\ 'function': Fn,
|
||||
\ 'args': args,
|
||||
\ 'execute': function('s:Execute')
|
||||
\}
|
||||
return binded_fn
|
||||
endfunction
|
||||
|
||||
" }}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
||||
" Vim: let g:UTfiles='tests/lh/function.vim'
|
@ -0,0 +1,177 @@
|
||||
"=============================================================================
|
||||
" $Id: tsort.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/tsort.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 21st Apr 2008
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: Library functions for Topological Sort
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Drop the file into {rtp}/autoload/lh/graph
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Debug {{{1
|
||||
function! lh#graph#tsort#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#graph#tsort#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
"## Helper functions {{{1
|
||||
"# s:Successors_fully_defined(node) {{{2
|
||||
function! s:Successors_fully_defined(node) dict
|
||||
if has_key(self.table, a:node)
|
||||
return self.table[a:node]
|
||||
else
|
||||
return []
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"# s:Successors_lazy(node) {{{2
|
||||
function! s:Successors_lazy(node) dict
|
||||
if !has_key(self.table, a:node)
|
||||
let nodes = self.fetch(a:node)
|
||||
let self.table[a:node] = nodes
|
||||
" if len(nodes) > 0
|
||||
" let self.nb += 1
|
||||
" endif
|
||||
return nodes
|
||||
else
|
||||
return self.table[a:node]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"# s:PrepareDAG(dag) {{{2
|
||||
function! s:PrepareDAG(dag)
|
||||
if type(a:dag) == type(function('has_key'))
|
||||
let dag = {
|
||||
\ 'successors': function('s:Successors_lazy'),
|
||||
\ 'fetch' : a:dag,
|
||||
\ 'table' : {}
|
||||
\}
|
||||
else
|
||||
let dag = {
|
||||
\ 'successors': function('s:Successors_fully_defined'),
|
||||
\ 'table' : deepcopy(a:dag)
|
||||
\}
|
||||
endif
|
||||
return dag
|
||||
endfunction
|
||||
|
||||
"## Depth-first search (recursive) {{{1
|
||||
" Do not detect cyclic graphs
|
||||
|
||||
"# lh#graph#tsort#depth(dag, start_nodes) {{{2
|
||||
function! lh#graph#tsort#depth(dag, start_nodes)
|
||||
let dag = s:PrepareDAG(a:dag)
|
||||
let results = []
|
||||
let visited_nodes = { 'Visited':function('s:Visited')}
|
||||
call s:RecursiveDTSort(dag, a:start_nodes, results, visited_nodes)
|
||||
call reverse(results)
|
||||
return results
|
||||
endfunction
|
||||
|
||||
"# The real, recursive, T-Sort {{{2
|
||||
"see boost.graph for a non recursive implementation
|
||||
function! s:RecursiveDTSort(dag, start_nodes, results, visited_nodes)
|
||||
for node in a:start_nodes
|
||||
let visited = a:visited_nodes.Visited(node)
|
||||
if visited == 1 | continue " done
|
||||
elseif visited == 2 | throw "Tsort: cyclic graph detected: ".node
|
||||
endif
|
||||
let a:visited_nodes[node] = 2 " visiting
|
||||
let succs = a:dag.successors(node)
|
||||
try
|
||||
call s:RecursiveDTSort(a:dag, succs, a:results, a:visited_nodes)
|
||||
catch /Tsort:/
|
||||
throw v:exception.'>'.node
|
||||
endtry
|
||||
let a:visited_nodes[node] = 1 " visited
|
||||
call add(a:results, node)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:Visited(node) dict
|
||||
return has_key(self, a:node) ? self[a:node] : 0
|
||||
endfunction
|
||||
|
||||
"## Breadth-first search (non recursive) {{{1
|
||||
"# lh#graph#tsort#breadth(dag, start_nodes) {{{2
|
||||
" warning: This implementation does not work with lazy dag, but only with fully
|
||||
" defined ones
|
||||
function! lh#graph#tsort#breadth(dag, start_nodes)
|
||||
let result = []
|
||||
let dag = s:PrepareDAG(a:dag)
|
||||
let queue = deepcopy(a:start_nodes)
|
||||
|
||||
while len(queue) > 0
|
||||
let node = remove(queue, 0)
|
||||
" echomsg "result <- ".node
|
||||
call add(result, node)
|
||||
let successors = dag.successors(node)
|
||||
while len(successors) > 0
|
||||
let m = s:RemoveEdgeFrom(dag, node)
|
||||
" echomsg "graph loose ".node."->".m
|
||||
if !s:HasIncomingEgde(dag, m)
|
||||
" echomsg "queue <- ".m
|
||||
call add(queue, m)
|
||||
endif
|
||||
endwhile
|
||||
endwhile
|
||||
if !s:Empty(dag)
|
||||
throw "Tsort: cyclic graph detected: "
|
||||
endif
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:HasIncomingEgde(dag, node)
|
||||
for node in keys(a:dag.table)
|
||||
if type(a:dag.table[node]) != type([])
|
||||
continue
|
||||
endif
|
||||
if index(a:dag.table[node], a:node) != -1
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endfunction
|
||||
function! s:RemoveEdgeFrom(dag, node)
|
||||
let successors = a:dag.successors(a:node)
|
||||
if len(successors) > 0
|
||||
let successor = remove(successors, 0)
|
||||
if len(successors) == 0
|
||||
" echomsg "finished with ->".a:node
|
||||
call remove(a:dag.table, a:node)
|
||||
endif
|
||||
return successor
|
||||
endif
|
||||
throw "No more edges from ".a:node
|
||||
endfunction
|
||||
function! s:Empty(dag)
|
||||
" echomsg "len="len(a:dag.table)
|
||||
return len(a:dag.table) == 0
|
||||
endfunction
|
||||
" }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker
|
338
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/list.vim
Normal file
338
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/list.vim
Normal file
@ -0,0 +1,338 @@
|
||||
"=============================================================================
|
||||
" $Id: list.vim 236 2010-06-01 00:43:34Z luc.hermitte $
|
||||
" File: autoload/lh/list.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 17th Apr 2007
|
||||
" Last Update: $Date: 2010-05-31 20:43:34 -0400 (Mon, 31 May 2010) $ (17th Apr 2007)
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Defines functions related to |Lists|
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.2.1:
|
||||
" (*) use :unlet in :for loop to support heterogeneous lists
|
||||
" (*) binary search algorithms (upper_bound, lower_bound, equal_range)
|
||||
" v2.2.0:
|
||||
" (*) new functions: lh#list#accumulate, lh#list#transform,
|
||||
" lh#list#transform_if, lh#list#find_if, lh#list#copy_if,
|
||||
" lh#list#subset, lh#list#intersect
|
||||
" (*) the functions are compatible with lh#function functors
|
||||
" v2.1.1:
|
||||
" (*) unique_sort
|
||||
" v2.0.7:
|
||||
" (*) Bug fix: lh#list#Match()
|
||||
" v2.0.6:
|
||||
" (*) lh#list#Find_if() supports search predicate, and start index
|
||||
" (*) lh#list#Match() supports start index
|
||||
" v2.0.0:
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#list#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#list#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # Public {{{2
|
||||
" Function: lh#list#Transform(input, output, action) {{{3
|
||||
" deprecated version
|
||||
function! lh#list#Transform(input, output, action)
|
||||
let new = map(copy(a:input), a:action)
|
||||
let res = extend(a:output,new)
|
||||
return res
|
||||
|
||||
for element in a:input
|
||||
let action = substitute(a:action, 'v:val','element', 'g')
|
||||
let res = eval(action)
|
||||
call add(a:output, res)
|
||||
unlet element " for heterogeneous lists
|
||||
endfor
|
||||
return a:output
|
||||
endfunction
|
||||
|
||||
function! lh#list#transform(input, output, action)
|
||||
for element in a:input
|
||||
let res = lh#function#execute(a:action, element)
|
||||
call add(a:output, res)
|
||||
unlet element " for heterogeneous lists
|
||||
endfor
|
||||
return a:output
|
||||
endfunction
|
||||
|
||||
function! lh#list#transform_if(input, output, action, predicate)
|
||||
for element in a:input
|
||||
if lh#function#execute(a:predicate, element)
|
||||
let res = lh#function#execute(a:action, element)
|
||||
call add(a:output, res)
|
||||
endif
|
||||
unlet element " for heterogeneous lists
|
||||
endfor
|
||||
return a:output
|
||||
endfunction
|
||||
|
||||
function! lh#list#copy_if(input, output, predicate)
|
||||
for element in a:input
|
||||
if lh#function#execute(a:predicate, element)
|
||||
call add(a:output, element)
|
||||
endif
|
||||
unlet element " for heterogeneous lists
|
||||
endfor
|
||||
return a:output
|
||||
endfunction
|
||||
|
||||
function! lh#list#accumulate(input, transformation, accumulator)
|
||||
let transformed = lh#list#transform(a:input, [], a:transformation)
|
||||
let res = lh#function#execute(a:accumulator, transformed)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#match(list, to_be_matched [, idx]) {{{3
|
||||
function! lh#list#match(list, to_be_matched, ...)
|
||||
let idx = (a:0>0) ? a:1 : 0
|
||||
while idx < len(a:list)
|
||||
if match(a:list[idx], a:to_be_matched) != -1
|
||||
return idx
|
||||
endif
|
||||
let idx += 1
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
function! lh#list#Match(list, to_be_matched, ...)
|
||||
let idx = (a:0>0) ? a:1 : 0
|
||||
return lh#list#match(a:list, a:to_be_matched, idx)
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
|
||||
function! lh#list#Find_if(list, predicate, ...)
|
||||
" Parameters
|
||||
let idx = 0
|
||||
let args = []
|
||||
if a:0 == 2
|
||||
let idx = a:2
|
||||
let args = a:1
|
||||
elseif a:0 == 1
|
||||
if type(a:1) == type([])
|
||||
let args = a:1
|
||||
elseif type(a:1) == type(42)
|
||||
let idx = a:1
|
||||
else
|
||||
throw "lh#list#Find_if: unexpected argument type"
|
||||
endif
|
||||
elseif a:0 != 0
|
||||
throw "lh#list#Find_if: unexpected number of arguments: lh#list#Find_if(list, predicate [, predicate-arguments] [, start-pos])"
|
||||
endif
|
||||
|
||||
" The search loop
|
||||
while idx != len(a:list)
|
||||
let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
|
||||
let predicate = substitute(predicate, 'v:\(\d\+\)_', 'args[\1-1]', 'g')
|
||||
let res = eval(predicate)
|
||||
if res | return idx | endif
|
||||
let idx += 1
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#find_if(list, predicate [, predicate-arguments] [, start-pos]) {{{3
|
||||
function! lh#list#find_if(list, predicate, ...)
|
||||
" Parameters
|
||||
let idx = 0
|
||||
let args = []
|
||||
if a:0 == 1
|
||||
let idx = a:1
|
||||
elseif a:0 != 0
|
||||
throw "lh#list#find_if: unexpected number of arguments: lh#list#find_if(list, predicate [, start-pos])"
|
||||
endif
|
||||
|
||||
" The search loop
|
||||
while idx != len(a:list)
|
||||
" let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
|
||||
let res = lh#function#execute(a:predicate, a:list[idx])
|
||||
if res | return idx | endif
|
||||
let idx += 1
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#lower_bound(sorted_list, value [, first[, last]]) {{{3
|
||||
function! lh#list#lower_bound(list, val, ...)
|
||||
let first = 0
|
||||
let last = len(a:list)
|
||||
if a:0 >= 1 | let first = a:1
|
||||
elseif a:0 >= 2 | let last = a:2
|
||||
elseif a:0 > 2
|
||||
throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value [, first[, last]])"
|
||||
endif
|
||||
|
||||
let len = last - first
|
||||
|
||||
while len > 0
|
||||
let half = len / 2
|
||||
let middle = first + half
|
||||
if a:list[middle] < a:val
|
||||
let first = middle + 1
|
||||
let len -= half + 1
|
||||
else
|
||||
let len = half
|
||||
endif
|
||||
endwhile
|
||||
return first
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#upper_bound(sorted_list, value [, first[, last]]) {{{3
|
||||
function! lh#list#upper_bound(list, val, ...)
|
||||
let first = 0
|
||||
let last = len(a:list)
|
||||
if a:0 >= 1 | let first = a:1
|
||||
elseif a:0 >= 2 | let last = a:2
|
||||
elseif a:0 > 2
|
||||
throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value [, first[, last]])"
|
||||
endif
|
||||
|
||||
let len = last - first
|
||||
|
||||
while len > 0
|
||||
let half = len / 2
|
||||
let middle = first + half
|
||||
if a:val < a:list[middle]
|
||||
let len = half
|
||||
else
|
||||
let first = middle + 1
|
||||
let len -= half + 1
|
||||
endif
|
||||
endwhile
|
||||
return first
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#equal_range(sorted_list, value [, first[, last]]) {{{3
|
||||
" @return [f, l], where
|
||||
" f : First position where {value} could be inserted
|
||||
" l : Last position where {value} could be inserted
|
||||
function! lh#list#equal_range(list, val, ...)
|
||||
let first = 0
|
||||
let last = len(a:list)
|
||||
|
||||
" Parameters
|
||||
if a:0 >= 1 | let first = a:1
|
||||
elseif a:0 >= 2 | let last = a:2
|
||||
elseif a:0 > 2
|
||||
throw "lh#list#equal_range: unexpected number of arguments: lh#list#equal_range(sorted_list, value [, first[, last]])"
|
||||
endif
|
||||
|
||||
" The search loop ( == STLPort's equal_range)
|
||||
|
||||
let len = last - first
|
||||
while len > 0
|
||||
let half = len / 2
|
||||
let middle = first + half
|
||||
if a:list[middle] < a:val
|
||||
let first = middle + 1
|
||||
let len -= half + 1
|
||||
elseif a:val < a:list[middle]
|
||||
let len = half
|
||||
else
|
||||
let left = lh#list#lower_bound(a:list, a:val, first, middle)
|
||||
let right = lh#list#upper_bound(a:list, a:val, middle+1, first+len)
|
||||
return [left, right]
|
||||
endif
|
||||
|
||||
" let predicate = substitute(a:predicate, 'v:val', 'a:list['.idx.']', 'g')
|
||||
" let res = lh#function#execute(a:predicate, a:list[idx])
|
||||
endwhile
|
||||
return [first, first]
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#unique_sort(list [, func]) {{{3
|
||||
" See also http://vim.wikia.com/wiki/Unique_sorting
|
||||
"
|
||||
" Works like sort(), optionally taking in a comparator (just like the
|
||||
" original), except that duplicate entries will be removed.
|
||||
" todo: support another argument that act as an equality predicate
|
||||
function! lh#list#unique_sort(list, ...)
|
||||
let dictionary = {}
|
||||
for i in a:list
|
||||
let dictionary[string(i)] = i
|
||||
endfor
|
||||
let result = []
|
||||
" echo join(values(dictionary),"\n")
|
||||
if ( exists( 'a:1' ) )
|
||||
let result = sort( values( dictionary ), a:1 )
|
||||
else
|
||||
let result = sort( values( dictionary ) )
|
||||
endif
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! lh#list#unique_sort2(list, ...)
|
||||
let list = copy(a:list)
|
||||
if ( exists( 'a:1' ) )
|
||||
call sort(list, a:1 )
|
||||
else
|
||||
call sort(list)
|
||||
endif
|
||||
if len(list) <= 1 | return list | endif
|
||||
let result = [ list[0] ]
|
||||
let last = list[0]
|
||||
let i = 1
|
||||
while i < len(list)
|
||||
if last != list[i]
|
||||
let last = list[i]
|
||||
call add(result, last)
|
||||
endif
|
||||
let i += 1
|
||||
endwhile
|
||||
return result
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#subset(list, indices) {{{3
|
||||
function! lh#list#subset(list, indices)
|
||||
let result=[]
|
||||
for e in a:indices
|
||||
call add(result, a:list[e])
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
" Function: lh#list#intersect(list1, list2) {{{3
|
||||
function! lh#list#intersect(list1, list2)
|
||||
let result = copy(a:list1)
|
||||
call filter(result, 'index(a:list2, v:val) >= 0')
|
||||
return result
|
||||
|
||||
for e in a:list1
|
||||
if index(a:list2, e) > 0
|
||||
call result(result, e)
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
384
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/menu.vim
Normal file
384
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/menu.vim
Normal file
@ -0,0 +1,384 @@
|
||||
"=============================================================================
|
||||
" $Id: menu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/menu.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 13th Oct 2006
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (28th Aug 2007)
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Defines the global function lh#menu#def_menu
|
||||
" Aimed at (ft)plugin writers.
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop this file into {rtp}/autoload/lh/
|
||||
" Requires Vim 7+
|
||||
" History:
|
||||
" v2.0.0: Moving to vim7
|
||||
" v2.0.1: :ToggleXxx echoes the new value
|
||||
" v2.2.0: Support environment variables
|
||||
" Only one :Toggle command is defined.
|
||||
" TODO:
|
||||
" Should the argument to :Toggle be simplified to use the variable
|
||||
" name instead ?
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
" ## Internal Variables {{{1
|
||||
let s:k_Toggle_cmd = 'Toggle'
|
||||
if !exists('s:toggle_commands')
|
||||
let s:toggle_commands = {}
|
||||
endif
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#menu#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#menu#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # Common stuff {{{2
|
||||
" Function: lh#menu#text({text}) {{{3
|
||||
" @return a text to be used in menus where "\" and spaces have been escaped.
|
||||
function! lh#menu#text(text)
|
||||
return escape(a:text, '\ ')
|
||||
endfunction
|
||||
|
||||
" # Toggling menu item {{{2
|
||||
" Function: s:Fetch({Data},{key}) {{{3
|
||||
" @param[in] Data Menu-item definition
|
||||
" @param[in] key Table table from which the result will be fetched
|
||||
" @return the current value, or text, whose index is Data.idx_crt_value.
|
||||
function! s:Fetch(Data, key)
|
||||
let len = len(a:Data[a:key])
|
||||
if a:Data.idx_crt_value >= len | let a:Data.idx_crt_value = 0 | endif
|
||||
let value = a:Data[a:key][a:Data.idx_crt_value]
|
||||
return value
|
||||
endfunction
|
||||
|
||||
" Function: s:Search({Data},{value}) {{{3
|
||||
" Searches for the index of {value} in {Data.values} list. Return 0 if not
|
||||
" found.
|
||||
function! s:Search(Data, value)
|
||||
let idx = 0
|
||||
while idx != len(a:Data.values)
|
||||
if a:value == a:Data.values[idx]
|
||||
" echo a:Data.variable . "[".idx."] == " . a:value
|
||||
return idx
|
||||
endif
|
||||
let idx = idx + 1
|
||||
endwhile
|
||||
" echo a:Data.variable . "[".-1."] == " . a:value
|
||||
return 0 " default is first element
|
||||
endfunction
|
||||
|
||||
" Function: s:Set({Data}) {{{3
|
||||
" @param[in,out] Data Menu item definition
|
||||
"
|
||||
" Sets the global variable associated to the menu item according to the item's
|
||||
" current value.
|
||||
function! s:Set(Data)
|
||||
let value = a:Data.values[a:Data.idx_crt_value]
|
||||
let variable = a:Data.variable
|
||||
if variable[0] == '$' " environment variabmes
|
||||
exe "let ".variable." = ".string(value)
|
||||
else
|
||||
let g:{variable} = value
|
||||
endif
|
||||
if has_key(a:Data, "actions")
|
||||
let l:Action = a:Data.actions[a:Data.idx_crt_value]
|
||||
if type(l:Action) == type(function('tr'))
|
||||
call l:Action()
|
||||
else
|
||||
exe l:Action
|
||||
endif
|
||||
endif
|
||||
return value
|
||||
endfunction
|
||||
|
||||
" Function: s:MenuKey({Data}) {{{3
|
||||
" @return the table name from which the current value name (to dsplay in the
|
||||
" menu) must be fetched.
|
||||
" Priority is given to the optional "texts" table over the madatory "values" table.
|
||||
function! s:MenuKey(Data)
|
||||
if has_key(a:Data, "texts")
|
||||
let menu_id = "texts"
|
||||
else
|
||||
let menu_id = "values"
|
||||
endif
|
||||
return menu_id
|
||||
endfunction
|
||||
|
||||
" Function: s:NextValue({Data}) {{{3
|
||||
" Change the value of the variable to the next in the list of value.
|
||||
" The menu, and the variable are updated in consequence.
|
||||
function! s:NextValue(Data)
|
||||
" Where the texts for values must be fetched
|
||||
let labels_key = s:MenuKey(a:Data)
|
||||
" Fetch the old current value
|
||||
let old = s:Fetch(a:Data, labels_key)
|
||||
|
||||
" Remove the entry from the menu
|
||||
call s:ClearMenu(a:Data.menu, old)
|
||||
|
||||
" Cycle/increment the current value
|
||||
let a:Data.idx_crt_value += 1
|
||||
" Fetch it
|
||||
let new = s:Fetch(a:Data,labels_key)
|
||||
" Add the updated entry in the menu
|
||||
call s:UpdateMenu(a:Data.menu, new, a:Data.command)
|
||||
" Update the binded global variable
|
||||
let value = s:Set(a:Data)
|
||||
echo a:Data.variable.'='.value
|
||||
endfunction
|
||||
|
||||
" Function: s:ClearMenu({Menu}, {text}) {{{3
|
||||
" Removes a menu item
|
||||
"
|
||||
" @param[in] Menu.priority Priority of the new menu-item
|
||||
" @param[in] Menu.name Name of the new menu-item
|
||||
" @param[in] text Text of the previous value of the variable binded
|
||||
function! s:ClearMenu(Menu, text)
|
||||
if has('gui_running')
|
||||
let name = substitute(a:Menu.name, '&', '', 'g')
|
||||
let cmd = 'unmenu '.lh#menu#text(name.'<tab>('.a:text.')')
|
||||
silent! exe cmd
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Function: s:UpdateMenu({Menu}, {text}, {command}) {{{3
|
||||
" Adds a new menu item, with the text associated to the current value in
|
||||
" braces.
|
||||
"
|
||||
" @param[in] Menu.priority Priority of the new menu-item
|
||||
" @param[in] Menu.name Name of the new menu-item
|
||||
" @param[in] text Text of the current value of the variable binded to
|
||||
" the menu-item
|
||||
" @param[in] command Toggle command to execute when the menu-item is selected
|
||||
function! s:UpdateMenu(Menu, text, command)
|
||||
if has('gui_running')
|
||||
let cmd = 'nnoremenu <silent> '.a:Menu.priority.' '.
|
||||
\ lh#menu#text(a:Menu.name.'<tab>('.a:text.')').
|
||||
\ ' :silent '.s:k_Toggle_cmd.' '.a:command."\<cr>"
|
||||
silent! exe cmd
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Function: s:SaveData({Data}) {{{3
|
||||
" @param Data Menu-item definition
|
||||
" Saves {Data} as s:Data{s:data_id++}. The definition will be used by
|
||||
" automatically generated commands.
|
||||
" @return s:data_id
|
||||
let s:data_id = 0
|
||||
function! s:SaveData(Data)
|
||||
let s:Data{s:data_id} = a:Data
|
||||
let id = s:data_id
|
||||
let s:data_id += 1
|
||||
return id
|
||||
endfunction
|
||||
|
||||
" Function: lh#menu#def_toggle_item({Data}) {{{3
|
||||
" @param Data.idx_crt_value
|
||||
" @param Data.definitions == [ {value:, menutext: } ]
|
||||
" @param Data.menu == { name:, position: }
|
||||
"
|
||||
" Sets a toggle-able menu-item defined by {Data}.
|
||||
"
|
||||
function! lh#menu#def_toggle_item(Data)
|
||||
" Save the menu data as an internal script variable
|
||||
let id = s:SaveData(a:Data)
|
||||
|
||||
" If the index of the current value hasn't been set, fetch it from the
|
||||
" associated variable
|
||||
if !has_key(a:Data, "idx_crt_value")
|
||||
" Fetch the value of the associated variable
|
||||
let value = lh#option#get(a:Data.variable, 0, 'g')
|
||||
" echo a:Data.variable . " <- " . value
|
||||
" Update the index of the current value
|
||||
let a:Data.idx_crt_value = s:Search(a:Data, value)
|
||||
endif
|
||||
|
||||
" Name of the auto-matically generated toggle command
|
||||
let cmdName = substitute(a:Data.menu.name, '[^a-zA-Z_]', '', 'g')
|
||||
" Lazy definition of the command
|
||||
if 2 != exists(':'.s:k_Toggle_cmd)
|
||||
exe 'command! -nargs=1 -complete=custom,lh#menu#_toggle_complete '
|
||||
\ . s:k_Toggle_cmd . ' :call s:Toggle(<f-args>)'
|
||||
endif
|
||||
" silent exe 'command! -nargs=0 '.cmdName.' :call s:NextValue(s:Data'.id.')'
|
||||
let s:toggle_commands[cmdName] = eval('s:Data'.id)
|
||||
let a:Data["command"] = cmdName
|
||||
|
||||
" Add the menu entry according to the current value
|
||||
call s:UpdateMenu(a:Data.menu, s:Fetch(a:Data, s:MenuKey(a:Data)), cmdName)
|
||||
" Update the associated global variable
|
||||
call s:Set(a:Data)
|
||||
endfunction
|
||||
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
function! s:Toggle(cmdName)
|
||||
if !has_key(s:toggle_commands, a:cmdName)
|
||||
throw "toggle-menu: unknown toggable variable ".a:cmdName
|
||||
endif
|
||||
let data = s:toggle_commands[a:cmdName]
|
||||
call s:NextValue(data)
|
||||
endfunction
|
||||
|
||||
function! lh#menu#_toggle_complete(ArgLead, CmdLine, CursorPos)
|
||||
return join(keys(s:toggle_commands),"\n")
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # IVN Menus {{{2
|
||||
" Function: s:CTRL_O({cmd}) {{{3
|
||||
" Build the command (sequence of ':ex commands') to be executed from
|
||||
" INSERT-mode.
|
||||
function! s:CTRL_O(cmd)
|
||||
return substitute(a:cmd, '\(^\|<CR>\):', '\1\<C-O>:', 'g')
|
||||
endfunction
|
||||
|
||||
" Function: lh#menu#is_in_visual_mode() {{{3
|
||||
function! lh#menu#is_in_visual_mode()
|
||||
return exists('s:is_in_visual_mode') && s:is_in_visual_mode
|
||||
endfunction
|
||||
|
||||
" Function: lh#menu#_CMD_and_clear_v({cmd}) {{{3
|
||||
" Internal function that executes the command and then clears the @v buffer
|
||||
" todo: save and restore @v,
|
||||
function! lh#menu#_CMD_and_clear_v(cmd)
|
||||
try
|
||||
let s:is_in_visual_mode = 1
|
||||
exe a:cmd
|
||||
finally
|
||||
let @v=''
|
||||
silent! unlet s:is_in_visual_mode
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" Function: s:Build_CMD({prefix},{cmd}) {{{3
|
||||
" build the exact command to execute regarding the mode it is dedicated
|
||||
function! s:Build_CMD(prefix, cmd)
|
||||
if a:cmd[0] != ':' | return ' ' . a:cmd
|
||||
endif
|
||||
if a:prefix[0] == "i" | return ' ' . <SID>CTRL_O(a:cmd)
|
||||
elseif a:prefix[0] == "n" | return ' ' . a:cmd
|
||||
elseif a:prefix[0] == "v"
|
||||
if match(a:cmd, ":VCall") == 0
|
||||
return substitute(a:cmd, ':VCall', ' :call', ''). "\<cr>gV"
|
||||
" gV exit select-mode if we where in it!
|
||||
else
|
||||
return
|
||||
\ " \"vy\<C-C>:call lh#menu#_CMD_and_clear_v('" .
|
||||
\ substitute(a:cmd, "<CR>$", '', '') ."')\<cr>"
|
||||
endif
|
||||
elseif a:prefix[0] == "c" | return " \<C-C>" . a:cmd
|
||||
else | return ' ' . a:cmd
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Function: lh#menu#map_all({map_type}, [{map args}...) {{{3
|
||||
" map the command to all the modes required
|
||||
function! lh#menu#map_all(map_type,...)
|
||||
let nore = (match(a:map_type, '[aincv]*noremap') != -1) ? "nore" : ""
|
||||
let prefix = matchstr(substitute(a:map_type, nore, '', ''), '[aincv]*')
|
||||
if a:1 == "<buffer>" | let i = 3 | let binding = a:1 . ' ' . a:2
|
||||
else | let i = 2 | let binding = a:1
|
||||
endif
|
||||
let binding = '<silent> ' . binding
|
||||
let cmd = a:{i}
|
||||
let i += 1
|
||||
while i <= a:0
|
||||
let cmd .= ' ' . a:{i}
|
||||
let i += 1
|
||||
endwhile
|
||||
let build_cmd = nore . 'map ' . binding
|
||||
while strlen(prefix)
|
||||
if prefix[0] == "a" | let prefix = "incv"
|
||||
else
|
||||
execute prefix[0] . build_cmd . <SID>Build_CMD(prefix[0],cmd)
|
||||
let prefix = strpart(prefix, 1)
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
" Function: lh#menu#make({prefix},{code},{text},{binding},...) {{{3
|
||||
" Build the menu and map its associated binding to all the modes required
|
||||
function! lh#menu#make(prefix, code, text, binding, ...)
|
||||
let nore = (match(a:prefix, '[aincv]*nore') != -1) ? "nore" : ""
|
||||
let prefix = matchstr(substitute(a:prefix, nore, '', ''), '[aincv]*')
|
||||
let b = (a:1 == "<buffer>") ? 1 : 0
|
||||
let i = b + 1
|
||||
let cmd = a:{i}
|
||||
let i += 1
|
||||
while i <= a:0
|
||||
let cmd .= ' ' . a:{i}
|
||||
let i += 1
|
||||
endwhile
|
||||
let build_cmd = nore . "menu <silent> " . a:code . ' ' . lh#menu#text(a:text)
|
||||
if strlen(a:binding) != 0
|
||||
let build_cmd .= '<tab>' .
|
||||
\ substitute(lh#menu#text(a:binding), '&', '\0\0', 'g')
|
||||
if b != 0
|
||||
call lh#menu#map_all(prefix.nore."map", ' <buffer> '.a:binding, cmd)
|
||||
else
|
||||
call lh#menu#map_all(prefix.nore."map", a:binding, cmd)
|
||||
endif
|
||||
endif
|
||||
if has("gui_running")
|
||||
while strlen(prefix)
|
||||
execute <SID>BMenu(b).prefix[0].build_cmd.<SID>Build_CMD(prefix[0],cmd)
|
||||
let prefix = strpart(prefix, 1)
|
||||
endwhile
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Function: s:BMenu({b}) {{{3
|
||||
" If <buffermenu.vim> is installed and the menu should be local, then the
|
||||
" apropriate string is returned.
|
||||
function! s:BMenu(b)
|
||||
let res = (a:b && exists(':Bmenu')
|
||||
\ && (1 == lh#option#get("want_buffermenu_or_global_disable", 1, "bg"))
|
||||
\) ? 'B' : ''
|
||||
" call confirm("BMenu(".a:b.")=".res, '&Ok', 1)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
" Function: lh#menu#IVN_make(...) {{{3
|
||||
function! lh#menu#IVN_make(code, text, binding, i_cmd, v_cmd, n_cmd, ...)
|
||||
" nore options
|
||||
let nore_i = (a:0 > 0) ? ((a:1 != 0) ? 'nore' : '') : ''
|
||||
let nore_v = (a:0 > 1) ? ((a:2 != 0) ? 'nore' : '') : ''
|
||||
let nore_n = (a:0 > 2) ? ((a:3 != 0) ? 'nore' : '') : ''
|
||||
"
|
||||
call lh#menu#make('i'.nore_i,a:code,a:text, a:binding, '<buffer>', a:i_cmd)
|
||||
call lh#menu#make('v'.nore_v,a:code,a:text, a:binding, '<buffer>', a:v_cmd)
|
||||
if strlen(a:n_cmd) != 0
|
||||
call lh#menu#make('n'.nore_n,a:code,a:text, a:binding, '<buffer>', a:n_cmd)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
107
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/option.vim
Normal file
107
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/option.vim
Normal file
@ -0,0 +1,107 @@
|
||||
"=============================================================================
|
||||
" $Id: option.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/option.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 24th Jul 2004
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (07th Oct 2006)
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Defines the global function lh#option#get().
|
||||
" Aimed at (ft)plugin writers.
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop this file into {rtp}/autoload/lh/
|
||||
" Requires Vim 7+
|
||||
" History:
|
||||
" v2.0.5
|
||||
" (*) lh#option#get_non_empty() manages Lists and Dictionaries
|
||||
" (*) lh#option#get() doesn't test emptyness anymore
|
||||
" v2.0.0
|
||||
" Code moved from {rtp}/macros/
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#option#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#option#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
" # Public {{{2
|
||||
" Function: lh#option#get(name, default [, scope]) {{{3
|
||||
" @return b:{name} if it exists, or g:{name} if it exists, or {default}
|
||||
" otherwise
|
||||
" The order of the variables checked can be specified through the optional
|
||||
" argument {scope}
|
||||
function! lh#option#get(name,default,...)
|
||||
let scope = (a:0 == 1) ? a:1 : 'bg'
|
||||
let name = a:name
|
||||
let i = 0
|
||||
while i != strlen(scope)
|
||||
if exists(scope[i].':'.name)
|
||||
" \ && (0 != strlen({scope[i]}:{name}))
|
||||
return {scope[i]}:{name}
|
||||
endif
|
||||
let i += 1
|
||||
endwhile
|
||||
return a:default
|
||||
endfunction
|
||||
function! lh#option#Get(name,default,...)
|
||||
let scope = (a:0 == 1) ? a:1 : 'bg'
|
||||
return lh#option#get(a:name, a:default, scope)
|
||||
endfunction
|
||||
|
||||
function! s:IsEmpty(variable)
|
||||
if type(a:variable) == type('string') | return 0 == strlen(a:variable)
|
||||
elseif type(a:variable) == type(42) | return 0 == a:variable
|
||||
elseif type(a:variable) == type([]) | return 0 == len(a:variable)
|
||||
elseif type(a:variable) == type({}) | return 0 == len(a:variable)
|
||||
else | return false
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Function: lh#option#get_non_empty(name, default [, scope]) {{{3
|
||||
" @return of b:{name}, g:{name}, or {default} the first which exists and is not empty
|
||||
" The order of the variables checked can be specified through the optional
|
||||
" argument {scope}
|
||||
function! lh#option#get_non_empty(name,default,...)
|
||||
let scope = (a:0 == 1) ? a:1 : 'bg'
|
||||
let name = a:name
|
||||
let i = 0
|
||||
while i != strlen(scope)
|
||||
if exists(scope[i].':'.name) && !s:IsEmpty({scope[i]}:{name})
|
||||
return {scope[i]}:{name}
|
||||
endif
|
||||
let i += 1
|
||||
endwhile
|
||||
return a:default
|
||||
endfunction
|
||||
function! lh#option#GetNonEmpty(name,default,...)
|
||||
let scope = (a:0 == 1) ? a:1 : 'bg'
|
||||
return lh#option#get_non_empty(a:name, a:default, scope)
|
||||
endfunction
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
308
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/path.vim
Normal file
308
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/path.vim
Normal file
@ -0,0 +1,308 @@
|
||||
"=============================================================================
|
||||
" $Id: path.vim 237 2010-06-01 00:44:35Z luc.hermitte $
|
||||
" File: autoload/lh/path.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 23rd Jan 2007
|
||||
" Last Update: 11th Feb 2008
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Functions related to the handling of pathnames
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop this file into {rtp}/autoload/lh
|
||||
" Requires Vim7+
|
||||
" History:
|
||||
" v 1.0.0 First Version
|
||||
" (*) Functions moved from searchInRuntimeTime
|
||||
" v 2.0.1
|
||||
" (*) lh#path#Simplify() becomes like |simplify()| except for trailing
|
||||
" v 2.0.2
|
||||
" (*) lh#path#SelectOne()
|
||||
" (*) lh#path#ToRelative()
|
||||
" v 2.0.3
|
||||
" (*) lh#path#GlobAsList()
|
||||
" v 2.0.4
|
||||
" (*) lh#path#StripStart()
|
||||
" v 2.0.5
|
||||
" (*) lh#path#StripStart() interprets '.' as getcwd()
|
||||
" v 2.2.0
|
||||
" (*) new functions: lh#path#common(), lh#path#to_dirname(),
|
||||
" lh#path#depth(), lh#path#relative_to(), lh#path#to_regex(),
|
||||
" lh#path#find()
|
||||
" (*) lh#path#simplify() fixed
|
||||
" (*) lh#path#to_relative() use simplify()
|
||||
" TODO:
|
||||
" (*) Decide what #depth('../../bar') shall return
|
||||
" (*) Fix #simplify('../../bar')
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
" Avoid global reinclusion {{{1
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
|
||||
"=============================================================================
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
let s:verbose = 0
|
||||
function! lh#path#verbose(...)
|
||||
if a:0 > 0 | let s:verbose = a:1 | endif
|
||||
return s:verbose
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#path#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"=============================================================================
|
||||
" # Public {{{2
|
||||
" Function: lh#path#simplify({pathname}) {{{3
|
||||
" Like |simplify()|, but also strip the leading './'
|
||||
" It seems unable to simplify '..\' when compiled without +shellslash
|
||||
function! lh#path#simplify(pathname)
|
||||
let pathname = simplify(a:pathname)
|
||||
let pathname = substitute(pathname, '^\%(\.[/\\]\)\+', '', '')
|
||||
let pathname = substitute(pathname, '\([/\\]\)\%(\.[/\\]\)\+', '\1', 'g')
|
||||
let pwd = getcwd().'/'
|
||||
let pathname = substitute(pathname, '^'.lh#path#to_regex(pwd), '', 'g')
|
||||
return pathname
|
||||
endfunction
|
||||
function! lh#path#Simplify(pathname)
|
||||
return lh#path#simplify(a:pathname)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#common({pathnames}) {{{3
|
||||
" Find the common leading path between all pathnames
|
||||
function! lh#path#common(pathnames)
|
||||
" assert(len(pathnames)) > 1
|
||||
let common = a:pathnames[0]
|
||||
let i = 1
|
||||
while i < len(a:pathnames)
|
||||
let fcrt = a:pathnames[i]
|
||||
" pathnames should not contain @
|
||||
let common = matchstr(common.'@@'.fcrt, '^\zs\(.*[/\\]\)\ze.\{-}@@\1.*$')
|
||||
if strlen(common) == 0
|
||||
" No need to further checks
|
||||
break
|
||||
endif
|
||||
let i += 1
|
||||
endwhile
|
||||
return common
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#strip_common({pathnames}) {{{3
|
||||
" Find the common leading path between all pathnames, and strip it
|
||||
function! lh#path#strip_common(pathnames)
|
||||
" assert(len(pathnames)) > 1
|
||||
let common = lh#path#common(a:pathnames)
|
||||
let l = strlen(common)
|
||||
if l == 0
|
||||
return a:pathnames
|
||||
else
|
||||
let pathnames = a:pathnames
|
||||
call map(pathnames, 'strpart(v:val, '.l.')' )
|
||||
return pathnames
|
||||
endif
|
||||
endfunction
|
||||
function! lh#path#StripCommon(pathnames)
|
||||
return lh#path#strip_common(a:pathnames)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#is_absolute_path({path}) {{{3
|
||||
function! lh#path#is_absolute_path(path)
|
||||
return a:path =~ '^/'
|
||||
\ . '\|^[a-zA-Z]:[/\\]'
|
||||
\ . '\|^[/\\]\{2}'
|
||||
" Unix absolute path
|
||||
" or Windows absolute path
|
||||
" or UNC path
|
||||
endfunction
|
||||
function! lh#path#IsAbsolutePath(path)
|
||||
return lh#path#is_absolute_path(a:path)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#is_url({path}) {{{3
|
||||
function! lh#path#is_url(path)
|
||||
" todo: support UNC paths and other urls
|
||||
return a:path =~ '^\%(https\=\|s\=ftp\|dav\|fetch\|file\|rcp\|rsynch\|scp\)://'
|
||||
endfunction
|
||||
function! lh#path#IsURL(path)
|
||||
return lh#path#is_url(a:path)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#select_one({pathnames},{prompt}) {{{3
|
||||
function! lh#path#select_one(pathnames, prompt)
|
||||
if len(a:pathnames) > 1
|
||||
let simpl_pathnames = deepcopy(a:pathnames)
|
||||
let simpl_pathnames = lh#path#strip_common(simpl_pathnames)
|
||||
let simpl_pathnames = [ '&Cancel' ] + simpl_pathnames
|
||||
" Consider guioptions+=c is case of difficulties with the gui
|
||||
let selection = confirm(a:prompt, join(simpl_pathnames,"\n"), 1, 'Question')
|
||||
let file = (selection == 1) ? '' : a:pathnames[selection-2]
|
||||
return file
|
||||
elseif len(a:pathnames) == 0
|
||||
return ''
|
||||
else
|
||||
return a:pathnames[0]
|
||||
endif
|
||||
endfunction
|
||||
function! lh#path#SelectOne(pathnames, prompt)
|
||||
return lh#path#select_one(a:pathnames, a:prompt)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#to_relative({pathname}) {{{3
|
||||
function! lh#path#to_relative(pathname)
|
||||
let newpath = fnamemodify(a:pathname, ':p:.')
|
||||
let newpath = simplify(newpath)
|
||||
return newpath
|
||||
endfunction
|
||||
function! lh#path#ToRelative(pathname)
|
||||
return lh#path#to_relative(a:pathname)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#to_dirname({dirname}) {{{3
|
||||
" todo: use &shellslash
|
||||
function! lh#path#to_dirname(dirname)
|
||||
let dirname = a:dirname . (a:dirname[-1:] =~ '[/\\]' ? '' : '/')
|
||||
return dirname
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#depth({dirname}) {{{3
|
||||
" todo: make a choice about "negative" paths like "../../foo"
|
||||
function! lh#path#depth(dirname)
|
||||
if empty(a:dirname) | return 0 | endif
|
||||
let dirname = lh#path#to_dirname(a:dirname)
|
||||
let dirname = lh#path#simplify(dirname)
|
||||
if lh#path#is_absolute_path(dirname)
|
||||
let dirname = matchstr(dirname, '.\{-}[/\\]\zs.*')
|
||||
endif
|
||||
let depth = len(substitute(dirname, '[^/\\]\+[/\\]', '§', 'g'))
|
||||
return depth
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#relative_to({from}, {to}) {{{3
|
||||
" @param two directories
|
||||
" @return a directories delta that ends with a '/' (may depends on
|
||||
" &shellslash)
|
||||
function! lh#path#relative_to(from, to)
|
||||
" let from = fnamemodify(a:from, ':p')
|
||||
" let to = fnamemodify(a:to , ':p')
|
||||
let from = lh#path#to_dirname(a:from)
|
||||
let to = lh#path#to_dirname(a:to )
|
||||
let [from, to] = lh#path#strip_common([from, to])
|
||||
let nb_up = lh#path#depth(from)
|
||||
return repeat('../', nb_up).to
|
||||
|
||||
" cannot rely on :cd (as it alters things, and doesn't work with
|
||||
" non-existant paths)
|
||||
let pwd = getcwd()
|
||||
exe 'cd '.a:to
|
||||
let res = lh#path#to_relative(a:from)
|
||||
exe 'cd '.pwd
|
||||
return res
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#glob_as_list({pathslist}, {expr}) {{{3
|
||||
function! s:GlobAsList(pathslist, expr)
|
||||
let sResult = globpath(a:pathslist, a:expr)
|
||||
let lResult = split(sResult, '\n')
|
||||
" workaround a non feature of wildignore: it does not ignore directories
|
||||
for ignored_pattern in split(&wildignore,',')
|
||||
if stridx(ignored_pattern,'/') != -1
|
||||
call filter(lResult, 'v:val !~ '.string(ignored_pattern))
|
||||
endif
|
||||
endfor
|
||||
return lResult
|
||||
endfunction
|
||||
|
||||
function! lh#path#glob_as_list(pathslist, expr)
|
||||
if type(a:expr) == type('string')
|
||||
return s:GlobAsList(a:pathslist, a:expr)
|
||||
elseif type(a:expr) == type([])
|
||||
let res = []
|
||||
for expr in a:expr
|
||||
call extend(res, s:GlobAsList(a:pathslist, expr))
|
||||
endfor
|
||||
return res
|
||||
else
|
||||
throw "Unexpected type for a:expression"
|
||||
endif
|
||||
endfunction
|
||||
function! lh#path#GlobAsList(pathslist, expr)
|
||||
return lh#path#glob_as_list(a:pathslist, a:expr)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#strip_start({pathname}, {pathslist}) {{{3
|
||||
" Strip occurrence of paths from {pathslist} in {pathname}
|
||||
" @param[in] {pathname} name to simplify
|
||||
" @param[in] {pathslist} list of pathname (can be a |string| of pathnames
|
||||
" separated by ",", of a |List|).
|
||||
function! lh#path#strip_start(pathname, pathslist)
|
||||
if type(a:pathslist) == type('string')
|
||||
" let strip_re = escape(a:pathslist, '\\.')
|
||||
" let strip_re = '^' . substitute(strip_re, ',', '\\|^', 'g')
|
||||
let pathslist = split(a:pathslist, ',')
|
||||
elseif type(a:pathslist) == type([])
|
||||
let pathslist = deepcopy(a:pathslist)
|
||||
else
|
||||
throw "Unexpected type for a:pathname"
|
||||
endif
|
||||
|
||||
" apply a realpath like operation
|
||||
let nb_paths = len(pathslist) " set before the loop
|
||||
let i = 0
|
||||
while i != nb_paths
|
||||
if pathslist[i] =~ '^\.\%(/\|$\)'
|
||||
let path2 = getcwd().pathslist[i][1:]
|
||||
call add(pathslist, path2)
|
||||
endif
|
||||
let i += 1
|
||||
endwhile
|
||||
" replace path separators by a regex that can match them
|
||||
call map(pathslist, 'substitute(v:val, "[\\\\/]", "[\\\\/]", "g")')
|
||||
" echomsg string(pathslist)
|
||||
" escape .
|
||||
call map(pathslist, '"^".escape(v:val, ".")')
|
||||
" build the strip regex
|
||||
let strip_re = join(pathslist, '\|')
|
||||
" echomsg strip_re
|
||||
let res = substitute(a:pathname, '\%('.strip_re.'\)[/\\]\=', '', '')
|
||||
return res
|
||||
endfunction
|
||||
function! lh#path#StripStart(pathname, pathslist)
|
||||
return lh#path#strip_start(a:pathname, a:pathslist)
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#to_regex({pathname}) {{{3
|
||||
function! lh#path#to_regex(path)
|
||||
let regex = substitute(a:path, '[/\\]', '[/\\\\]', 'g')
|
||||
return regex
|
||||
endfunction
|
||||
|
||||
" Function: lh#path#find({pathname}, {regex}) {{{3
|
||||
function! lh#path#find(paths, regex)
|
||||
let paths = (type(a:paths) == type([]))
|
||||
\ ? (a:paths)
|
||||
\ : split(a:paths,',')
|
||||
for path in paths
|
||||
if match(path ,a:regex) != -1
|
||||
return path
|
||||
endif
|
||||
endfor
|
||||
return ''
|
||||
endfunction
|
||||
"=============================================================================
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,93 @@
|
||||
"=============================================================================
|
||||
" $Id: position.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/position.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 05th Sep 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (05th Sep 2007)
|
||||
"------------------------------------------------------------------------
|
||||
" Description: «description»
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History: «history»
|
||||
" v1.0.0:
|
||||
" Creation
|
||||
" TODO:
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#position#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#position#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # Public {{{2
|
||||
" Function: lh#position#is_before {{{3
|
||||
" @param[in] positions as those returned from |getpos()|
|
||||
" @return whether lhs_pos is before rhs_pos
|
||||
function! lh#position#is_before(lhs_pos, rhs_pos)
|
||||
if a:lhs_pos[0] != a:rhs_pos[0]
|
||||
throw "Positions from incompatible buffers can't be ordered"
|
||||
endif
|
||||
"1 test lines
|
||||
"2 test cols
|
||||
let before
|
||||
\ = (a:lhs_pos[1] == a:rhs_pos[1])
|
||||
\ ? (a:lhs_pos[2] < a:rhs_pos[2])
|
||||
\ : (a:lhs_pos[1] < a:rhs_pos[1])
|
||||
return before
|
||||
endfunction
|
||||
function! lh#position#IsBefore(lhs_pos, rhs_pos)
|
||||
return lh#position#is_before(a:lhs_pos, a:rhs_pos)
|
||||
endfunction
|
||||
|
||||
|
||||
" Function: lh#position#char_at_mark {{{3
|
||||
" @return the character at a given mark (|mark|)
|
||||
function! lh#position#char_at_mark(mark)
|
||||
let c = getline(a:mark)[col(a:mark)-1]
|
||||
return c
|
||||
endfunction
|
||||
function! lh#position#CharAtMark(mark)
|
||||
return lh#position#char_at_mark(a:mark)
|
||||
endfunction
|
||||
|
||||
" Function: lh#position#char_at_pos {{{3
|
||||
" @return the character at a given position (|getpos()|)
|
||||
function! lh#position#char_at_pos(pos)
|
||||
let c = getline(a:pos[1])[col(a:pos[2])-1]
|
||||
return c
|
||||
endfunction
|
||||
function! lh#position#CharAtPos(pos)
|
||||
return lh#position#char_at_pos(a:pos)
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
138
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/syntax.vim
Normal file
138
bundle/vim-mundo/tests/bundled/lh-vim-lib/autoload/lh/syntax.vim
Normal file
@ -0,0 +1,138 @@
|
||||
"=============================================================================
|
||||
" $Id: syntax.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: autoload/lh/syntax.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 05th Sep 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (05th Sep 2007)
|
||||
"------------------------------------------------------------------------
|
||||
" Description: «description»
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History: «history»
|
||||
" v1.0.0:
|
||||
" Creation ;
|
||||
" Functions moved from lhVimSpell
|
||||
" TODO:
|
||||
" function, to inject "contained", see lhVimSpell approach
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! lh#syntax#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#syntax#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
" # Public {{{2
|
||||
" Functions: Show name of the syntax kind of a character {{{3
|
||||
function! lh#syntax#name_at(l,c, ...)
|
||||
let what = a:0 > 0 ? a:1 : 0
|
||||
return synIDattr(synID(a:l, a:c, what),'name')
|
||||
endfunction
|
||||
function! lh#syntax#NameAt(l,c, ...)
|
||||
let what = a:0 > 0 ? a:1 : 0
|
||||
return lh#syntax#name_at(a:l, a:c, what)
|
||||
endfunction
|
||||
|
||||
function! lh#syntax#name_at_mark(mark, ...)
|
||||
let what = a:0 > 0 ? a:1 : 0
|
||||
return lh#syntax#name_at(line(a:mark), col(a:mark), what)
|
||||
endfunction
|
||||
function! lh#syntax#NameAtMark(mark, ...)
|
||||
let what = a:0 > 0 ? a:1 : 0
|
||||
return lh#syntax#name_at_mark(a:mark, what)
|
||||
endfunction
|
||||
|
||||
" Functions: skip string, comment, character, doxygen {{{3
|
||||
func! lh#syntax#skip_at(l,c)
|
||||
return lh#syntax#name_at(a:l,a:c) =~? 'string\|comment\|character\|doxygen'
|
||||
endfun
|
||||
func! lh#syntax#SkipAt(l,c)
|
||||
return lh#syntax#skip_at(a:l,a:c)
|
||||
endfun
|
||||
|
||||
func! lh#syntax#skip()
|
||||
return lh#syntax#skip_at(line('.'), col('.'))
|
||||
endfun
|
||||
func! lh#syntax#Skip()
|
||||
return lh#syntax#skip()
|
||||
endfun
|
||||
|
||||
func! lh#syntax#skip_at_mark(mark)
|
||||
return lh#syntax#skip_at(line(a:mark), col(a:mark))
|
||||
endfun
|
||||
func! lh#syntax#SkipAtMark(mark)
|
||||
return lh#syntax#skip_at_mark(a:mark)
|
||||
endfun
|
||||
|
||||
" Function: Show current syntax kind {{{3
|
||||
command! SynShow echo 'hi<'.lh#syntax#name_at_mark('.',1).'> trans<'
|
||||
\ lh#syntax#name_at_mark('.',0).'> lo<'.
|
||||
\ synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name').'>'
|
||||
|
||||
|
||||
" Function: lh#syntax#list_raw(name) : string {{{3
|
||||
function! lh#syntax#list_raw(name)
|
||||
let a_save = @a
|
||||
try
|
||||
redir @a
|
||||
exe 'silent! syn list '.a:name
|
||||
redir END
|
||||
let res = @a
|
||||
finally
|
||||
let @a = a_save
|
||||
endtry
|
||||
return res
|
||||
endfunction
|
||||
|
||||
" Function: lh#syntax#list(name) : List {{{3
|
||||
function! lh#syntax#list(name)
|
||||
let raw = lh#syntax#list_raw(a:name)
|
||||
let res = []
|
||||
let lines = split(raw, '\n')
|
||||
let started = 0
|
||||
for l in lines
|
||||
if started
|
||||
let li = (l =~ 'links to') ? '' : l
|
||||
elseif l =~ 'xxx'
|
||||
let li = matchstr(l, 'xxx\s*\zs.*')
|
||||
let started = 1
|
||||
else
|
||||
let li = ''
|
||||
endif
|
||||
if strlen(li) != 0
|
||||
let li = substitute(li, 'contained\S*\|transparent\|nextgroup\|skipwhite\|skipnl\|skipempty', '', 'g')
|
||||
let kinds = split(li, '\s\+')
|
||||
call extend(res, kinds)
|
||||
endif
|
||||
endfor
|
||||
return res
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,42 @@
|
||||
"=============================================================================
|
||||
" $Id$
|
||||
" File: autoload/lh/visual.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 08th Sep 2008
|
||||
" Last Update: $Date$
|
||||
"------------------------------------------------------------------------
|
||||
" Helpers functions releated to the visual mode
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Drop it into {rtp}/autoload/lh/
|
||||
" Vim 7+ required.
|
||||
" History:
|
||||
" v2.0.6: First appearance
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
" Functions {{{1
|
||||
|
||||
" Function: lh#visual#selection() {{{3
|
||||
" @return the text currently selected
|
||||
function! lh#visual#selection()
|
||||
try
|
||||
let a_save = @a
|
||||
normal! gv"ay
|
||||
return @a
|
||||
finally
|
||||
let @a = a_save
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
1252
bundle/vim-mundo/tests/bundled/lh-vim-lib/doc/lh-vim-lib.txt
Normal file
1252
bundle/vim-mundo/tests/bundled/lh-vim-lib/doc/lh-vim-lib.txt
Normal file
File diff suppressed because it is too large
Load Diff
17
bundle/vim-mundo/tests/bundled/lh-vim-lib/lh-vim-lib.README
Normal file
17
bundle/vim-mundo/tests/bundled/lh-vim-lib/lh-vim-lib.README
Normal file
@ -0,0 +1,17 @@
|
||||
------------------
|
||||
lh-vim-lib 2.2.1
|
||||
------------------
|
||||
|
||||
lh-vim-lib is a library plugin for vim v7+. It is just a collection of
|
||||
functions that are meant to be used by script writers.
|
||||
|
||||
Audience : Vim script writers
|
||||
Requirements : Vim 7.1
|
||||
Required by : Just a few other plugins for the moment
|
||||
Author : Luc Hermitte
|
||||
License : GPL2
|
||||
More Help At : http://code.google.com/p/lh-vim/wiki/lhVimLib
|
||||
Vim script#214: http://www.vim.org/scripts/script.php?script_id=214
|
||||
Repository :
|
||||
svn checkout http://lh-vim.googlecode.com/svn/vim-lib/trunk lh-vim-lib
|
||||
|
@ -0,0 +1,83 @@
|
||||
"===========================================================================
|
||||
" $Id: menu-map.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: macros/menu-map.vim
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
"
|
||||
" Purpose: Define functions to build mappings and menus at the same time
|
||||
"
|
||||
" Version: 2.2.1
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $ (02nd Dec 2006)
|
||||
"
|
||||
" Last Changes: {{{
|
||||
" Version 2.0.0:
|
||||
" Moved to vim7,
|
||||
" Functions moved to {rtp}/autoload/
|
||||
" Version 1.6.2:
|
||||
" (*) Silent mappings and menus
|
||||
" Version 1.6. :
|
||||
" (*) Uses has('gui_running') instead of has('gui') to check if
|
||||
" we can generate the menu.
|
||||
" Version 1.5. :
|
||||
" (*) visual mappings launched from select-mode don't end with
|
||||
" text still selected -- applied to :VCalls
|
||||
" Version 1.4. :
|
||||
" (*) address obfuscated for spammers
|
||||
" (*) support the local option
|
||||
" b:want_buffermenu_or_global_disable if we don't want
|
||||
" buffermenu to be used systematically.
|
||||
" 0 -> buffer menu not used
|
||||
" 1 -> buffer menu used
|
||||
" 2 -> the VimL developper will use a global disable.
|
||||
" cf.: tex-maps.vim:: s:SimpleMenu()
|
||||
" and texmenus.vim
|
||||
" Version 1.3. :
|
||||
" (*) add continuation lines support ; cf 'cpoptions'
|
||||
" Version 1.2. :
|
||||
" (*) Code folded.
|
||||
" (*) Take advantage of buffermenu.vim if present for local
|
||||
" menus.
|
||||
" (*) If non gui is available, the menus won't be defined
|
||||
" Version 1.1. :
|
||||
" (*) Bug corrected :
|
||||
" vnore(map\|menu) does not imply v+n(map\|menu) any more
|
||||
" }}}
|
||||
"
|
||||
" Inspired By: A function from Benji Fisher
|
||||
"
|
||||
" TODO: (*) no menu if no gui.
|
||||
"
|
||||
"===========================================================================
|
||||
|
||||
if exists("g:loaded_menu_map") | finish | endif
|
||||
let g:loaded_menu_map = 1
|
||||
|
||||
"" line continuation used here ??
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
"=========================================================================
|
||||
" Commands {{{
|
||||
command! -nargs=+ -bang MAP map<bang> <args>
|
||||
command! -nargs=+ IMAP imap <args>
|
||||
command! -nargs=+ NMAP nmap <args>
|
||||
command! -nargs=+ CMAP cmap <args>
|
||||
command! -nargs=+ VMAP vmap <args>
|
||||
command! -nargs=+ AMAP
|
||||
\ call lh#menu#map_all('amap', <f-args>)
|
||||
|
||||
command! -nargs=+ -bang NOREMAP noremap<bang> <args>
|
||||
command! -nargs=+ INOREMAP inoremap <args>
|
||||
command! -nargs=+ NNOREMAP nnoremap <args>
|
||||
command! -nargs=+ CNOREMAP cnoremap <args>
|
||||
command! -nargs=+ VNOREMAP vnoremap <args>
|
||||
command! -nargs=+ ANOREMAP
|
||||
\ call lh#menu#map_all('anoremap', <f-args>)
|
||||
" }}}
|
||||
|
||||
" End !
|
||||
let &cpo = s:cpo_save
|
||||
finish
|
||||
|
||||
"=========================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,53 @@
|
||||
"=============================================================================
|
||||
" $Id: mk-lh-vim-lib.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: mk-lh-lib.vim
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
let s:version = '2.2.1'
|
||||
" Created: 06th Nov 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
cd <sfile>:p:h
|
||||
try
|
||||
let save_rtp = &rtp
|
||||
let &rtp = expand('<sfile>:p:h:h').','.&rtp
|
||||
exe '22,$MkVimball! lh-vim-lib-'.s:version
|
||||
set modifiable
|
||||
set buftype=
|
||||
finally
|
||||
let &rtp = save_rtp
|
||||
endtry
|
||||
finish
|
||||
autoload/lh/askvim.vim
|
||||
autoload/lh/buffer.vim
|
||||
autoload/lh/buffer/dialog.vim
|
||||
autoload/lh/command.vim
|
||||
autoload/lh/common.vim
|
||||
autoload/lh/encoding.vim
|
||||
autoload/lh/env.vim
|
||||
autoload/lh/event.vim
|
||||
autoload/lh/graph/tsort.vim
|
||||
autoload/lh/list.vim
|
||||
autoload/lh/menu.vim
|
||||
autoload/lh/option.vim
|
||||
autoload/lh/path.vim
|
||||
autoload/lh/position.vim
|
||||
autoload/lh/syntax.vim
|
||||
autoload/lh/visual.vim
|
||||
doc/lh-vim-lib.txt
|
||||
macros/menu-map.vim
|
||||
mkVba/mk-lh-vim-lib.vim
|
||||
plugin/let.vim
|
||||
plugin/lhvl.vim
|
||||
plugin/ui-functions.vim
|
||||
plugin/words_tools.vim
|
||||
tests/lh/function.vim
|
||||
tests/lh/list.vim
|
||||
tests/lh/path.vim
|
||||
tests/lh/test-Fargs2String.vim
|
||||
tests/lh/test-askmenu.vim
|
||||
tests/lh/test-command.vim
|
||||
tests/lh/test-menu-map.vim
|
||||
tests/lh/test-toggle-menu.vim
|
||||
tests/lh/topological-sort.vim
|
54
bundle/vim-mundo/tests/bundled/lh-vim-lib/plugin/let.vim
Normal file
54
bundle/vim-mundo/tests/bundled/lh-vim-lib/plugin/let.vim
Normal file
@ -0,0 +1,54 @@
|
||||
"=============================================================================
|
||||
" $Id: let.vim 239 2010-06-01 00:48:43Z luc.hermitte $
|
||||
" File: plugin/let.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 31st May 2010
|
||||
" Last Update: $Date: 2010-05-31 20:48:43 -0400 (Mon, 31 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Defines a command :LetIfUndef that sets a variable if undefined
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop this file into {rtp}/plugin
|
||||
" Requires Vim7+
|
||||
" History:
|
||||
" v2.2.1: first version of this command into lh-vim-lib
|
||||
" TODO:
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
" Avoid global reinclusion {{{1
|
||||
let s:k_version = 221
|
||||
if &cp || (exists("g:loaded_let")
|
||||
\ && (g:loaded_let >= s:k_version)
|
||||
\ && !exists('g:force_reload_let'))
|
||||
finish
|
||||
endif
|
||||
let g:loaded_let = s:k_version
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
" Avoid global reinclusion }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Commands and Mappings {{{1
|
||||
command! -nargs=+ LetIfUndef call s:LetIfUndef(<f-args>)
|
||||
" Commands and Mappings }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Functions {{{1
|
||||
" Note: most functions are best placed into
|
||||
" autoload/«your-initials»/«let».vim
|
||||
" Keep here only the functions are are required when the plugin is loaded,
|
||||
" like functions that help building a vim-menu for this plugin.
|
||||
function! s:LetIfUndef(var, value)
|
||||
if !exists(a:var)
|
||||
let {a:var} = eval(a:value)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
45
bundle/vim-mundo/tests/bundled/lh-vim-lib/plugin/lhvl.vim
Normal file
45
bundle/vim-mundo/tests/bundled/lh-vim-lib/plugin/lhvl.vim
Normal file
@ -0,0 +1,45 @@
|
||||
"=============================================================================
|
||||
" $Id: lhvl.vim 245 2010-09-19 22:40:10Z luc.hermitte $
|
||||
" File: plugin/lhvl.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 27th Apr 2010
|
||||
" Last Update: $Date: 2010-09-19 18:40:10 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Non-function resources from lh-vim-lib
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop the file into {rtp}/plugin
|
||||
" History:
|
||||
" v2.2.1 first version
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
" Avoid global reinclusion {{{1
|
||||
let s:k_version = 221
|
||||
if &cp || (exists("g:loaded_lhvl")
|
||||
\ && (g:loaded_lhvl >= s:k_version)
|
||||
\ && !exists('g:force_reload_lhvl'))
|
||||
finish
|
||||
endif
|
||||
let g:loaded_lhvl = s:k_version
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
" Avoid global reinclusion }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Commands and Mappings {{{1
|
||||
" Moved from lh-cpp
|
||||
command! PopSearch :call histdel('search', -1)| let @/=histget('search',-1)
|
||||
|
||||
" Commands and Mappings }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Functions {{{1
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,480 @@
|
||||
"=============================================================================
|
||||
" File: plugin/ui-functions.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" URL: http://hermitte.free.fr/vim/ressources/vimfiles/plugin/ui-functions.vim
|
||||
"
|
||||
" Version: 2.2.1
|
||||
" Created: 18th nov 2002
|
||||
" Last Update: 28th Nov 2007
|
||||
"------------------------------------------------------------------------
|
||||
" Description: Functions for the interaction with a User Interface.
|
||||
" The UI can be graphical or textual.
|
||||
" At first, this was designed to ease the syntax of
|
||||
" mu-template's templates.
|
||||
"
|
||||
" Option: {{{2
|
||||
" {[bg]:ui_type}
|
||||
" = "g\%[ui]",
|
||||
" = "t\%[ext]" ; the call must not be |:silent|
|
||||
" = "f\%[te]"
|
||||
" }}}2
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: Drop this into one of your {rtp}/plugin/ directories.
|
||||
" History: {{{2
|
||||
" v0.01 Initial Version
|
||||
" v0.02
|
||||
" (*) Code "factorisations"
|
||||
" (*) Help on <F1> enhanced.
|
||||
" (*) Small changes regarding the parameter accepted
|
||||
" (*) Function SWITCH
|
||||
" v0.03
|
||||
" (*) Small bug fix with INPUT()
|
||||
" v0.04
|
||||
" (*) New function: WHICH()
|
||||
" v0.05
|
||||
" (*) In vim7e, inputdialog() returns a trailing '\n'. INPUT() strips the
|
||||
" NL character.
|
||||
" v0.06
|
||||
" (*) :s/echoerr/throw/ => vim7 only
|
||||
" v2.2.0
|
||||
" (*) menu to switch the ui_type
|
||||
"
|
||||
" TODO: {{{2
|
||||
" (*) Save the hl-User1..9 before using them
|
||||
" (*) Possibility other than &statusline:
|
||||
" echohl User1 |echon "bla"|echohl User2|echon "bli"|echohl None
|
||||
" (*) Wraps too long choices-line (length > term-width)
|
||||
" (*) Add to the documentation: "don't use CTRL-C to abort !!"
|
||||
" (*) Look if I need to support 'wildmode'
|
||||
" (*) 3rd mode: return string for FTE
|
||||
" (*) 4th mode: interaction in a scratch buffer
|
||||
"
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" Avoid reinclusion {{{1
|
||||
"
|
||||
if exists("g:loaded_ui_functions") && !exists('g:force_reload_ui_functions')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_ui_functions = 1
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
" }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" External functions {{{1
|
||||
" Function: IF(var, then, else) {{{2
|
||||
function! IF(var,then, else)
|
||||
let o = s:Opt_type() " {{{3
|
||||
if o =~ 'g\%[ui]\|t\%[ext]' " {{{4
|
||||
return a:var ? a:then : a:else
|
||||
elseif o =~ 'f\%[te]' " {{{4
|
||||
return s:if_fte(a:var, a:then, a:else)
|
||||
else " {{{4
|
||||
throw "UI-Fns::IF(): Unkonwn user-interface style (".o.")"
|
||||
endif
|
||||
" }}}3
|
||||
endfunction
|
||||
|
||||
" Function: SWITCH(var, case, action [, case, action] [default_action]) {{{2
|
||||
function! SWITCH(var, ...)
|
||||
let o = s:Opt_type() " {{{3
|
||||
if o =~ 'g\%[ui]\|t\%[ext]' " {{{4
|
||||
let explicit_def = ((a:0 % 2) == 1)
|
||||
let default = explicit_def ? a:{a:0} : ''
|
||||
let i = a:0 - 1 - explicit_def
|
||||
while i > 0
|
||||
if a:var == a:{i}
|
||||
return a:{i+1}
|
||||
endif
|
||||
let i = i - 2
|
||||
endwhile
|
||||
return default
|
||||
elseif o =~ 'f\%[te]' " {{{4
|
||||
return s:if_fte(a:var, a:then, a:else)
|
||||
else " {{{4
|
||||
throw "UI-Fns::SWITCH(): Unkonwn user-interface style (".o.")"
|
||||
endif
|
||||
" }}}3
|
||||
endfunction
|
||||
|
||||
" Function: CONFIRM(text [, choices [, default [, type]]]) {{{2
|
||||
function! CONFIRM(text, ...)
|
||||
" 1- Check parameters {{{3
|
||||
if a:0 > 4 " {{{4
|
||||
throw "UI-Fns::CONFIRM(): too many parameters"
|
||||
return 0
|
||||
endif
|
||||
" build the parameters string {{{4
|
||||
let i = 1
|
||||
while i <= a:0
|
||||
if i == 1 | let params = 'a:{1}'
|
||||
else | let params = params. ',a:{'.i.'}'
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
" 2- Choose the correct way to execute according to the option {{{3
|
||||
let o = s:Opt_type()
|
||||
if o =~ 'g\%[ui]' " {{{4
|
||||
exe 'return confirm(a:text,'.params.')'
|
||||
elseif o =~ 't\%[ext]' " {{{4
|
||||
if !has('gui_running') && has('dialog_con')
|
||||
exe 'return confirm(a:text,'.params.')'
|
||||
else
|
||||
exe 'return s:confirm_text("none", a:text,'.params.')'
|
||||
endif
|
||||
elseif o =~ 'f\%[te]' " {{{4
|
||||
exe 'return s:confirm_fte(a:text,'.params.')'
|
||||
else " {{{4
|
||||
throw "UI-Fns::CONFIRM(): Unkonwn user-interface style (".o.")"
|
||||
endif
|
||||
" }}}3
|
||||
endfunction
|
||||
|
||||
" Function: INPUT(prompt [, default ]) {{{2
|
||||
function! INPUT(prompt, ...)
|
||||
" 1- Check parameters {{{3
|
||||
if a:0 > 4 " {{{4
|
||||
throw "UI-Fns::INPUT(): too many parameters"
|
||||
return 0
|
||||
endif
|
||||
" build the parameters string {{{4
|
||||
let i = 1 | let params = ''
|
||||
while i <= a:0
|
||||
if i == 1 | let params = 'a:{1}'
|
||||
else | let params = params. ',a:{'.i.'}'
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
" 2- Choose the correct way to execute according to the option {{{3
|
||||
let o = s:Opt_type()
|
||||
if o =~ 'g\%[ui]' " {{{4
|
||||
exe 'return matchstr(inputdialog(a:prompt,'.params.'), ".\\{-}\\ze\\n\\=$")'
|
||||
elseif o =~ 't\%[ext]' " {{{4
|
||||
exe 'return input(a:prompt,'.params.')'
|
||||
elseif o =~ 'f\%[te]' " {{{4
|
||||
exe 'return s:input_fte(a:prompt,'.params.')'
|
||||
else " {{{4
|
||||
throw "UI-Fns::INPUT(): Unkonwn user-interface style (".o.")"
|
||||
endif
|
||||
" }}}3
|
||||
endfunction
|
||||
|
||||
" Function: COMBO(prompt, choice [, ... ]) {{{2
|
||||
function! COMBO(prompt, ...)
|
||||
" 1- Check parameters {{{3
|
||||
if a:0 > 4 " {{{4
|
||||
throw "UI-Fns::COMBO(): too many parameters"
|
||||
return 0
|
||||
endif
|
||||
" build the parameters string {{{4
|
||||
let i = 1
|
||||
while i <= a:0
|
||||
if i == 1 | let params = 'a:{1}'
|
||||
else | let params = params. ',a:{'.i.'}'
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
" 2- Choose the correct way to execute according to the option {{{3
|
||||
let o = s:Opt_type()
|
||||
if o =~ 'g\%[ui]' " {{{4
|
||||
exe 'return confirm(a:prompt,'.params.')'
|
||||
elseif o =~ 't\%[ext]' " {{{4
|
||||
exe 'return s:confirm_text("combo", a:prompt,'.params.')'
|
||||
elseif o =~ 'f\%[te]' " {{{4
|
||||
exe 'return s:combo_fte(a:prompt,'.params.')'
|
||||
else " {{{4
|
||||
throw "UI-Fns::COMBO(): Unkonwn user-interface style (".o.")"
|
||||
endif
|
||||
" }}}3
|
||||
endfunction
|
||||
|
||||
" Function: WHICH(function, prompt, choice [, ... ]) {{{2
|
||||
function! WHICH(fn, prompt, ...)
|
||||
" 1- Check parameters {{{3
|
||||
" build the parameters string {{{4
|
||||
let i = 1
|
||||
while i <= a:0
|
||||
if i == 1 | let params = 'a:{1}'
|
||||
else | let params = params. ',a:{'.i.'}'
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
" 2- Execute the function {{{3
|
||||
exe 'let which = '.a:fn.'(a:prompt,'.params.')'
|
||||
if 0 >= which | return ''
|
||||
elseif 1 == which
|
||||
return substitute(matchstr(a:{1}, '^.\{-}\ze\%(\n\|$\)'), '&', '', 'g')
|
||||
else
|
||||
return substitute(
|
||||
\ matchstr(a:{1}, '^\%(.\{-}\n\)\{'.(which-1).'}\zs.\{-}\ze\%(\n\|$\)')
|
||||
\ , '&', '', 'g')
|
||||
endif
|
||||
" }}}3
|
||||
endfunction
|
||||
|
||||
" Function: CHECK(prompt, choice [, ... ]) {{{2
|
||||
function! CHECK(prompt, ...)
|
||||
" 1- Check parameters {{{3
|
||||
if a:0 > 4 " {{{4
|
||||
throw "UI-Fns::CHECK(): too many parameters"
|
||||
return 0
|
||||
endif
|
||||
" build the parameters string {{{4
|
||||
let i = 1
|
||||
while i <= a:0
|
||||
if i == 1 | let params = 'a:{1}'
|
||||
else | let params = params. ',a:{'.i.'}'
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
" 2- Choose the correct way to execute according to the option {{{3
|
||||
let o = s:Opt_type()
|
||||
if o =~ 'g\%[ui]' " {{{4
|
||||
exe 'return s:confirm_text("check", a:prompt,'.params.')'
|
||||
elseif o =~ 't\%[ext]' " {{{4
|
||||
exe 'return s:confirm_text("check", a:prompt,'.params.')'
|
||||
elseif o =~ 'f\%[te]' " {{{4
|
||||
exe 'return s:check_fte(a:prompt,'.params.')'
|
||||
else " {{{4
|
||||
throw "UI-Fns::CHECK(): Unkonwn user-interface style (".o.")"
|
||||
endif
|
||||
" }}}3
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Options setting {{{1
|
||||
let s:OptionData = {
|
||||
\ "variable": "ui_type",
|
||||
\ "idx_crt_value": 1,
|
||||
\ "values": ['gui', 'text', 'fte'],
|
||||
\ "menu": { "priority": '500.2700', "name": '&Plugin.&LH.&UI type'}
|
||||
\}
|
||||
|
||||
call lh#menu#def_toggle_item(s:OptionData)
|
||||
|
||||
" }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Internal functions {{{1
|
||||
function! s:Option(name, default) " {{{2
|
||||
if exists('b:ui_'.a:name) | return b:ui_{a:name}
|
||||
elseif exists('g:ui_'.a:name) | return g:ui_{a:name}
|
||||
else | return a:default
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:Opt_type() " {{{2
|
||||
return s:Option('type', 'gui')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" Function: s:status_line(current, hl [, choices] ) {{{2
|
||||
" a:current: current item
|
||||
" a:hl : Generic, Warning, Error
|
||||
function! s:status_line(current, hl, ...)
|
||||
" Highlightning {{{3
|
||||
if a:hl == "Generic" | let hl = '%1*'
|
||||
elseif a:hl == "Warning" | let hl = '%2*'
|
||||
elseif a:hl == "Error" | let hl = '%3*'
|
||||
elseif a:hl == "Info" | let hl = '%4*'
|
||||
elseif a:hl == "Question" | let hl = '%5*'
|
||||
else | let hl = '%1*'
|
||||
endif
|
||||
|
||||
" Build the string {{{3
|
||||
let sl_choices = '' | let i = 1
|
||||
while i <= a:0
|
||||
if i == a:current
|
||||
let sl_choices = sl_choices . ' '. hl .
|
||||
\ substitute(a:{i}, '&\(.\)', '%6*\1'.hl, '') . '%* '
|
||||
else
|
||||
let sl_choices = sl_choices . ' ' .
|
||||
\ substitute(a:{i}, '&\(.\)', '%6*\1%*', '') . ' '
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
" }}}3
|
||||
return sl_choices
|
||||
endfunction
|
||||
|
||||
|
||||
" Function: s:confirm_text(box, text [, choices [, default [, type]]]) {{{2
|
||||
function! s:confirm_text(box, text, ...)
|
||||
let help = "/<esc>/<s-tab>/<tab>/<left>/<right>/<cr>/<F1>"
|
||||
" 1- Retrieve the parameters {{{3
|
||||
let choices = ((a:0>=1) ? a:1 : '&Ok')
|
||||
let default = ((a:0>=2) ? a:2 : (('check' == a:box) ? 0 : 1))
|
||||
let type = ((a:0>=3) ? a:3 : 'Generic')
|
||||
if 'none' == a:box | let prefix = ''
|
||||
elseif 'combo' == a:box | let prefix = '( )_'
|
||||
elseif 'check' == a:box | let prefix = '[ ]_'
|
||||
let help = '/ '.help
|
||||
else | let prefix = ''
|
||||
endif
|
||||
|
||||
|
||||
" 2- Retrieve the proposed choices {{{3
|
||||
" Prepare the hot keys
|
||||
let i = 0
|
||||
while i != 26
|
||||
let hotkey_{nr2char(i+65)} = 0
|
||||
let i += 1
|
||||
endwhile
|
||||
let hotkeys = '' | let help_k = '/'
|
||||
" Parse the choices
|
||||
let i = 0
|
||||
while choices != ""
|
||||
let i = i + 1
|
||||
let item = matchstr(choices, "^.\\{-}\\ze\\(\n\\|$\\)")
|
||||
let choices = matchstr(choices, "\n\\zs.*$")
|
||||
" exe 'anoremenu ]'.a:text.'.'.item.' :let s:choice ='.i.'<cr>'
|
||||
if ('check' == a:box) && (strlen(default)>=i) && (1 == default[i-1])
|
||||
" let choice_{i} = '[X]' . substitute(item, '&', '', '')
|
||||
let choice_{i} = '[X]_' . item
|
||||
else
|
||||
" let choice_{i} = prefix . substitute(item, '&', '', '')
|
||||
let choice_{i} = prefix . item
|
||||
endif
|
||||
if i == 1
|
||||
let list_choices = 'choice_{1}'
|
||||
else
|
||||
let list_choices = list_choices . ',choice_{'.i.'}'
|
||||
endif
|
||||
" Update the hotkey.
|
||||
let key = toupper(matchstr(choice_{i}, '&\zs.\ze'))
|
||||
let hotkey_{key} = i
|
||||
let hotkeys = hotkeys . tolower(key) . toupper(key)
|
||||
let help_k = help_k . tolower(key)
|
||||
endwhile
|
||||
let nb_choices = i
|
||||
if default > nb_choices | let default = nb_choices | endif
|
||||
|
||||
" 3- Run an interactive text menu {{{3
|
||||
" Note: emenu can not be used through ":exe" {{{4
|
||||
" let wcm = &wcm
|
||||
" set wcm=<tab>
|
||||
" exe ':emenu ]'.a:text.'.'."<tab>"
|
||||
" let &wcm = wcm
|
||||
" 3.1- Preparations for the statusline {{{4
|
||||
" save the statusline
|
||||
let sl = &l:statusline
|
||||
" Color schemes for selected item {{{5
|
||||
:hi User1 term=inverse,bold cterm=inverse,bold ctermfg=Yellow
|
||||
\ guifg=Black guibg=Yellow
|
||||
:hi User2 term=inverse,bold cterm=inverse,bold ctermfg=LightRed
|
||||
\ guifg=Black guibg=LightRed
|
||||
:hi User3 term=inverse,bold cterm=inverse,bold ctermfg=Red
|
||||
\ guifg=Black guibg=Red
|
||||
:hi User4 term=inverse,bold cterm=inverse,bold ctermfg=Cyan
|
||||
\ guifg=Black guibg=Cyan
|
||||
:hi User5 term=inverse,bold cterm=inverse,bold ctermfg=LightYellow
|
||||
\ guifg=Black guibg=LightYellow
|
||||
:hi User6 term=inverse,bold cterm=inverse,bold ctermfg=LightGray
|
||||
\ guifg=DarkRed guibg=LightGray
|
||||
" }}}5
|
||||
|
||||
" 3.2- Interactive loop {{{4
|
||||
let help = "\r-- Keys available (".help_k.help.")"
|
||||
" item selected at the start
|
||||
let i = ('check' != a:box) ? default : 1
|
||||
let direction = 0 | let toggle = 0
|
||||
while 1
|
||||
if 'combo' == a:box
|
||||
let choice_{i} = substitute(choice_{i}, '^( )', '(*)', '')
|
||||
endif
|
||||
" Colored statusline
|
||||
" Note: unfortunately the 'statusline' is a global option, {{{
|
||||
" not a local one. I the hope that may change, as it does not provokes any
|
||||
" error, I use '&l:statusline'. }}}
|
||||
exe 'let &l:statusline=s:status_line(i, type,'. list_choices .')'
|
||||
if has(':redrawstatus')
|
||||
redrawstatus!
|
||||
else
|
||||
redraw!
|
||||
endif
|
||||
" Echo the current selection
|
||||
echo "\r". a:text.' '.substitute(choice_{i}, '&', '', '')
|
||||
" Wait the user to hit a key
|
||||
let key=getchar()
|
||||
let complType=nr2char(key)
|
||||
" If the key hit matched awaited keys ...
|
||||
if -1 != stridx(" \<tab>\<esc>\<enter>".hotkeys,complType) ||
|
||||
\ (key =~ "\<F1>\\|\<right>\\|\<left>\\|\<s-tab>")
|
||||
if key == "\<F1>" " Help {{{5
|
||||
redraw!
|
||||
echohl StatusLineNC
|
||||
echo help
|
||||
echohl None
|
||||
let key=getchar()
|
||||
let complType=nr2char(key)
|
||||
endif
|
||||
" TODO: support CTRL-D
|
||||
if complType == "\<enter>" " Validate {{{5
|
||||
break
|
||||
elseif complType == " " " check box {{{5
|
||||
let toggle = 1
|
||||
elseif complType == "\<esc>" " Abort {{{5
|
||||
let i = -1 | break
|
||||
elseif complType == "\<tab>" || key == "\<right>" " Next {{{5
|
||||
let direction = 1
|
||||
elseif key =~ "\<left>\\|\<s-tab>" " Previous {{{5
|
||||
let direction = -1
|
||||
elseif -1 != stridx(hotkeys, complType ) " Hotkeys {{{5
|
||||
if '' == complType | continue | endif
|
||||
let direction = hotkey_{toupper(complType)} - i
|
||||
let toggle = 1
|
||||
" else
|
||||
endif
|
||||
" }}}5
|
||||
endif
|
||||
if direction != 0 " {{{5
|
||||
if 'combo' == a:box
|
||||
let choice_{i} = substitute(choice_{i}, '^(\*)', '( )', '')
|
||||
endif
|
||||
let i = i + direction
|
||||
if i > nb_choices | let i = 1
|
||||
elseif i == 0 | let i = nb_choices
|
||||
endif
|
||||
let direction = 0
|
||||
endif
|
||||
if toggle == 1 " {{{5
|
||||
if 'check' == a:box
|
||||
let choice_{i} = ((choice_{i}[1] == ' ')? '[X]' : '[ ]')
|
||||
\ . strpart(choice_{i}, 3)
|
||||
endif
|
||||
let toggle = 0
|
||||
endif
|
||||
endwhile " }}}4
|
||||
" 4- Terminate {{{3
|
||||
" Clear screen
|
||||
redraw!
|
||||
|
||||
" Restore statusline
|
||||
let &l:statusline=sl
|
||||
" Return
|
||||
if (i == -1) || ('check' != a:box)
|
||||
return i
|
||||
else
|
||||
let r = '' | let i = 1
|
||||
while i <= nb_choices
|
||||
let r = r . ((choice_{i}[1] == 'X') ? '1' : '0')
|
||||
let i = i + 1
|
||||
endwhile
|
||||
return r
|
||||
endif
|
||||
endfunction
|
||||
" }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Functions that insert fte statements {{{1
|
||||
" Function: s:if_fte(var, then, else) {{{2
|
||||
" Function: s:confirm_fte(text, [, choices [, default [, type]]]) {{{2
|
||||
" Function: s:input_fte(prompt [, default]) {{{2
|
||||
" Function: s:combo_fte(prompt, choice [, ...]) {{{2
|
||||
" Function: s:check_fte(prompt, choice [, ...]) {{{2
|
||||
" }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
104
bundle/vim-mundo/tests/bundled/lh-vim-lib/plugin/words_tools.vim
Normal file
104
bundle/vim-mundo/tests/bundled/lh-vim-lib/plugin/words_tools.vim
Normal file
@ -0,0 +1,104 @@
|
||||
" File: plugin/words_tools.vim
|
||||
" Author: Luc Hermitte <hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" URL: http://hermitte.free.fr/vim/ressources/vim_dollar/plugin/words_tools.vim
|
||||
"
|
||||
" Last Update: 14th nov 2002
|
||||
" Purpose: Define functions better than expand("<cword>")
|
||||
"
|
||||
" Note: They are expected to be used in insert mode (thanks to <c-r>
|
||||
" or <c-o>)
|
||||
"
|
||||
"===========================================================================
|
||||
|
||||
" Return the current keyword, uses spaces to delimitate {{{1
|
||||
function! GetNearestKeyword()
|
||||
let c = col ('.')-1
|
||||
let ll = getline('.')
|
||||
let ll1 = strpart(ll,0,c)
|
||||
let ll1 = matchstr(ll1,'\k*$')
|
||||
let ll2 = strpart(ll,c,strlen(ll)-c+1)
|
||||
let ll2 = matchstr(ll2,'^\k*')
|
||||
" let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
|
||||
return ll1.ll2
|
||||
endfunction
|
||||
|
||||
" Return the current word, uses spaces to delimitate {{{1
|
||||
function! GetNearestWord()
|
||||
let c = col ('.')-1
|
||||
let l = line('.')
|
||||
let ll = getline(l)
|
||||
let ll1 = strpart(ll,0,c)
|
||||
let ll1 = matchstr(ll1,'\S*$')
|
||||
let ll2 = strpart(ll,c,strlen(ll)-c+1)
|
||||
let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
|
||||
""echo ll1.ll2
|
||||
return ll1.ll2
|
||||
endfunction
|
||||
|
||||
" Return the word before the cursor, uses spaces to delimitate {{{1
|
||||
" Rem : <cword> is the word under or after the cursor
|
||||
function! GetCurrentWord()
|
||||
let c = col ('.')-1
|
||||
let l = line('.')
|
||||
let ll = getline(l)
|
||||
let ll1 = strpart(ll,0,c)
|
||||
let ll1 = matchstr(ll1,'\S*$')
|
||||
if strlen(ll1) == 0
|
||||
return ll1
|
||||
else
|
||||
let ll2 = strpart(ll,c,strlen(ll)-c+1)
|
||||
let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
|
||||
return ll1.ll2
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Return the keyword before the cursor, uses \k to delimitate {{{1
|
||||
" Rem : <cword> is the word under or after the cursor
|
||||
function! GetCurrentKeyword()
|
||||
let c = col ('.')-1
|
||||
let l = line('.')
|
||||
let ll = getline(l)
|
||||
let ll1 = strpart(ll,0,c)
|
||||
let ll1 = matchstr(ll1,'\k*$')
|
||||
if strlen(ll1) == 0
|
||||
return ll1
|
||||
else
|
||||
let ll2 = strpart(ll,c,strlen(ll)-c+1)
|
||||
let ll2 = matchstr(ll2,'^\k*')
|
||||
" let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
|
||||
return ll1.ll2
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Extract the word before the cursor, {{{1
|
||||
" use keyword definitions, skip latter spaces (see "bla word_accepted ")
|
||||
function! GetPreviousWord()
|
||||
let lig = getline(line('.'))
|
||||
let lig = strpart(lig,0,col('.')-1)
|
||||
return matchstr(lig, '\<\k*\>\s*$')
|
||||
endfunction
|
||||
|
||||
" GetLikeCTRL_W() retrieves the characters that i_CTRL-W deletes. {{{1
|
||||
" Initial need by Hari Krishna Dara <hari_vim@yahoo.com>
|
||||
" Last ver:
|
||||
" Pb: "if strlen(w) == " --> ") == " instead of just "== ".
|
||||
" There still exists a bug regarding the last char of a line. VIM bug ?
|
||||
function! GetLikeCTRL_W()
|
||||
let lig = getline(line('.'))
|
||||
let lig = strpart(lig,0,col('.')-1)
|
||||
" treat ending spaces apart.
|
||||
let s = matchstr(lig, '\s*$')
|
||||
let lig = strpart(lig, 0, strlen(lig)-strlen(s))
|
||||
" First case : last characters belong to a "word"
|
||||
let w = matchstr(lig, '\<\k\+\>$')
|
||||
if strlen(w) == 0
|
||||
" otherwise, they belong to a "non word" (without any space)
|
||||
let w = substitute(lig, '.*\(\k\|\s\)', '', 'g')
|
||||
endif
|
||||
return w . s
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
"========================================================================
|
||||
" vim60: set fdm=marker:
|
284
bundle/vim-mundo/tests/bundled/lh-vim-lib/tests/lh/function.vim
Normal file
284
bundle/vim-mundo/tests/bundled/lh-vim-lib/tests/lh/function.vim
Normal file
@ -0,0 +1,284 @@
|
||||
"=============================================================================
|
||||
" $Id: function.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: tests/lh/function.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 03rd Nov 2008
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Tests for autoload/lh/function.vim
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
UTSuite [lh-vim-lib] Testing lh#function plugin
|
||||
|
||||
runtime autoload/lh/function.vim
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
function! Test(...)
|
||||
let nb = len(a:000)
|
||||
" echo "test(".nb.':' .join(a:000, ' -- ')')'
|
||||
let i =0
|
||||
while i!= len(a:000)
|
||||
echo "Test: type(".i.")=".type(a:000[i]).' --> '. string(a:000[i])
|
||||
let i += 1
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! Print(...)
|
||||
let res = lh#list#accumulate([1,2,'foo'], 'string', 'join(v:1_, " ## ")')
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! Id(...)
|
||||
return copy(a:000)
|
||||
endfunction
|
||||
|
||||
function! s:TestId()
|
||||
let r = Id(1, 'string', [0], [[1]], {'ffo':42}, function('exists'), 1.2)
|
||||
Assert! len(r) == 7
|
||||
Assert! should#be#number (r[0])
|
||||
Assert! should#be#string (r[1])
|
||||
Assert! should#be#list (r[2])
|
||||
Assert! should#be#list (r[3])
|
||||
Assert! should#be#dict (r[4])
|
||||
Assert! should#be#funcref(r[5])
|
||||
Assert! should#be#float (r[6])
|
||||
Assert r[0] == 1
|
||||
Assert r[1] == 'string'
|
||||
Assert r[2] == [0]
|
||||
Assert r[3] == [[1]]
|
||||
Assert r[4].ffo == 42
|
||||
Assert r[5] == function('exists')
|
||||
Assert r[6] == 1.2
|
||||
endfunction
|
||||
|
||||
function! s:Test_bind()
|
||||
" lh#function#bind + lh#function#execute
|
||||
let rev4 = lh#function#bind(function('Id'), 'v:4_', 42, 'v:3_', 'v:2_', 'v:1_')
|
||||
let r = lh#function#execute(rev4, 1,'two','three', [4,5])
|
||||
Assert! len(r) == 5
|
||||
Assert! should#be#list (r[0])
|
||||
Assert! should#be#number (r[1])
|
||||
Assert! should#be#string (r[2])
|
||||
Assert! should#be#string (r[3])
|
||||
Assert! should#be#number (r[4])
|
||||
|
||||
Assert r[0] == [4,5]
|
||||
Assert r[1] == 42
|
||||
Assert r[2] == 'three'
|
||||
Assert r[3] == 'two'
|
||||
Assert r[4] == 1
|
||||
endfunction
|
||||
|
||||
function! s:Test_bind_compound_vars()
|
||||
" lh#function#bind + lh#function#execute
|
||||
let rev4 = lh#function#bind(function('Id'), 'v:4_', 'v:1_ . v:2_', 'v:3_', 'v:2_', 'v:1_')
|
||||
let r = lh#function#execute(rev4, 1,'two','three', [4,5])
|
||||
Assert! len(r) == 5
|
||||
Assert! should#be#list (r[0])
|
||||
Assert! should#be#string (r[1])
|
||||
Assert! should#be#string (r[2])
|
||||
Assert! should#be#string (r[3])
|
||||
Assert! should#be#number (r[4])
|
||||
|
||||
Assert r[0] == [4,5]
|
||||
Assert r[1] == '1two'
|
||||
Assert r[2] == 'three'
|
||||
Assert r[3] == 'two'
|
||||
Assert r[4] == 1
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:Test_execute_func_string_name()
|
||||
" function name as string
|
||||
let r = lh#function#execute('Id', 1,'two',3)
|
||||
Assert! len(r) == 3
|
||||
Assert! should#be#number (r[0])
|
||||
Assert! should#be#string (r[1])
|
||||
Assert! should#be#number (r[2])
|
||||
Assert r[0] == 1
|
||||
Assert r[1] == 'two'
|
||||
Assert r[2] == 3
|
||||
endfunction
|
||||
|
||||
function! s:Test_execute_string_expr()
|
||||
" exp as binded-string
|
||||
let r = lh#function#execute('Id(12,len(v:2_).v:2_, 42, v:3_, v:1_)', 1,'two',3)
|
||||
Assert! len(r) == 5
|
||||
Assert! should#be#number (r[0])
|
||||
Assert! should#be#string (r[1])
|
||||
Assert! should#be#number (r[2])
|
||||
Assert! should#be#number (r[3])
|
||||
Assert! should#be#number (r[4])
|
||||
Assert r[0] == 12
|
||||
Assert r[1] == len('two').'two'
|
||||
Assert r[2] == 42
|
||||
Assert r[3] == 3
|
||||
Assert r[4] == 1
|
||||
endfunction
|
||||
|
||||
function! s:Test_execute_func()
|
||||
" calling a function() + bind
|
||||
let r = lh#function#execute(function('Id'), 1,'two','v:1_',['a',42])
|
||||
Assert! len(r) == 4
|
||||
Assert! should#be#number (r[0])
|
||||
Assert! should#be#string (r[1])
|
||||
Assert! should#be#string (r[2])
|
||||
Assert! should#be#list (r[3])
|
||||
Assert r[0] == 1
|
||||
Assert r[1] == 'two'
|
||||
Assert r[2] == 'v:1_'
|
||||
Assert r[3] == ['a', 42]
|
||||
endfunction
|
||||
"------------------------------------------------------------------------
|
||||
function! s:Test_bind_func_string_name_AND_execute()
|
||||
" function name as string
|
||||
let rev3 = lh#function#bind('Id', 'v:3_', 12, 'v:2_', 'v:1_')
|
||||
let r = lh#function#execute(rev3, 1,'two',3)
|
||||
|
||||
Assert! len(r) == 4
|
||||
Assert! should#be#number (r[0])
|
||||
Assert! should#be#number (r[1])
|
||||
Assert! should#be#string (r[2])
|
||||
Assert! should#be#number (r[3])
|
||||
Assert r[0] == 3
|
||||
Assert r[1] == 12
|
||||
Assert r[2] == 'two'
|
||||
Assert r[3] == 1
|
||||
endfunction
|
||||
|
||||
function! s:Test_bind_string_expr_AND_execute()
|
||||
" expressions as string
|
||||
let rev3 = lh#function#bind('Id(12,len(v:2_).v:2_, 42, v:3_, v:1_)')
|
||||
let r = lh#function#execute(rev3, 1,'two',3)
|
||||
Assert! len(r) == 5
|
||||
Assert! should#be#number (r[0])
|
||||
Assert! should#be#string (r[1])
|
||||
Assert! should#be#number (r[2])
|
||||
Assert! should#be#number (r[3])
|
||||
Assert! should#be#number (r[4])
|
||||
Assert r[0] == 12
|
||||
Assert r[1] == len('two').'two'
|
||||
Assert r[2] == 42
|
||||
Assert r[3] == 3
|
||||
Assert r[4] == 1
|
||||
endfunction
|
||||
|
||||
function! s:Test_double_bind_func_name()
|
||||
let f1 = lh#function#bind('Id', 1, 2, 'v:1_', 4, 'v:2_')
|
||||
" Comment "f1=".string(f1)
|
||||
let r = lh#function#execute(f1, 3, 5)
|
||||
Assert! len(r) == 5
|
||||
let i = 0
|
||||
while i != len(r)
|
||||
Assert! should#be#number (r[i])
|
||||
Assert r[i] == i+1
|
||||
let i += 1
|
||||
endwhile
|
||||
|
||||
" f2
|
||||
let f2 = lh#function#bind(f1, 'v:1_', 5)
|
||||
" Comment "f2=f1(v:1_, 5)=".string(f2)
|
||||
let r = lh#function#execute(f2, 3)
|
||||
Assert! len(r) == 5
|
||||
let i = 0
|
||||
while i != len(r)
|
||||
Assert! should#be#number (r[i])
|
||||
" echo "?? ".(r[i])."==".(i+1)
|
||||
Assert r[i] == i+1
|
||||
let i += 1
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:Test_double_bind_func()
|
||||
let f1 = lh#function#bind(function('Id'), 1, 2, 'v:1_', 4, 'v:2_')
|
||||
" Comment "f1=".string(f1)
|
||||
let r = lh#function#execute(f1, 3, 5)
|
||||
Assert! len(r) == 5
|
||||
let i = 0
|
||||
while i != len(r)
|
||||
Assert! should#be#number (r[i])
|
||||
Assert r[i] == i+1
|
||||
let i += 1
|
||||
endwhile
|
||||
|
||||
" f2
|
||||
let f2 = lh#function#bind(f1, 'v:1_', 5)
|
||||
" Comment "f2=f1(v:1_, 5)=".string(f2)
|
||||
let r = lh#function#execute(f2, 3)
|
||||
Assert! len(r) == 5
|
||||
let i = 0
|
||||
while i != len(r)
|
||||
Assert! should#be#number (r[i])
|
||||
Assert r[i] == i+1
|
||||
let i += 1
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:Test_double_bind_func_cplx()
|
||||
let s:bar = "bar"
|
||||
let f1 = lh#function#bind(function('Id'), 1, 2, 'v:1_', 4, 'v:2_', 'v:3_', 'v:4_', 'v:5_', 'v:6_', 'v:7_')
|
||||
" Comment "f1=".string(f1)
|
||||
let f2 = lh#function#bind(f1, 'v:1_', 5, 'foo', s:bar, 'len(s:bar.v:1_)+v:1_', [1,2], '[v:1_, v:2_]')
|
||||
" Comment "f2=f1(v:1_, 5)=".string(f2)
|
||||
|
||||
let r = lh#function#execute(f2, 42, "foo")
|
||||
Assert! 0 && "not ready"
|
||||
Comment "2bcpl# ".string(r)
|
||||
endfunction
|
||||
|
||||
function! s:Test_double_bind_expr()
|
||||
let f1 = lh#function#bind('Id(1, 2, v:1_, v:3_, v:2_)')
|
||||
Comment "2be# f1=".string(f1)
|
||||
let r = lh#function#execute(f1, 3, 5, 4)
|
||||
Comment "2be# ".string(r)
|
||||
Assert! len(r) == 5
|
||||
let i = 0
|
||||
while i != len(r)
|
||||
Assert! should#be#number (r[i])
|
||||
Assert r[i] == i+1
|
||||
let i += 1
|
||||
endwhile
|
||||
|
||||
" f2
|
||||
let f2 = lh#function#bind(f1, 'v:1_', '"foo"', [])
|
||||
Comment "2be# f2=f1(v:1_, 5)=".string(f2)
|
||||
let r = lh#function#execute(f2, 3)
|
||||
Comment "2be# ".string(r)
|
||||
Assert! len(r) == 5
|
||||
let i = 0
|
||||
while i != len(r)-2
|
||||
Assert! should#be#number (r[i])
|
||||
Assert r[i] == i+1
|
||||
let i += 1
|
||||
endwhile
|
||||
|
||||
Assert! should#be#list (r[-2])
|
||||
Assert r[-2] == []
|
||||
Assert! should#be#string (r[-1])
|
||||
Assert r[-1] == 'foo'
|
||||
endfunction
|
||||
|
||||
"todo: write double-binded tests for all kind of binded parameters:
|
||||
" 'len(g:bar)'
|
||||
" 42
|
||||
" []
|
||||
" v:1_ + len(v:2_.v:3_)
|
||||
" '"foo"'
|
||||
" v:1_
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
165
bundle/vim-mundo/tests/bundled/lh-vim-lib/tests/lh/list.vim
Normal file
165
bundle/vim-mundo/tests/bundled/lh-vim-lib/tests/lh/list.vim
Normal file
@ -0,0 +1,165 @@
|
||||
"=============================================================================
|
||||
" $Id: list.vim 238 2010-06-01 00:47:16Z luc.hermitte $
|
||||
" File: tests/lh/list.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 19th Nov 2008
|
||||
" Last Update: $Date: 2010-05-31 20:47:16 -0400 (Mon, 31 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Tests for autoload/lh/list.vim
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
UTSuite [lh-vim-lib] Testing lh#list functions
|
||||
|
||||
runtime autoload/lh/function.vim
|
||||
runtime autoload/lh/list.vim
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
" Find_if
|
||||
function! s:Test_Find_If_string_predicate()
|
||||
:let b = { 'min': 12, 'max': 42 }
|
||||
:let l = [ 1, 5, 48, 25, 5, 28, 6]
|
||||
:let i = lh#list#Find_if(l, 'v:val>v:1_.min && v:val<v:1_.max && v:val%v:2_==0', [b, 2] )
|
||||
" echo i . '/' . len(l)
|
||||
Assert i == 5
|
||||
Assert l[i] == 28
|
||||
" :echo l[i]
|
||||
endfunction
|
||||
|
||||
function! s:Test_Find_If_functor_predicate()
|
||||
:let l = [ 1, 5, 48, 25, 5, 28, 6]
|
||||
:let i = lh#list#find_if(l, 'v:1_>12 && v:1_<42 && v:1_%2==0')
|
||||
" echo i . '/' . len(l)
|
||||
Assert i == 5
|
||||
Assert l[i] == 28
|
||||
" :echo l[i]
|
||||
endfunction
|
||||
|
||||
function! s:Test_find_if_double_bind()
|
||||
:let b = { 'min': 12, 'max': 42 }
|
||||
:let l = [ 1, 5, 48, 25, 5, 28, 6]
|
||||
:let f = lh#function#bind( 'v:3_>v:1_.min && v:3_<v:1_.max && v:3_%v:2_==0')
|
||||
:let p = lh#function#bind(f, b,2,'v:1_')
|
||||
:let i = lh#list#find_if(l, p)
|
||||
:echo l[i]
|
||||
endfunction
|
||||
" double bind is not yet operational
|
||||
UTIgnore Test_find_if_double_bind
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" Unique Sorting
|
||||
function! CmpNumbers(lhs, rhs)
|
||||
if a:lhs < a:rhs | return -1
|
||||
elseif a:lhs == a:rhs | return 0
|
||||
else | return +1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Test_sort()
|
||||
:let l = [ 1, 5, 48, 25, 5, 28, 6]
|
||||
:let expected = [ 1, 5, 6, 25, 28, 48]
|
||||
:let s = lh#list#unique_sort(l, "CmpNumbers")
|
||||
" Comment string(s)
|
||||
Assert s == expected
|
||||
endfunction
|
||||
|
||||
function! s:Test_sort2()
|
||||
:let l = [ 1, 5, 48, 25, 5, 28, 6]
|
||||
:let expected = [ 1, 5, 6, 25, 28, 48]
|
||||
:let s = lh#list#unique_sort2(l, "CmpNumbers")
|
||||
" Comment string(s)
|
||||
Assert s == expected
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" Searchs
|
||||
function! s:TestBinarySearches()
|
||||
let v1 = [ -3, -2, -1, -1, 0, 0, 1, 2, 3, 4, 6 ]
|
||||
let i = lh#list#lower_bound(v1, 3)
|
||||
Assert v1[i] == 3
|
||||
let i = lh#list#upper_bound(v1, 3)
|
||||
Assert v1[i] == 4
|
||||
let r = lh#list#equal_range(v1, 3)
|
||||
Assert v1[r[0]:r[1]-1] == [3]
|
||||
|
||||
let i = lh#list#lower_bound(v1, -1)
|
||||
Assert v1[i] == -1
|
||||
let i = lh#list#upper_bound(v1, -1)
|
||||
Assert v1[i] == 0
|
||||
let r = lh#list#equal_range(v1, -1)
|
||||
Assert v1[r[0]:r[1]-1] == [-1, -1]
|
||||
|
||||
let i = lh#list#lower_bound(v1, 5)
|
||||
Assert v1[i] == 6
|
||||
let i = lh#list#upper_bound(v1, 5)
|
||||
Assert v1[i] == 6
|
||||
let r = lh#list#equal_range(v1, 5)
|
||||
Assert v1[r[0]:r[1]-1] == []
|
||||
|
||||
Assert len(v1) == lh#list#lower_bound(v1, 10)
|
||||
Assert len(v1) == lh#list#upper_bound(v1, 10)
|
||||
Assert [len(v1), len(v1)] == lh#list#equal_range(v1, 10)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" accumulate
|
||||
|
||||
function! s:Test_accumulate_len_strings()
|
||||
let strings = [ 'foo', 'bar', 'toto' ]
|
||||
let len = eval(lh#list#accumulate(strings, 'strlen', 'join(v:1_, "+")'))
|
||||
Assert len == 3+3+4
|
||||
endfunction
|
||||
|
||||
function! s:Test_accumulate_join()
|
||||
let ll = [ 1, 2, 'foo', ['bar'] ]
|
||||
let res = lh#list#accumulate(ll, 'string', 'join(v:1_, " ## ")')
|
||||
Assert res == "1 ## 2 ## 'foo' ## ['bar']"
|
||||
" This test will fail because it seems :for each loop cannot iterate on
|
||||
" heterogeneous containers
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" Copy_if
|
||||
function! s:Test_copy_if()
|
||||
:let l = [ 1, 25, 5, 48, 25, 5, 28, 6]
|
||||
:let expected = [ 25, 48, 25, 28, 6]
|
||||
:let s = lh#list#copy_if(l, [], "v:1_ > 5")
|
||||
" Comment string(s)
|
||||
Assert s == expected
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" subset
|
||||
function! s:Test_subset()
|
||||
:let l = [ 1, 25, 5, 48, 25, 5, 28, 6]
|
||||
:let indices = [ 0, 5, 7, 3 ]
|
||||
:let expected = [ 1, 5, 6, 48 ]
|
||||
:let s = lh#list#subset(l, indices)
|
||||
" Comment string(s)
|
||||
Assert s == expected
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" intersect
|
||||
function! s:Test_intersect()
|
||||
:let l1 = [ 1, 25, 7, 48, 26, 5, 28, 6]
|
||||
:let l2 = [ 3, 8, 7, 25, 6 ]
|
||||
:let expected = [ 25, 7, 6 ]
|
||||
:let s = lh#list#intersect(l1, l2)
|
||||
" Comment string(s)
|
||||
Assert s == expected
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
173
bundle/vim-mundo/tests/bundled/lh-vim-lib/tests/lh/path.vim
Normal file
173
bundle/vim-mundo/tests/bundled/lh-vim-lib/tests/lh/path.vim
Normal file
@ -0,0 +1,173 @@
|
||||
"=============================================================================
|
||||
" $Id: path.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: tests/lh/path.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 28th May 2009
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Tests for autoload/lh/path.vim
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
UTSuite [lh-vim-lib] Testing lh#path functions
|
||||
|
||||
runtime autoload/lh/path.vim
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
function! s:Test_simplify()
|
||||
Assert lh#path#simplify('a/b/c') == 'a/b/c'
|
||||
Assert lh#path#simplify('a/b/./c') == 'a/b/c'
|
||||
Assert lh#path#simplify('./a/b/./c') == 'a/b/c'
|
||||
Assert lh#path#simplify('./a/../b/./c') == 'b/c'
|
||||
Assert lh#path#simplify('../a/../b/./c') == '../b/c'
|
||||
Assert lh#path#simplify('a\b\c') == 'a\b\c'
|
||||
Assert lh#path#simplify('a\b\.\c') == 'a\b\c'
|
||||
Assert lh#path#simplify('.\a\b\.\c') == 'a\b\c'
|
||||
if exists('+shellslash')
|
||||
Assert lh#path#simplify('.\a\..\b\.\c') == 'b\c'
|
||||
Assert lh#path#simplify('..\a\..\b\.\c') == '..\b\c'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Test_strip_common()
|
||||
let paths = ['foo/bar/file', 'foo/file', 'foo/foo/file']
|
||||
let expected = [ 'bar/file', 'file', 'foo/file']
|
||||
Assert lh#path#strip_common(paths) == expected
|
||||
endfunction
|
||||
|
||||
function! s:Test_common()
|
||||
Assert 'foo/' == lh#path#common(['foo/bar/dir', 'foo'])
|
||||
Assert 'foo/bar/' == lh#path#common(['foo/bar/dir', 'foo/bar'])
|
||||
Assert 'foo/' == lh#path#common(['foo/bar/dir', 'foo/bar2'])
|
||||
endfunction
|
||||
|
||||
function! s:Test_strip_start()
|
||||
let expected = 'template/bar.template'
|
||||
Assert lh#path#strip_start($HOME.'/.vim/template/bar.template',
|
||||
\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ])
|
||||
\ == expected
|
||||
|
||||
Assert lh#path#strip_start($HOME.'/vimfiles/template/bar.template',
|
||||
\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ])
|
||||
\ == expected
|
||||
|
||||
Assert lh#path#strip_start('/usr/local/share/vim/template/bar.template',
|
||||
\ [ $HOME.'/.vim', $HOME.'/vimfiles', '/usr/local/share/vim' ])
|
||||
\ == expected
|
||||
endfunction
|
||||
|
||||
function! s:Test_IsAbsolutePath()
|
||||
" nix paths
|
||||
Assert lh#path#is_absolute_path('/usr/local')
|
||||
Assert lh#path#is_absolute_path($HOME)
|
||||
Assert ! lh#path#is_absolute_path('./usr/local')
|
||||
Assert ! lh#path#is_absolute_path('.usr/local')
|
||||
|
||||
" windows paths
|
||||
Assert lh#path#is_absolute_path('e:\usr\local')
|
||||
Assert ! lh#path#is_absolute_path('.\usr\local')
|
||||
Assert ! lh#path#is_absolute_path('.usr\local')
|
||||
|
||||
" UNC paths
|
||||
Assert lh#path#is_absolute_path('\\usr\local')
|
||||
Assert lh#path#is_absolute_path('//usr/local')
|
||||
endfunction
|
||||
|
||||
function! s:Test_IsURL()
|
||||
" nix paths
|
||||
Assert ! lh#path#is_url('/usr/local')
|
||||
Assert ! lh#path#is_url($HOME)
|
||||
Assert ! lh#path#is_url('./usr/local')
|
||||
Assert ! lh#path#is_url('.usr/local')
|
||||
|
||||
" windows paths
|
||||
Assert ! lh#path#is_url('e:\usr\local')
|
||||
Assert ! lh#path#is_url('.\usr\local')
|
||||
Assert ! lh#path#is_url('.usr\local')
|
||||
|
||||
" UNC paths
|
||||
Assert ! lh#path#is_url('\\usr\local')
|
||||
Assert ! lh#path#is_url('//usr/local')
|
||||
|
||||
" URLs
|
||||
Assert lh#path#is_url('http://www.usr/local')
|
||||
Assert lh#path#is_url('https://www.usr/local')
|
||||
Assert lh#path#is_url('ftp://www.usr/local')
|
||||
Assert lh#path#is_url('sftp://www.usr/local')
|
||||
Assert lh#path#is_url('dav://www.usr/local')
|
||||
Assert lh#path#is_url('fetch://www.usr/local')
|
||||
Assert lh#path#is_url('file://www.usr/local')
|
||||
Assert lh#path#is_url('rcp://www.usr/local')
|
||||
Assert lh#path#is_url('rsynch://www.usr/local')
|
||||
Assert lh#path#is_url('scp://www.usr/local')
|
||||
endfunction
|
||||
|
||||
function! s:Test_ToRelative()
|
||||
let pwd = getcwd()
|
||||
Assert lh#path#to_relative(pwd.'/foo/bar') == 'foo/bar'
|
||||
Assert lh#path#to_relative(pwd.'/./foo') == 'foo'
|
||||
Assert lh#path#to_relative(pwd.'/foo/../bar') == 'bar'
|
||||
|
||||
" Does not work yet as it returns an absolute path it that case
|
||||
Assert lh#path#to_relative(pwd.'/../bar') == '../bar'
|
||||
endfunction
|
||||
|
||||
function! s:Test_relative_path()
|
||||
Assert lh#path#relative_to('foo/bar/dir', 'foo') == '../../'
|
||||
Assert lh#path#relative_to('foo', 'foo/bar/dir') == 'bar/dir/'
|
||||
Assert lh#path#relative_to('foo/bar', 'foo/bar2/dir') == '../bar2/dir/'
|
||||
|
||||
let pwd = getcwd()
|
||||
Assert lh#path#relative_to(pwd ,pwd.'/../bar') == '../bar/'
|
||||
endfunction
|
||||
|
||||
function! s:Test_search_vimfiles()
|
||||
let expected_win = $HOME . '/vimfiles'
|
||||
let expected_nix = $HOME . '/.vim'
|
||||
let what = lh#path#to_regex($HOME.'/').'\(vimfiles\|.vim\)'
|
||||
" Comment what
|
||||
let z = lh#path#find(&rtp,what)
|
||||
if has('win16')||has('win32')||has('win64')
|
||||
Assert z == expected_win
|
||||
else
|
||||
Assert z == expected_nix
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Test_path_depth()
|
||||
Assert 0 == lh#path#depth('.')
|
||||
Assert 0 == lh#path#depth('./')
|
||||
Assert 0 == lh#path#depth('.\')
|
||||
Assert 1 == lh#path#depth('toto')
|
||||
Assert 1 == lh#path#depth('toto/')
|
||||
Assert 1 == lh#path#depth('toto\')
|
||||
Assert 1 == lh#path#depth('toto/.')
|
||||
Assert 1 == lh#path#depth('toto\.')
|
||||
Assert 1 == lh#path#depth('toto/./.')
|
||||
Assert 1 == lh#path#depth('toto\.\.')
|
||||
Assert 0 == lh#path#depth('toto/..')
|
||||
if exists('+shellslash')
|
||||
Assert 0 == lh#path#depth('toto\..')
|
||||
endif
|
||||
Assert 2 == lh#path#depth('toto/titi/')
|
||||
Assert 2 == lh#path#depth('toto\titi\')
|
||||
Assert 2 == lh#path#depth('/toto/titi/')
|
||||
Assert 2 == lh#path#depth('c:/toto/titi/')
|
||||
Assert 2 == lh#path#depth('c:\toto/titi/')
|
||||
" todo: make a choice about "negative" paths like "../../foo"
|
||||
Assert -1 == lh#path#depth('../../foo')
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,83 @@
|
||||
"=============================================================================
|
||||
" $Id: test-Fargs2String.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: tests/lh/test-Fargs2String.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 16th Apr 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: Tests for lh-vim-lib . lh#command#Fargs2String
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Relies on the version «patched by myself|1?» of vim_units
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
function! s:TestEmpty()
|
||||
let empty = []
|
||||
let res = lh#command#Fargs2String(empty)
|
||||
call VUAssertEquals(len(empty), 0, 'Expected empty', 22)
|
||||
call VUAssertEquals(res, '', 'Expected empty result', 23)
|
||||
endfunction
|
||||
|
||||
function! s:TestSimpleText1()
|
||||
let expected = 'text'
|
||||
let one = [ expected ]
|
||||
let res = lh#command#Fargs2String(one)
|
||||
call VUAssertEquals(len(one), 0, 'Expected empty', 27)
|
||||
call VUAssertEquals(res, expected, 'Expected a simple result', 28)
|
||||
endfunction
|
||||
|
||||
function! s:TestSimpleTextN()
|
||||
let expected = 'text'
|
||||
let list = [ expected , 'stuff1', 'stuff2']
|
||||
let res = lh#command#Fargs2String(list)
|
||||
call VUAssertEquals(len(list), 2, 'Expected not empty', 38)
|
||||
call VUAssertEquals(res, expected, 'Expected a simple result', 39)
|
||||
endfunction
|
||||
|
||||
function! s:TestComposedN()
|
||||
let expected = '"a several tokens string"'
|
||||
let list = [ '"a', 'several', 'tokens', 'string"', 'stuff1', 'stuff2']
|
||||
let res = lh#command#Fargs2String(list)
|
||||
call VUAssertEquals(len(list), 2, 'Expected not empty', 46)
|
||||
call VUAssertEquals(res, expected, 'Expected a composed string', 47)
|
||||
call VUAssertEquals(list, ['stuff1', 'stuff2'], 'Expected a list', 48)
|
||||
call VUAssertNotSame(list, ['stuff1', 'stuff2'], 'Expected different lists', 49)
|
||||
endfunction
|
||||
|
||||
function! s:TestComposed1()
|
||||
let expected = '"string"'
|
||||
let list = [ '"string"', 'stuff1', 'stuff2']
|
||||
let res = lh#command#Fargs2String(list)
|
||||
call VUAssertEquals(len(list), 2, 'Expected not empty', 56)
|
||||
call VUAssertEquals(res, expected, 'Expected a string', 57)
|
||||
call VUAssertEquals(list, ['stuff1', 'stuff2'], 'Expected a list', 58)
|
||||
call VUAssertNotSame(list, ['stuff1', 'stuff2'], 'Expected different lists', 59)
|
||||
endfunction
|
||||
|
||||
function! s:TestInvalidString()
|
||||
let expected = '"a string'
|
||||
let list = [ '"a', 'string']
|
||||
let res = lh#command#Fargs2String(list)
|
||||
call VUAssertEquals(len(list), 0, 'Expected empty', 66)
|
||||
call VUAssertEquals(res, expected, 'Expected an invalid string', 67)
|
||||
endfunction
|
||||
|
||||
function! AllTests()
|
||||
call s:TestEmpty()
|
||||
call s:TestSimpleText1()
|
||||
call s:TestSimpleTextN()
|
||||
call s:TestComposed1()
|
||||
call s:TestComposedN()
|
||||
endfunction
|
||||
|
||||
" call VURunnerRunTest('AllTests')
|
||||
VURun % AllTests
|
||||
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,65 @@
|
||||
"=============================================================================
|
||||
" $Id: test-askmenu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: test-buffer-menu.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 18th Apr 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Test units for buffermenu.vim
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: Requires:
|
||||
" (*) Vim 7.0+
|
||||
" (*) vim_units.vim v0.2/1.0?
|
||||
" Vimscript # «???»
|
||||
" (*) lh-vim-lib (lh#ask#menu)
|
||||
"
|
||||
" User Manual:
|
||||
" Source this file.
|
||||
"
|
||||
" History:
|
||||
" (*) 17th Apr 2007: First version
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
|
||||
"=============================================================================
|
||||
let s:cpo_save=&cpo
|
||||
"------------------------------------------------------------------------
|
||||
" Functions {{{1
|
||||
|
||||
function! TestAskMenu()
|
||||
imenu 42.40.10 &LH-Tests.&Menu.&ask.i iask
|
||||
inoremenu 42.40.10 &LH-Tests.&Menu.&ask.inore inoreask
|
||||
nmenu 42.40.10 &LH-Tests.&Menu.&ask.n nask
|
||||
nnoremenu 42.40.10 &LH-Tests.&Menu.&ask.nnore nnoreask
|
||||
nmenu <script> 42.40.10 &LH-Tests.&Menu.&ask.nscript nscriptask
|
||||
nnoremenu <script> 42.40.10 &LH-Tests.&Menu.&ask.nnnscript nnscriptask
|
||||
|
||||
vmenu 42.40.10 &LH-Tests.&Menu.&ask.v vask
|
||||
vnoremenu 42.40.10 &LH-Tests.&Menu.&ask.vnore vnoreask
|
||||
|
||||
call s:CheckInMode('i', 'i')
|
||||
|
||||
endfunction
|
||||
|
||||
function! s:CheckInMode(mode, name)
|
||||
let g:menu = lh#askvim#menu('LH-Tests.Menu.ask.'.a:name, a:mode)
|
||||
let g:name = a:name
|
||||
" VUAssert 55 Equals g:menu.name g:name "Name mismatch"
|
||||
" VUAssert 56 Equals g:menu.priority '42.40.10' "Priority mismatch"
|
||||
" VUAssert 57 Fail "parce qu'il le faut bien"
|
||||
echomsg "name= ".g:menu.name
|
||||
echomsg "prio= ".g:menu.priority
|
||||
endfunction
|
||||
|
||||
" Functions }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,69 @@
|
||||
" $Id: test-command.vim 156 2010-05-07 00:54:36Z luc.hermitte $
|
||||
" Tests for lh-vim-lib . lh#command
|
||||
|
||||
" FindFilter(filter): Helper {{{3
|
||||
function! s:FindFilter(filter)
|
||||
let filter = a:filter . '.vim'
|
||||
let result =globpath(&rtp, "compiler/BTW-".filter) . "\n" .
|
||||
\ globpath(&rtp, "compiler/BTW_".filter). "\n" .
|
||||
\ globpath(&rtp, "compiler/BTW/".filter)
|
||||
let result = substitute(result, '\n\n', '\n', 'g')
|
||||
let result = substitute(result, '^\n', '', 'g')
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:ComplFilter(filter)
|
||||
let files = s:FindFilter('*')
|
||||
let files = substitute(files,
|
||||
\ '\(^\|\n\).\{-}compiler[\\/]BTW[-_\\/]\(.\{-}\)\.vim\>\ze\%(\n\|$\)',
|
||||
\ '\1\2', 'g')
|
||||
return files
|
||||
endfunction
|
||||
|
||||
function! s:Add()
|
||||
endfunction
|
||||
|
||||
let s:v1 = 'v1'
|
||||
let s:v2 = 2
|
||||
|
||||
function! s:Foo(i)
|
||||
return a:i*a:i
|
||||
endfunction
|
||||
|
||||
function! s:echo(params)
|
||||
echo s:{join(a:params, '')}
|
||||
endfunction
|
||||
|
||||
function! Echo(params)
|
||||
" echo "Echo(".string(a:params).')'
|
||||
let expr = 's:'.join(a:params, '')
|
||||
" echo expr
|
||||
exe 'echo '.expr
|
||||
endfunction
|
||||
|
||||
let TBTWcommand = {
|
||||
\ "name" : "TBT",
|
||||
\ "arg_type" : "sub_commands",
|
||||
\ "arguments" :
|
||||
\ [
|
||||
\ { "name" : "echo",
|
||||
\ "arg_type" : "function",
|
||||
\ "arguments" : "v1,v2",
|
||||
\ "action": function("\<sid>echo") },
|
||||
\ { "name" : "Echo",
|
||||
\ "arg_type" : "function",
|
||||
\ "arguments" : "v1,v2",
|
||||
\ "action": function("Echo") },
|
||||
\ { "name" : "help" },
|
||||
\ { "name" : "add",
|
||||
\ "arguments": function("s:ComplFilter"),
|
||||
\ "action" : function("s:Add") }
|
||||
\ ]
|
||||
\ }
|
||||
|
||||
call lh#command#new(TBTWcommand)
|
||||
|
||||
nnoremap µ :call lh#command#new(TBTWcommand)<cr>
|
||||
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,54 @@
|
||||
"=============================================================================
|
||||
" $Id: test-menu-map.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: tests/lh/test-menu-map.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 05th Dec 2006
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: Tests for lh-vim-lib . lh#menu#
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
|
||||
" let g:want_buffermenu_or_global_disable = 1
|
||||
" let b:want_buffermenu_or_global_disable = 1
|
||||
" echo lh#option#get("want_buffermenu_or_global_disable", 1, "bg")
|
||||
|
||||
" Call a command (':Command')
|
||||
call lh#menu#make("nic", '42.50.340',
|
||||
\ '&LH-Tests.&Menu-Make.Build Ta&gs', "<C-L>g",
|
||||
\ '<buffer>',
|
||||
\ ":echo 'TeXtags'<CR>")
|
||||
|
||||
" With '{' expanding to '{}××', or '{}' regarding the mode
|
||||
call lh#menu#IVN_make('42.50.360.200',
|
||||
\ '&LH-Tests.&Menu-Make.&Insert.\toto{}', ']toto',
|
||||
\ '\\toto{',
|
||||
\ '{%i\\toto<ESC>%l',
|
||||
\ "viw]toto")
|
||||
|
||||
" Noremap for the visual maps
|
||||
call lh#menu#IVN_make('42.50.360.200',
|
||||
\ '&LH-Tests.&Menu-Make.&Insert.\titi{}', ']titi',
|
||||
\ '\\titi{',
|
||||
\ '<ESC>`>a}<ESC>`<i\\titi{<ESC>%l',
|
||||
\ "viw]titi",
|
||||
\ 0, 1, 0)
|
||||
|
||||
" Noremap for the insert and visual maps
|
||||
call lh#menu#IVN_make('42.50.360.200',
|
||||
\ '&LH-Tests.&Menu-Make.&Insert.<tata></tata>', ']tata',
|
||||
\ '<tata></tata><esc>?<<CR>i',
|
||||
\ '<ESC>`>a</tata><ESC>`<i<tata><ESC>/<\\/tata>/e1<CR>',
|
||||
\ "viw]tata",
|
||||
\ 1, 1, 0)
|
||||
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
@ -0,0 +1,84 @@
|
||||
"=============================================================================
|
||||
" $Id: test-toggle-menu.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: tests/lh/topological-sort.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 17th Apr 2007
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" Tests for lh-vim-lib . lh#menu#def_toggle_item()
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
source autoload/lh/menu.vim
|
||||
|
||||
let Data = {
|
||||
\ "variable": "bar",
|
||||
\ "idx_crt_value": 1,
|
||||
\ "values": [ 'a', 'b', 'c', 'd' ],
|
||||
\ "menu": { "priority": '42.50.10', "name": '&LH-Tests.&TogMenu.&bar'}
|
||||
\}
|
||||
|
||||
call lh#menu#def_toggle_item(Data)
|
||||
|
||||
let Data2 = {
|
||||
\ "variable": "foo",
|
||||
\ "idx_crt_value": 3,
|
||||
\ "texts": [ 'un', 'deux', 'trois', 'quatre' ],
|
||||
\ "values": [ 1, 2, 3, 4 ],
|
||||
\ "menu": { "priority": '42.50.11', "name": '&LH-Tests.&TogMenu.&foo'}
|
||||
\}
|
||||
|
||||
call lh#menu#def_toggle_item(Data2)
|
||||
|
||||
" No default
|
||||
let Data3 = {
|
||||
\ "variable": "nodef",
|
||||
\ "texts": [ 'one', 'two', 'three', 'four' ],
|
||||
\ "values": [ 1, 2, 3, 4 ],
|
||||
\ "menu": { "priority": '42.50.12', "name": '&LH-Tests.&TogMenu.&nodef'}
|
||||
\}
|
||||
call lh#menu#def_toggle_item(Data3)
|
||||
|
||||
" No default
|
||||
let g:def = 2
|
||||
let Data4 = {
|
||||
\ "variable": "def",
|
||||
\ "values": [ 1, 2, 3, 4 ],
|
||||
\ "menu": { "priority": '42.50.13', "name": '&LH-Tests.&TogMenu.&def'}
|
||||
\}
|
||||
call lh#menu#def_toggle_item(Data4)
|
||||
|
||||
" What follows does not work because we can't build an exportable FuncRef on top
|
||||
" of a script local function
|
||||
" finish
|
||||
|
||||
function! s:getSNR()
|
||||
if !exists("s:SNR")
|
||||
let s:SNR=matchstr(expand("<sfile>"), "<SNR>\\d\\+_\\zegetSNR$")
|
||||
endif
|
||||
return s:SNR
|
||||
endfunction
|
||||
|
||||
function! s:Yes()
|
||||
echomsg "Yes"
|
||||
endfunction
|
||||
|
||||
function! s:No()
|
||||
echomsg "No"
|
||||
endfunction
|
||||
let Data4 = {
|
||||
\ "variable": "yesno",
|
||||
\ "values": [ 1, 2 ],
|
||||
\ "text": [ "No", "Yes" ],
|
||||
\ "actions": [ function(s:getSNR()."No"), function(s:getSNR()."Yes") ],
|
||||
\ "menu": { "priority": '42.50.20', "name": '&LH-Tests.&TogMenu.&yesno'}
|
||||
\}
|
||||
call lh#menu#def_toggle_item(Data4)
|
@ -0,0 +1,120 @@
|
||||
"=============================================================================
|
||||
" $Id: topological-sort.vim 246 2010-09-19 22:40:58Z luc.hermitte $
|
||||
" File: tests/lh/topological-sort.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 2.2.1
|
||||
" Created: 17th Apr 2008
|
||||
" Last Update: $Date: 2010-09-19 18:40:58 -0400 (Sun, 19 Sep 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: «description»
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
UTSuite [lh-vim-lib] topological sort
|
||||
|
||||
" Fully defineds DAGs {{{1
|
||||
|
||||
" A Direct Acyclic Graph {{{2
|
||||
let s:dag1 = {}
|
||||
let s:dag1[7] = [11, 8]
|
||||
let s:dag1[5] = [11]
|
||||
let s:dag1[3] = [8, 10]
|
||||
let s:dag1[11] = [2, 9, 10]
|
||||
let s:dag1[8] = [9]
|
||||
|
||||
" A Direct Cyclic Graph {{{2
|
||||
let s:dcg1 = deepcopy(s:dag1)
|
||||
let s:dcg1[9] = [11]
|
||||
|
||||
" Check routine: are the elements correctly sorted? {{{2
|
||||
function! s:DoTestOrder(elements)
|
||||
Assert! len(a:elements) == 8
|
||||
Assert index(a:elements, 7) < index(a:elements, 11)
|
||||
Assert index(a:elements, 7) < index(a:elements, 8)
|
||||
Assert index(a:elements, 5) < index(a:elements, 11)
|
||||
Assert index(a:elements, 3) < index(a:elements, 8)
|
||||
Assert index(a:elements, 3) < index(a:elements, 10)
|
||||
Assert index(a:elements, 11) < index(a:elements, 2)
|
||||
Assert index(a:elements, 11) < index(a:elements, 9)
|
||||
Assert index(a:elements, 11) < index(a:elements, 10)
|
||||
Assert index(a:elements, 8) < index(a:elements, 9)
|
||||
endfunction
|
||||
|
||||
" Test DAG1 {{{2
|
||||
function! s:TestDAG_depth()
|
||||
let res = lh#graph#tsort#depth(s:dag1, [3, 5,7])
|
||||
call s:DoTestOrder(res)
|
||||
echo "D(s:dag1)=".string(res)
|
||||
endfunction
|
||||
|
||||
function! s:TestDAG_breadth()
|
||||
let res = lh#graph#tsort#breadth(s:dag1, [3, 5,7])
|
||||
call s:DoTestOrder(res)
|
||||
echo "B(s:dag1)=".string(res)
|
||||
endfunction
|
||||
|
||||
" Test DCG1 {{{2
|
||||
function! s:TestDCG_depth()
|
||||
let expr = 'lh#graph#tsort#depth('.string(s:dcg1).', [3, 5,7])'
|
||||
Assert should#throw(expr, 'Tsort: cyclic graph detected')
|
||||
endfunction
|
||||
|
||||
function! s:TestDCG_breadth()
|
||||
let expr = 'lh#graph#tsort#breadth('.string(s:dcg1).', [3, 5,7])'
|
||||
Assert should#throw(expr, 'Tsort: cyclic graph detected')
|
||||
endfunction
|
||||
|
||||
" Lazzy Evaluated DAGs {{{1
|
||||
|
||||
" Emulated lazzyness {{{2
|
||||
" The time-consumings evaluation function
|
||||
let s:called = 0
|
||||
function! Fetch(node)
|
||||
let s:called += 1
|
||||
return has_key(s:dag1, a:node) ? (s:dag1[a:node]) : []
|
||||
endfunction
|
||||
|
||||
" Test Fetch on a DAG {{{2
|
||||
function! s:TestDAG_fetch()
|
||||
let s:called = 0
|
||||
let res = lh#graph#tsort#depth(function('Fetch'), [3,5,7])
|
||||
call s:DoTestOrder(res)
|
||||
echo "D(fetch)=".string(res)
|
||||
echo "Fetch has been evaluated ".s:called." times / ".len(res)
|
||||
Assert s:called == len(res)
|
||||
endfunction
|
||||
|
||||
|
||||
" Setup/Teardown functions {{{1
|
||||
" display the test name before each assertion
|
||||
function! s:Setup()
|
||||
if exists('g:UT_print_test')
|
||||
let s:old_print_test = g:UT_print_test
|
||||
endif
|
||||
let g:UT_print_test = 1
|
||||
endfunction
|
||||
|
||||
function! s:Teardown()
|
||||
if exists('s:old_print_test')
|
||||
let g:UT_print_test = s:old_print_test
|
||||
unlet s:old_print_test
|
||||
else
|
||||
unlet g:UT_print_test
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
" }}}1
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
||||
|
16
bundle/vim-mundo/tests/bundled/ut/UT.README
Normal file
16
bundle/vim-mundo/tests/bundled/ut/UT.README
Normal file
@ -0,0 +1,16 @@
|
||||
--------------------
|
||||
UT v0.0.3
|
||||
--------------------
|
||||
|
||||
UT is a Unit Testing Framework for Vim
|
||||
|
||||
Audience : Vim script maintainers
|
||||
Requirements : Vim 7, lh-vim-lib v2.2.0 ;
|
||||
takes advantage of BuildtoolsWrappers if installed.
|
||||
Required by : Only lh-vim
|
||||
Maintainer : Luc Hermitte
|
||||
License : GPL 2 (see http://www.gnu.org/licenses/gpl.txt)
|
||||
More Help At : http://code.google.com/p/lh-vim/wiki/UT
|
||||
Vim script#???: http://www.vim.org/scripts/script.php?script_id=???
|
||||
Repository :
|
||||
svn checkout http://lh-vim.googlecode.com/svn/UT/trunk UT
|
442
bundle/vim-mundo/tests/bundled/ut/autoload/lh/UT.vim
Normal file
442
bundle/vim-mundo/tests/bundled/ut/autoload/lh/UT.vim
Normal file
@ -0,0 +1,442 @@
|
||||
"=============================================================================
|
||||
" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
|
||||
" File: autoload/lh/UT.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
" Version: 0.0.3
|
||||
" Created: 11th Feb 2009
|
||||
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: Yet Another Unit Testing Framework for Vim
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop this file into {rtp}/autoload/lh/
|
||||
" History:
|
||||
" Strongly inspired by Tom Link's tAssert plugin: all its functions are
|
||||
" compatible with this framework.
|
||||
"
|
||||
" Features:
|
||||
" - Assertion failures are reported in the quickfix window
|
||||
" - Assertion syntax is simple, check Tom Link's suite, it's the same
|
||||
" - Supports banged :Assert! to stop processing a given test on failed
|
||||
" assertions
|
||||
" - All the s:Test* functions of a suite are executed (almost) independently
|
||||
" (i.e., a critical :Assert! failure will stop the Test of the function, and
|
||||
" lh#UT will proceed to the next s:Test function
|
||||
" - Lightweight and simple to use: there is only one command defined, all the
|
||||
" other definitions are kept in an autoload plugin.
|
||||
" - A suite == a file
|
||||
" - Several s:TestXxx() per suite
|
||||
" - +optional s:Setup(), s:Teardown()
|
||||
" - Supports :Comment's ; :Comment takes an expression to evaluate
|
||||
" - s:LocalFunctions(), s:variables, and l:variables are supported
|
||||
" - Takes advantage of BuildToolsWrapper's :Copen command if installed
|
||||
" - Count successful tests (and not successful assertions)
|
||||
" - Short-cuts to run the Unit Tests associated to a given vim script
|
||||
" Relies on: Let-Modeline/local_vimrc/Project to set g:UTfiles (space
|
||||
" separated list of glob-able paths), and on lh-vim-lib#path
|
||||
" - Command to exclude, or specify the tests to play => UTPlay, UTIgnore
|
||||
" - Option g:UT_print_test to display, on assertion failure, the current test
|
||||
" name with the assertion failed.
|
||||
"
|
||||
" TODO:
|
||||
" - Always execute s:Teardown() -- move its call to a :finally bloc
|
||||
" - Test in UTF-8 (because of <SNR>_ injection)
|
||||
" - test under windows (where paths have spaces, etc)
|
||||
" - What about s:/SNR pollution ? The tmpfile is reused, and there is no
|
||||
" guaranty a script will clean its own place
|
||||
" - add &efm for viml errors like the one produced by :Assert 0 + [0]
|
||||
" and take into account the offset introduced by lines injected at the top of
|
||||
" the file
|
||||
" - simplify s:errors functions
|
||||
" - merge with Tom Link tAssert plugin? (the UI is quite different)
|
||||
" - :AssertEquals that shows the name of both expressions and their values as
|
||||
" well -- a correct distinction of both parameters will be tricky with
|
||||
" regexes ; using functions will loose either the name, or the value in case
|
||||
" of local/script variables use ; we need macros /à la C/...
|
||||
" - Support Embedded comments like for instance:
|
||||
" Assert 1 == 1 " 1 must value 1
|
||||
" - Ways to test buffers produced
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
|
||||
" ## Functions {{{1
|
||||
"------------------------------------------------------------------------
|
||||
" # Debug {{{2
|
||||
function! lh#UT#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr, ...)
|
||||
let lvl = a:0>0 ? a:1 : 1
|
||||
if exists('s:verbose') && s:verbose >= lvl
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! lh#UT#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" # Internal functions {{{2
|
||||
"------------------------------------------------------------------------
|
||||
|
||||
" Sourcing a script doesn't imply a new entry with its name in :scriptnames
|
||||
" As a consequence, the easiest thing to do is to reuse the same file over and
|
||||
" over in a given vim session.
|
||||
" This approach should be fine as long as there are less than 26 VimL testing vim
|
||||
" sessions opened simultaneously.
|
||||
let s:tempfile = tempname()
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" s:errors
|
||||
let s:errors = {
|
||||
\ 'qf' : [],
|
||||
\ 'crt_suite' : {},
|
||||
\ 'nb_asserts' : 0,
|
||||
\ 'nb_successful_asserts' : 0,
|
||||
\ 'nb_success' : 0,
|
||||
\ 'suites' : []
|
||||
\ }
|
||||
|
||||
function! s:errors.clear() dict
|
||||
let self.qf = []
|
||||
let self.nb_asserts = 0
|
||||
let self.nb_successful_asserts = 0
|
||||
let self.nb_success = 0
|
||||
let self.nb_tests = 0
|
||||
let self.suites = []
|
||||
let self.crt_suite = {}
|
||||
endfunction
|
||||
|
||||
function! s:errors.display() dict
|
||||
let g:errors = self.qf
|
||||
cexpr self.qf
|
||||
|
||||
" Open the quickfix window
|
||||
if exists(':Copen')
|
||||
" Defined in lh-BTW, make the windows as big as the number of errors, not
|
||||
" opened if there is no error
|
||||
Copen
|
||||
else
|
||||
copen
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:errors.set_current_SNR(SNR)
|
||||
let self.crt_suite.snr = a:SNR
|
||||
endfunction
|
||||
|
||||
function! s:errors.get_current_SNR()
|
||||
return self.crt_suite.snr
|
||||
endfunction
|
||||
|
||||
function! s:errors.add(FILE, LINE, message) dict
|
||||
let msg = a:FILE.':'.a:LINE.':'
|
||||
if lh#option#get('UT_print_test', 0, 'g') && has_key(s:errors, 'crt_test')
|
||||
let msg .= '['. s:errors.crt_test.name .'] '
|
||||
endif
|
||||
let msg.= a:message
|
||||
call add(self.qf, msg)
|
||||
endfunction
|
||||
|
||||
function! s:errors.add_test(test_name) dict
|
||||
call self.add_test(a:test_name)
|
||||
endfunction
|
||||
|
||||
function! s:errors.set_test_failed() dict
|
||||
if has_key(self, 'crt_test')
|
||||
let self.crt_test.failed = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" Tests wrapper functions
|
||||
|
||||
function! s:RunOneTest(file) dict
|
||||
try
|
||||
let s:errors.crt_test = self
|
||||
if has_key(s:errors.crt_suite, 'setup')
|
||||
let F = function(s:errors.get_current_SNR().'Setup')
|
||||
call F()
|
||||
endif
|
||||
let F = function(s:errors.get_current_SNR(). self.name)
|
||||
call F()
|
||||
if has_key(s:errors.crt_suite, 'teardown')
|
||||
let F = function(s:errors.get_current_SNR().'Teardown')
|
||||
call F()
|
||||
endif
|
||||
catch /Assert: abort/
|
||||
call s:errors.add(a:file,
|
||||
\ matchstr(v:exception, '.*(\zs\d\+\ze)'),
|
||||
\ 'Test <'. self.name .'> execution aborted on critical assertion failure')
|
||||
catch /.*/
|
||||
let throwpoint = substitute(v:throwpoint, escape(s:tempfile, '.\'), a:file, 'g')
|
||||
let msg = throwpoint . ': '.v:exception
|
||||
call s:errors.add(a:file, 0, msg)
|
||||
finally
|
||||
unlet s:errors.crt_test
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:AddTest(test_name) dict
|
||||
let test = {
|
||||
\ 'name' : a:test_name,
|
||||
\ 'run' : function('s:RunOneTest'),
|
||||
\ 'failed' : 0
|
||||
\ }
|
||||
call add(self.tests, test)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" Suites wrapper functions
|
||||
|
||||
function! s:ConcludeSuite() dict
|
||||
call s:errors.add(self.file,0, 'SUITE<'. self.name.'> '. s:errors.nb_success .'/'. s:errors.nb_tests . ' tests successfully executed.')
|
||||
" call add(s:errors.qf, 'SUITE<'. self.name.'> '. s:rrors.nb_success .'/'. s:errors.nb_tests . ' tests successfully executed.')
|
||||
endfunction
|
||||
|
||||
function! s:PlayTests(...) dict
|
||||
call s:Verbose('Execute tests: '.join(a:000, ', '))
|
||||
call filter(self.tests, 'index(a:000, v:val.name) >= 0')
|
||||
call s:Verbose('Keeping tests: '.join(self.tests, ', '))
|
||||
endfunction
|
||||
|
||||
function! s:IgnoreTests(...) dict
|
||||
call s:Verbose('Ignoring tests: '.join(a:000, ', '))
|
||||
call filter(self.tests, 'index(a:000, v:val.name) < 0')
|
||||
call s:Verbose('Keeping tests: '.join(self.tests, ', '))
|
||||
endfunction
|
||||
|
||||
function! s:errors.new_suite(file) dict
|
||||
let suite = {
|
||||
\ 'scriptname' : s:tempfile,
|
||||
\ 'file' : a:file,
|
||||
\ 'tests' : [],
|
||||
\ 'snr' : '',
|
||||
\ 'add_test' : function('s:AddTest'),
|
||||
\ 'conclude' : function('s:ConcludeSuite'),
|
||||
\ 'play' : function('s:PlayTests'),
|
||||
\ 'ignore' : function('s:IgnoreTests'),
|
||||
\ 'nb_tests_failed' : 0
|
||||
\ }
|
||||
call add(self.suites, suite)
|
||||
let self.crt_suite = suite
|
||||
return suite
|
||||
endfunction
|
||||
|
||||
function! s:errors.set_suite(suite_name) dict
|
||||
let a = s:Decode(a:suite_name)
|
||||
call s:Verbose('SUITE <- '. a.expr, 1)
|
||||
call s:Verbose('SUITE NAME: '. a:suite_name, 2)
|
||||
" call self.add(a.file, a.line, 'SUITE <'. a.expr .'>')
|
||||
call self.add(a.file,0, 'SUITE <'. a.expr .'>')
|
||||
let self.crt_suite.name = a.expr
|
||||
" let self.crt_suite.file = a.file
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
function! s:Decode(expression)
|
||||
let filename = s:errors.crt_suite.file
|
||||
let expr = a:expression
|
||||
let line = matchstr(expr, '^\d\+')
|
||||
" echo filename.':'.line
|
||||
let expr = strpart(expr, strlen(line)+1)
|
||||
let res = { 'file':filename, 'line':line, 'expr':expr}
|
||||
call s:Verbose('decode:'. (res.file) .':'. (res.line) .':'. (res.expr), 2)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! lh#UT#callback_decode(expression)
|
||||
return s:Decode(a:expression)
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let s:k_commands = '\%(Assert\|UTSuite\|Comment\)'
|
||||
let s:k_local_evaluate = [
|
||||
\ 'command! -bang -nargs=1 Assert '.
|
||||
\ 'let s:a = lh#UT#callback_decode(<q-args>) |'.
|
||||
\ 'let s:ok = !empty(eval(s:a.expr)) |'.
|
||||
\ 'exe "UTAssert<bang> ".s:ok." ".(<f-args>)|'
|
||||
\]
|
||||
let s:k_getSNR = [
|
||||
\ 'function! s:getSNR()',
|
||||
\ ' if !exists("s:SNR")',
|
||||
\ ' let s:SNR=matchstr(expand("<sfile>"), "<SNR>\\d\\+_\\zegetSNR$")',
|
||||
\ ' endif',
|
||||
\ ' return s:SNR',
|
||||
\ 'endfunction',
|
||||
\ 'call lh#UT#callback_set_SNR(s:getSNR())',
|
||||
\ ''
|
||||
\ ]
|
||||
|
||||
function! s:PrepareFile(file)
|
||||
if !filereadable(a:file)
|
||||
call s:errors.add('-', 0, a:file . " can not be read")
|
||||
return
|
||||
endif
|
||||
let file = escape(a:file, ' \')
|
||||
|
||||
let lines = readfile(a:file)
|
||||
let need_to_know_SNR = 0
|
||||
let suite = s:errors.new_suite(a:file)
|
||||
|
||||
let no = 0
|
||||
let last_line = len(lines)
|
||||
while no < last_line
|
||||
if lines[no] =~ '^\s*'.s:k_commands.'\>'
|
||||
let lines[no] = substitute(lines[no], '^\s*'.s:k_commands.'!\= \zs', (no+1).' ', '')
|
||||
|
||||
elseif lines[no] =~ '^\s*function!\=\s\+s:Test'
|
||||
let test_name = matchstr(lines[no], '^\s*function!\=\s\+s:\zsTest\S\{-}\ze(')
|
||||
call suite.add_test(test_name)
|
||||
elseif lines[no] =~ '^\s*function!\=\s\+s:Teardown'
|
||||
let suite.teardown = 1
|
||||
elseif lines[no] =~ '^\s*function!\=\s\+s:Setup'
|
||||
let suite.setup = 1
|
||||
endif
|
||||
if lines[no] =~ '^\s*function!\=\s\+s:'
|
||||
let need_to_know_SNR = 1
|
||||
endif
|
||||
let no += 1
|
||||
endwhile
|
||||
|
||||
" Inject s:getSNR() in the script if there is a s:Function in the Test script
|
||||
if need_to_know_SNR
|
||||
call extend(lines, s:k_getSNR, 0)
|
||||
let last_line += len(s:k_getSNR)
|
||||
endif
|
||||
|
||||
" Inject local evualation of expressions in the script
|
||||
" => takes care of s:variables, s:Functions(), and l:variables
|
||||
call extend(lines, s:k_local_evaluate, 0)
|
||||
|
||||
call writefile(lines, suite.scriptname)
|
||||
let g:lines=lines
|
||||
endfunction
|
||||
|
||||
function! s:RunOneFile(file)
|
||||
try
|
||||
call s:PrepareFile(a:file)
|
||||
exe 'source '.s:tempfile
|
||||
|
||||
let s:errors.nb_tests = len(s:errors.crt_suite.tests)
|
||||
if !empty(s:errors.crt_suite.tests)
|
||||
call s:Verbose('Executing tests: '.join(s:errors.crt_suite.tests, ', '))
|
||||
for test in s:errors.crt_suite.tests
|
||||
call test.run(a:file)
|
||||
let s:errors.nb_success += 1 - test.failed
|
||||
endfor
|
||||
endif
|
||||
|
||||
catch /Assert: abort/
|
||||
call s:errors.add(a:file,
|
||||
\ matchstr(v:exception, '.*(\zs\d\+\ze)'),
|
||||
\ 'Suite <'. s:errors.crt_suite .'> execution aborted on critical assertion failure')
|
||||
catch /.*/
|
||||
let throwpoint = substitute(v:throwpoint, escape(s:tempfile, '.\'), a:file, 'g')
|
||||
let msg = throwpoint . ': '.v:exception
|
||||
call s:errors.add(a:file, 0, msg)
|
||||
finally
|
||||
call s:errors.crt_suite.conclude()
|
||||
" Never! the name must not be used by other Vim sessions
|
||||
" call delete(s:tempfile)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
function! s:StripResultAndDecode(expr)
|
||||
" Function needed because of an odd degenerescence of vim: commands
|
||||
" eventually loose their '\'
|
||||
return s:Decode(matchstr(a:expr, '^\d\+\s\+\zs.*'))
|
||||
endfunction
|
||||
|
||||
function! s:GetResult(expr)
|
||||
" Function needed because of an odd degenerescence of vim: commands
|
||||
" eventually loose their '\'
|
||||
return matchstr(a:expr, '^\d\+\ze\s\+.*')
|
||||
endfunction
|
||||
|
||||
function! s:DefineCommands()
|
||||
" NB: variables are already interpreted, make it a function
|
||||
" command! -nargs=1 Assert call s:Assert(<q-args>)
|
||||
command! -bang -nargs=1 UTAssert
|
||||
\ let s:a = s:StripResultAndDecode(<q-args>) |
|
||||
\ let s:ok = s:GetResult(<q-args>) |
|
||||
\ let s:errors.nb_asserts += 1 |
|
||||
\ if ! s:ok |
|
||||
\ call s:errors.set_test_failed() |
|
||||
\ call s:errors.add(s:a.file, s:a.line, 'assertion failed: '.s:a.expr) |
|
||||
\ if '<bang>' == '!' |
|
||||
\ throw "Assert: abort (".s:a.line.")" |
|
||||
\ endif |
|
||||
\ else |
|
||||
\ let s:errors.nb_successful_asserts += 1 |
|
||||
\ endif
|
||||
|
||||
command! -nargs=1 Comment
|
||||
\ let s:a = s:Decode(<q-args>) |
|
||||
\ call s:errors.add(s:a.file, s:a.line, eval(s:a.expr))
|
||||
command! -nargs=1 UTSuite call s:errors.set_suite(<q-args>)
|
||||
|
||||
command! -nargs=+ UTPlay call s:errors.crt_suite.play(<f-args>)
|
||||
command! -nargs=+ UTIgnore call s:errors.crt_suite.ignore(<f-args>)
|
||||
endfunction
|
||||
|
||||
function! s:UnDefineCommands()
|
||||
silent! delcommand Assert
|
||||
silent! delcommand UTAssert
|
||||
silent! command! -nargs=* UTSuite :echoerr "Use :UTRun and not :source on this script"<bar>finish
|
||||
silent! delcommand UTPlay
|
||||
silent! delcommand UTIgnore
|
||||
endfunction
|
||||
"------------------------------------------------------------------------
|
||||
" # callbacks {{{2
|
||||
function! lh#UT#callback_set_SNR(SNR)
|
||||
call s:errors.set_current_SNR(a:SNR)
|
||||
endfunction
|
||||
|
||||
" # Main function {{{2
|
||||
function! lh#UT#run(bang,...)
|
||||
" 1- clear the errors table
|
||||
let must_keep = a:bang == "!"
|
||||
if ! must_keep
|
||||
call s:errors.clear()
|
||||
endif
|
||||
|
||||
try
|
||||
" 2- define commands
|
||||
call s:DefineCommands()
|
||||
|
||||
" 3- run every test
|
||||
let rtp = '.,'.&rtp
|
||||
let files = []
|
||||
for file in a:000
|
||||
let lFile = lh#path#glob_as_list(rtp, file)
|
||||
if len(lFile) > 0
|
||||
call add(files, lFile[0])
|
||||
endif
|
||||
endfor
|
||||
|
||||
for file in files
|
||||
call s:RunOneFile(file)
|
||||
endfor
|
||||
finally
|
||||
call s:UnDefineCommands()
|
||||
call s:errors.display()
|
||||
endtry
|
||||
|
||||
" 3- Open the quickfix
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
||||
" VIM: let g:UTfiles='tests/lh/UT*.vim'
|
68
bundle/vim-mundo/tests/bundled/ut/autoload/should/be.vim
Normal file
68
bundle/vim-mundo/tests/bundled/ut/autoload/should/be.vim
Normal file
@ -0,0 +1,68 @@
|
||||
"=============================================================================
|
||||
" $Id: be.vim 193 2010-05-17 23:10:03Z luc.hermitte $
|
||||
" File: autoload/should/be.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://hermitte.free.fr/vim/>
|
||||
" Version: 0.0.3
|
||||
" Created: 23rd Feb 2009
|
||||
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description:
|
||||
" UT & tAssert API
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop this file into {rtp}/autoload/should
|
||||
" History:
|
||||
"
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
|
||||
" ## Functions {{{1
|
||||
" # Debug {{{2
|
||||
function! should#be#verbose(level)
|
||||
let s:verbose = a:level
|
||||
endfunction
|
||||
|
||||
function! s:Verbose(expr)
|
||||
if exists('s:verbose') && s:verbose
|
||||
echomsg a:expr
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! should#be#debug(expr)
|
||||
return eval(a:expr)
|
||||
endfunction
|
||||
|
||||
|
||||
" # Convinience functions for tAssert/UT {{{2
|
||||
function! should#be#list(var)
|
||||
return type(a:var) == type([])
|
||||
endfunction
|
||||
function! should#be#number(var)
|
||||
return type(a:var) == type(42)
|
||||
endfunction
|
||||
function! should#be#string(var)
|
||||
return type(a:var) == type('')
|
||||
endfunction
|
||||
function! should#be#dict(var)
|
||||
return type(a:var) == type({})
|
||||
endfunction
|
||||
function! should#be#float(var)
|
||||
return type(a:var) == type(0.1)
|
||||
endfunction
|
||||
function! should#be#funcref(var)
|
||||
return type(a:var) == type(function('exists'))
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
165
bundle/vim-mundo/tests/bundled/ut/doc/UT.txt
Normal file
165
bundle/vim-mundo/tests/bundled/ut/doc/UT.txt
Normal file
@ -0,0 +1,165 @@
|
||||
*UT.txt* Unit Testing Framework for Vim (v0.0.3)
|
||||
For Vim version 7+. Last change: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
|
||||
|
||||
By Luc Hermitte
|
||||
hermitte {at} free {dot} fr
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
CONTENTS *UT-contents* {{{1
|
||||
|UT-presentation| Presentation
|
||||
|UT-usage| Usage
|
||||
|UT-API| UT API
|
||||
|UT-examples| Examples
|
||||
|UT-todo| Bugs to fix and futur enhancements to come
|
||||
|UT-design| Design choices
|
||||
|UT-others| Other tests related plugins for vim
|
||||
|add-local-help| Instructions on installing this file
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
PRESENTATION *UT-presentation* {{{1
|
||||
UT is another Test Unit Framework for Vim, which main particularity is to fill
|
||||
the |quickfix| window with the assertion failures.
|
||||
|
||||
Features~
|
||||
- Assertion failures are reported in the |quickfix| window
|
||||
- Assertion syntax is simple, check Tom Link's suite, it's the same
|
||||
- Supports banged ":Assert!" to stop processing a given test on failed
|
||||
assertions
|
||||
- All the |s:Test()| functions of a suite are executed (almost)
|
||||
independently (i.e., a critical ":Assert!" failure will stop the Test of
|
||||
the function, and |lh#UT| will proceed to the next |s:Test()| function
|
||||
- Lightweight and simple to use: there is only one command defined, all the
|
||||
other definitions are kept in an autoload plugin.
|
||||
- A suite == a file
|
||||
- Several |s:Test()| functions per suite
|
||||
- +optional |s:Setup()|, |s:Teardown()|
|
||||
- Supports |:Comments|
|
||||
- |local-function|s, |script-variable|s, and |local-variable|s are supported
|
||||
- Takes advantage of |BuildToolsWrapper|'s |:Copen| command if installed
|
||||
- Counts successful tests and not successful assertions
|
||||
- Short-cuts to run the Unit Tests associated to a given vim script; Relies
|
||||
on: |Let-Modeline|, |local_vimrc|/|project.vim| to set |g:UTfiles| (space
|
||||
separated list of glob-able paths), and on |lhvl#path|.
|
||||
- Command to exclude, or specify the tests to play => |:UTPlay|, |UTIgnore|
|
||||
|
||||
Requirements~
|
||||
This suite requires Vim 7.1 and |lh-vim-lib| v2.2.0+.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
USAGE *UT-usage* {{{1
|
||||
First, create a new vim script, it will be a Unit Testing Suite.
|
||||
|
||||
*:UTSuite*
|
||||
One of the first lines must contain >
|
||||
UTSuite Some intelligible name for the suite
|
||||
<
|
||||
*:Assert*
|
||||
Then you are free to directly assert anything you wish as long as it is a
|
||||
valid vim |expression|, e.g. >
|
||||
Assert 1 > 2
|
||||
Assert 1 > 0
|
||||
Assert s:foo > s:Bar(g:var + 28) / strlen("foobar")
|
||||
or to define as many independent tests as you wish.
|
||||
|
||||
*:Comment*
|
||||
Comments may be added to the |quickfix| report thanks to the |:Comment|
|
||||
fake command.
|
||||
*s:Test()*
|
||||
A test is a function with a name starting with |s:Test|. Even if a test
|
||||
critically fails, the next test will be executed, e.g. >
|
||||
function s:Test1()
|
||||
let var = SomeFucntion()
|
||||
Assert! type(var) == type(0)
|
||||
Assert var < 42
|
||||
Assert! var > 0
|
||||
|
||||
" Some other code that won't be executed if the previous assertion failed
|
||||
let i = var / 42.0
|
||||
Comment This comment may never be displayed if {var} is negative or not a number
|
||||
endfunction
|
||||
|
||||
function s:Test2()
|
||||
Assert s:what != Ever()
|
||||
endfunction
|
||||
<
|
||||
*s:Setup()* *s:Teardown()*
|
||||
If you wish to see a set-up function executed before each test, define the
|
||||
|s:Setup()| function.
|
||||
|
||||
If you wish to see a clean-up function executed after each test, define the
|
||||
|s:Teardown()| function.
|
||||
|
||||
*:UTRun*
|
||||
Finally run |:UTRun| on your test script (filename), and ... debug your failed
|
||||
assertions from the |quickfix| window.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
UT API *UT-API* {{{1
|
||||
|
||||
*should#be#dict()* returns whether the parameter is a |Dictionary|
|
||||
*should#be#float()* returns whether the parameter is a |float|
|
||||
*should#be#funcref()* returns whether the parameter is a |Funcref|
|
||||
*should#be#list()* returns whether the parameter is a |List|
|
||||
*should#be#number()* returns whether the parameter is a |expr-number|
|
||||
*should#be#string()* returns whether the parameter is a |expr-string|
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
EXAMPLES *UT-examples* {{{1
|
||||
See:
|
||||
- {rtp}/tests/lh/UT.vim tests/lh/UT.vim for a classical test,
|
||||
- {rtp}/tests/lh/UT-fixtures.vim tests/lh/UT-fixtures.vim for a test with
|
||||
fixtures.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
TO DO *UT-todo* {{{1
|
||||
- Add |'efm'| for VimL errors like the one produced by >
|
||||
:Assert 0 + [0]
|
||||
- Check UT works fine under windows (where paths have spaces, etc), and on
|
||||
UTF-8 files
|
||||
- Simplify "s:errors" functions
|
||||
- Merge with Tom Link's tAssert plugin? (the UI is quite different)
|
||||
- |:AssertEquals| that shows the name of both expressions and their values as
|
||||
well -- a correct distinction of both parameters will be tricky with regexes
|
||||
; using functions will loose either the name, or the value in case of
|
||||
local/script variables use ; we need macros /à la C/...
|
||||
- Support Embedded comments like for instance: >
|
||||
Assert 1 == 1 " 1 must value 1
|
||||
- Ways to test buffers produced
|
||||
- Always execute |s:Teardown()| -- move its call to a |:finally| bloc
|
||||
- Find a way to prevent the potential script scope pollution
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
DESIGN CHOICES *UT-design* {{{1
|
||||
The assertions supported by this plugin are expected to be made in a Unit
|
||||
Testing file, they are not to be used in regular VimL scripts as a /Design by
|
||||
Contract/ tool. Check Thomas Link's plugin, it is much more suited for that
|
||||
kind of assertions.
|
||||
|
||||
In order to be able to produce the |quickfix| entries, the plugin first parses
|
||||
the Unit Test file to complete all |:Assert| occurrences with extra
|
||||
information about the line number where the assertion is made.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
OTHER TESTS RELATED PLUGINS FOR VIM *UT-others* {{{1
|
||||
You may also want to have a look at:
|
||||
- Tom Link's |tAssert| plugin
|
||||
http://www.vim.org/scripts/script.php?script_id=1730
|
||||
- Staale Flock's |vimUnit| plugin
|
||||
http://www.vim.org/scripts/script.php?script_id=1125
|
||||
- Meikel Brandmeyer's |vimTAP| plugin
|
||||
http://www.vim.org/scripts/script.php?script_id=2213
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
© Luc Hermitte, 2010, http://code.google.com/p/lh-vim/
|
||||
$Id: UT.txt 193 2010-05-17 23:10:03Z luc.hermitte $
|
||||
VIM: let b:VS_language = 'american'
|
||||
vim:ts=8:sw=4:tw=80:fo=tcq2:isk=!-~,^*,^\|,^\":ft=help:fdm=marker:
|
67
bundle/vim-mundo/tests/bundled/ut/ftplugin/vim/vim_UT.vim
Normal file
67
bundle/vim-mundo/tests/bundled/ut/ftplugin/vim/vim_UT.vim
Normal file
@ -0,0 +1,67 @@
|
||||
"=============================================================================
|
||||
" $Id: vim_UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
|
||||
" File: ftplugin/vim/vim_UT.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
let s:k_version = 003
|
||||
" Version: 0.0.3
|
||||
" Created: 20th Feb 2009
|
||||
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: Yet Another Unit Testing Framework for Vim
|
||||
" - Defines <F7> as :UTRun {targets=g:UTfiles}
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
" Buffer-local Definitions {{{1
|
||||
" Avoid local reinclusion {{{2
|
||||
if &cp || (exists("b:loaded_ftplug_vim_UT") && !exists('g:force_reload_ftplug_vim_UT'))
|
||||
finish
|
||||
endif
|
||||
let b:loaded_ftplug_vim_UT = s:k_version
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
" Avoid local reinclusion }}}2
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
" Local mappings {{{2
|
||||
|
||||
nnoremap <buffer> <silent> <Plug>UTMake :call <sid>UTMake()<cr>
|
||||
|
||||
let s:key = lh#option#get('UTMake_key', '<F7>')
|
||||
exe 'imap <buffer> '.s:key.' <c-\><c-n><Plug>UTMake'
|
||||
exe 'vmap <buffer> '.s:key.' <c-\><c-n><Plug>UTMake'
|
||||
exe 'nmap <buffer> '.s:key.' <Plug>UTMake'
|
||||
|
||||
"=============================================================================
|
||||
" Global Definitions {{{1
|
||||
" Avoid global reinclusion {{{2
|
||||
if &cp || (exists("g:loaded_ftplug_vim_UT") && !exists('g:force_reload_ftplug_vim_UT'))
|
||||
let &cpo=s:cpo_save
|
||||
finish
|
||||
endif
|
||||
let g:loaded_ftplug_vim_UT = s:k_version
|
||||
" Avoid global reinclusion }}}2
|
||||
"------------------------------------------------------------------------
|
||||
" Functions {{{2
|
||||
|
||||
function! s:UTMake()
|
||||
let files = lh#option#get('UTfiles', '%')
|
||||
echo 'update|source '.expand('%').'|UTRun '.files
|
||||
update
|
||||
so%
|
||||
exe 'UTRun '.files
|
||||
endfunction
|
||||
|
||||
|
||||
" Functions }}}2
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
||||
" VIM: let g:UTfiles='tests/lh/UT*.vim'
|
32
bundle/vim-mundo/tests/bundled/ut/mkVba/mk-UT.vim
Normal file
32
bundle/vim-mundo/tests/bundled/ut/mkVba/mk-UT.vim
Normal file
@ -0,0 +1,32 @@
|
||||
"=============================================================================
|
||||
" $Id: mk-UT.vim 194 2010-05-17 23:26:14Z luc.hermitte $
|
||||
" File: mk-UT.vim
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://hermitte.free.fr/vim/>
|
||||
" Version: 0.0.3
|
||||
let s:version = '0.0.3'
|
||||
" Created: 19th Feb 2009
|
||||
" Last Update: $Date: 2010-05-17 19:26:14 -0400 (Mon, 17 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
cd <sfile>:p:h
|
||||
try
|
||||
let save_rtp = &rtp
|
||||
let &rtp = expand('<sfile>:p:h:h').','.&rtp
|
||||
exe '22,$MkVimball! UT-'.s:version
|
||||
set modifiable
|
||||
set buftype=
|
||||
finally
|
||||
let &rtp = save_rtp
|
||||
endtry
|
||||
finish
|
||||
UT.README
|
||||
autoload/lh/UT.vim
|
||||
autoload/should.vim
|
||||
autoload/should/be.vim
|
||||
doc/UT.txt
|
||||
ftplugin/vim/vim_UT.vim
|
||||
mkVba/mk-UT.vim
|
||||
plugin/UT.vim
|
||||
tests/lh/UT-fixtures.vim
|
||||
tests/lh/UT.vim
|
||||
tests/lh/assert.vim
|
48
bundle/vim-mundo/tests/bundled/ut/plugin/UT.vim
Normal file
48
bundle/vim-mundo/tests/bundled/ut/plugin/UT.vim
Normal file
@ -0,0 +1,48 @@
|
||||
"=============================================================================
|
||||
" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
|
||||
" File: plugin/UT.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://code.google.com/p/lh-vim/>
|
||||
let s:k_version = 003
|
||||
" Version: 0.0.3
|
||||
" Created: 11th Feb 2009
|
||||
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: Yet Another Unit Testing Framework for Vim
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation:
|
||||
" Drop the file into {rtp}/plugin/lh/
|
||||
" History:
|
||||
" Strongly inspired by Tom Link's tAssert
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
" Avoid global reinclusion {{{1
|
||||
if &cp || (exists("g:loaded_UT") && !exists('g:force_reload_UT'))
|
||||
finish
|
||||
endif
|
||||
let g:loaded_UT = s:k_version
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
" Avoid global reinclusion }}}1
|
||||
"------------------------------------------------------------------------
|
||||
" Commands and Mappings {{{1
|
||||
|
||||
" Real commands (used to call UT files)
|
||||
"command! UTRun {filenames}
|
||||
command! -bang -nargs=+ -complete=file UTRun :call lh#UT#run("<bang>",<f-args>)
|
||||
|
||||
" Fake commands (used in UT files)
|
||||
"command UTSuite {expression} [#{comments}]
|
||||
command! -nargs=* UTSuite :echoerr "Use :UTRun and not :source on this script"<bar>finish
|
||||
"command Assert {expression} [#{comments}]
|
||||
|
||||
|
||||
" Commands and Mappings }}}1
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
||||
" VIM: let g:UTfiles='tests/lh/UT*.vim'
|
58
bundle/vim-mundo/tests/bundled/ut/tests/lh/UT-fixtures.vim
Normal file
58
bundle/vim-mundo/tests/bundled/ut/tests/lh/UT-fixtures.vim
Normal file
@ -0,0 +1,58 @@
|
||||
"=============================================================================
|
||||
" $Id: UT-fixtures.vim 193 2010-05-17 23:10:03Z luc.hermitte $
|
||||
" File: tests/lh/UT-fixtures.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://hermitte.free.fr/vim/>
|
||||
" Version: 0.0.1
|
||||
" Created: 11th Feb 2009
|
||||
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: UnitTests for the UT plugin.
|
||||
" - Test fixtures
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
UTSuite [lh#UT] Testing fixtures
|
||||
|
||||
let s:v1 = 0
|
||||
let s:v2 = 0
|
||||
|
||||
function! s:Setup()
|
||||
Assert! exists('s:v1')
|
||||
Assert! exists('s:v2')
|
||||
let s:v1 += 1
|
||||
let s:v2 += 1
|
||||
endfunction
|
||||
|
||||
function! s:Teardown()
|
||||
let s:v1 = 0
|
||||
endfunction
|
||||
|
||||
function! s:TestSetup()
|
||||
Comment "First test weither s:v1 and g:v2 are set to 1"
|
||||
" Assert0 s:v1 == 1
|
||||
Assert s:v1 == 1
|
||||
Assert s:v2 == 1
|
||||
endfunction
|
||||
|
||||
function! s:TestTeardown()
|
||||
Comment "Second test weither only s:v1 is incremented, while g:v2 is set to 1"
|
||||
Assert s:v1 == 1
|
||||
Assert s:v2 == 2
|
||||
endfunction
|
||||
|
||||
" UTPlay TestTeardown
|
||||
UTIgnore TestTeardown
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
73
bundle/vim-mundo/tests/bundled/ut/tests/lh/UT.vim
Normal file
73
bundle/vim-mundo/tests/bundled/ut/tests/lh/UT.vim
Normal file
@ -0,0 +1,73 @@
|
||||
"=============================================================================
|
||||
" $Id: UT.vim 193 2010-05-17 23:10:03Z luc.hermitte $
|
||||
" File: tests/lh/UT.vim {{{1
|
||||
" Author: Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
|
||||
" <URL:http://hermitte.free.fr/vim/>
|
||||
" Version: 0.0.1
|
||||
" Created: 11th Feb 2009
|
||||
" Last Update: $Date: 2010-05-17 19:10:03 -0400 (Mon, 17 May 2010) $
|
||||
"------------------------------------------------------------------------
|
||||
" Description: UnitTests for the UT plugin.
|
||||
" - Tests global assertions
|
||||
" - Tests assertions definied in tests (functions s:Test)
|
||||
"
|
||||
"------------------------------------------------------------------------
|
||||
" Installation: «install details»
|
||||
" History: «history»
|
||||
" TODO: «missing features»
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
|
||||
let s:cpo_save=&cpo
|
||||
set cpo&vim
|
||||
"------------------------------------------------------------------------
|
||||
UTSuite [lh#UT] Testing global and local assertions
|
||||
|
||||
Assert 1 == 1
|
||||
Assert 1 != 42
|
||||
Assert 1 < 20
|
||||
Assert 1 > 20
|
||||
|
||||
let st = "string"
|
||||
Assert st =~ 'str'
|
||||
Assert st !~ 'str'
|
||||
Assert st == 'str'
|
||||
Assert st != 'str'
|
||||
Assert st == 0
|
||||
" Assert 0 + [0]
|
||||
|
||||
function! s:One()
|
||||
return 1
|
||||
endfunction
|
||||
Assert s:One() == 1
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
function! s:TestOK()
|
||||
Comment "TestOK"
|
||||
Assert! 1 == 1
|
||||
Assert 1 == 1
|
||||
Assert repeat('1', 5) == '11111'
|
||||
Assert! repeat('1', 5) == '11111'
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
function! s:TestCriticalNOK()
|
||||
Comment "TestCriticalNOK"
|
||||
Assert! 1 == 0
|
||||
Assert repeat('1', 5) == '1111'
|
||||
endfunction
|
||||
|
||||
"------------------------------------------------------------------------
|
||||
function! s:TestNOK()
|
||||
Comment "TestNOK"
|
||||
Assert 0 == 1
|
||||
Assert repeat('1', 5) == '1111'
|
||||
endfunction
|
||||
|
||||
function! s:Foo()
|
||||
endfunction
|
||||
"------------------------------------------------------------------------
|
||||
"------------------------------------------------------------------------
|
||||
let &cpo=s:cpo_save
|
||||
"=============================================================================
|
||||
" vim600: set fdm=marker:
|
13
bundle/vim-mundo/tests/run-tests.sh
Normal file
13
bundle/vim-mundo/tests/run-tests.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $# -eq 0 ]]
|
||||
then
|
||||
TESTS="`ls *.vim | tr "\n" ' '`"
|
||||
else
|
||||
IFS=' '
|
||||
TESTS="$*"
|
||||
fi
|
||||
|
||||
vim -u vimrc_test -c ":UTRun $TESTS"
|
64
bundle/vim-mundo/tests/test-graph.vim
Normal file
64
bundle/vim-mundo/tests/test-graph.vim
Normal file
@ -0,0 +1,64 @@
|
||||
UTSuite [Mundo] Testing Toggling
|
||||
|
||||
function! s:Setup()"{{{
|
||||
exec 'edit test'
|
||||
call g:Goto('test')
|
||||
setlocal buftype=nofile
|
||||
endfunction"}}}
|
||||
function! s:Teardown()"{{{
|
||||
if bufwinnr(bufnr('__Mundo__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufwinnr(bufnr('__Mundo_Preview__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo_Preview__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufnr('__Mundo__') != -1
|
||||
exec 'bwipeout ' . bufnr('__Mundo__')
|
||||
endif
|
||||
if bufnr('__Mundo_Preview__') != -1
|
||||
exec 'bwipeout ' . bufnr('__Mundo_Preview__')
|
||||
endif
|
||||
if bufnr('test') != -1
|
||||
exec 'bwipeout ' . bufnr('test')
|
||||
endif
|
||||
if bufnr('test2') != -1
|
||||
exec 'bwipeout ' . bufnr('test2')
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestToggleBasic()"{{{
|
||||
call g:TypeLine("ONE")
|
||||
call g:TypeLineDone("TWO")
|
||||
|
||||
MundoToggle
|
||||
|
||||
Assert g:Contains("o [0]")
|
||||
Assert g:Contains("o [1]")
|
||||
Assert g:Contains("@ [2]")
|
||||
Assert !g:Contains("[3]")
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestToggleBranches()"{{{
|
||||
call g:TypeLineDone("ONE")
|
||||
silent! undo
|
||||
call g:TypeLineDone("TWO")
|
||||
|
||||
MundoToggle
|
||||
|
||||
" Make sure there is a branch next to state 2
|
||||
call g:GotoLineContaining("[1]")
|
||||
Assert g:CurrentLineContains("|")
|
||||
|
||||
" Make sure there is no branch next to states 0 and 2
|
||||
call g:GotoLineContaining("[0]")
|
||||
Assert !g:CurrentLineContains("|")
|
||||
call g:GotoLineContaining("[2]")
|
||||
Assert !g:CurrentLineContains("|")
|
||||
|
||||
" Make sure the branch point is directly above state 0
|
||||
call g:GotoLineContaining("[0]")
|
||||
call g:MoveUp()
|
||||
Assert g:CurrentLineContains("|/")
|
||||
endfunction"}}}
|
150
bundle/vim-mundo/tests/test-movement.vim
Normal file
150
bundle/vim-mundo/tests/test-movement.vim
Normal file
@ -0,0 +1,150 @@
|
||||
UTSuite [Mundo] Testing Movement
|
||||
|
||||
function! s:Setup()"{{{
|
||||
exec 'edit test'
|
||||
call g:Goto('test')
|
||||
endfunction"}}}
|
||||
function! s:Teardown()"{{{
|
||||
if bufwinnr(bufnr('__Mundo__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufwinnr(bufnr('__Mundo_Preview__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo_Preview__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufnr('__Mundo__') != -1
|
||||
exec 'bwipeout! ' . bufnr('__Mundo__')
|
||||
endif
|
||||
if bufnr('__Mundo_Preview__') != -1
|
||||
exec 'bwipeout! ' . bufnr('__Mundo_Preview__')
|
||||
endif
|
||||
if bufnr('test') != -1
|
||||
exec 'bwipeout! ' . bufnr('test')
|
||||
endif
|
||||
if bufnr('test2') != -1
|
||||
exec 'bwipeout! ' . bufnr('test2')
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestMovementBasic()"{{{
|
||||
" Make three linear changes
|
||||
call g:TypeLineDone("ONE")
|
||||
call g:TypeLineDone("TWO")
|
||||
call g:TypeLineDone("THREE")
|
||||
|
||||
" Open Mundo
|
||||
MundoToggle
|
||||
|
||||
" Make sure we're on the newest/current state
|
||||
Assert g:CurrentLineContains("[3]")
|
||||
|
||||
" Move down
|
||||
normal j
|
||||
Assert g:CurrentLineContains("[2]")
|
||||
|
||||
" Move down
|
||||
normal j
|
||||
Assert g:CurrentLineContains("[1]")
|
||||
|
||||
" Move down
|
||||
normal j
|
||||
Assert g:CurrentLineContains("[0]")
|
||||
|
||||
" Move up
|
||||
normal k
|
||||
Assert g:CurrentLineContains("[1]")
|
||||
|
||||
" Move up
|
||||
normal k
|
||||
Assert g:CurrentLineContains("[2]")
|
||||
|
||||
" Move up
|
||||
normal k
|
||||
Assert g:CurrentLineContains("[3]")
|
||||
|
||||
" Test arrow mappings
|
||||
|
||||
" Move down
|
||||
exec "normal \<down>"
|
||||
Assert g:CurrentLineContains("[2]")
|
||||
|
||||
" Move down
|
||||
exec "normal \<down>"
|
||||
Assert g:CurrentLineContains("[1]")
|
||||
|
||||
" Move down
|
||||
exec "normal \<down>"
|
||||
Assert g:CurrentLineContains("[0]")
|
||||
|
||||
" Move up
|
||||
exec "normal \<up>"
|
||||
Assert g:CurrentLineContains("[1]")
|
||||
|
||||
" Move up
|
||||
exec "normal \<up>"
|
||||
Assert g:CurrentLineContains("[2]")
|
||||
|
||||
" Move up
|
||||
exec "normal \<up>"
|
||||
Assert g:CurrentLineContains("[3]")
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestMovementLinear()"{{{
|
||||
" Make four changes:
|
||||
"
|
||||
" o [4]
|
||||
" |
|
||||
" | o [3]
|
||||
" | |
|
||||
" o | [2]
|
||||
" |/
|
||||
" o [1]
|
||||
" |
|
||||
" o [0] (original)
|
||||
|
||||
call g:TypeLineDone("ONE")
|
||||
call g:TypeLineDone("TWO")
|
||||
silent! undo
|
||||
call g:TypeLineDone("THREE")
|
||||
silent! undo 2
|
||||
call g:TypeLineDone("FOUR")
|
||||
|
||||
" Open Mundo
|
||||
MundoToggle
|
||||
|
||||
" Make sure we're on the newest/current state
|
||||
Assert g:CurrentLineContains("[4]")
|
||||
|
||||
" Move down
|
||||
normal j
|
||||
Assert g:CurrentLineContains("[3]")
|
||||
|
||||
" Move down
|
||||
normal j
|
||||
Assert g:CurrentLineContains("[2]")
|
||||
|
||||
" Move down
|
||||
normal j
|
||||
Assert g:CurrentLineContains("[1]")
|
||||
|
||||
" Move down
|
||||
normal j
|
||||
Assert g:CurrentLineContains("[0]")
|
||||
|
||||
" Move up
|
||||
normal k
|
||||
Assert g:CurrentLineContains("[1]")
|
||||
|
||||
" Move up
|
||||
normal k
|
||||
Assert g:CurrentLineContains("[2]")
|
||||
|
||||
" Move up
|
||||
normal k
|
||||
Assert g:CurrentLineContains("[3]")
|
||||
|
||||
" Move up
|
||||
normal k
|
||||
Assert g:CurrentLineContains("[4]")
|
||||
endfunction"}}}
|
131
bundle/vim-mundo/tests/test-preview.vim
Normal file
131
bundle/vim-mundo/tests/test-preview.vim
Normal file
@ -0,0 +1,131 @@
|
||||
UTSuite [Mundo] Testing Preview Pane
|
||||
|
||||
function! s:Setup()"{{{
|
||||
exec 'edit test'
|
||||
call g:Goto('test')
|
||||
endfunction"}}}
|
||||
function! s:Teardown()"{{{
|
||||
if bufwinnr(bufnr('__Mundo__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufwinnr(bufnr('__Mundo_Preview__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo_Preview__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufnr('__Mundo__') != -1
|
||||
exec 'bwipeout! ' . bufnr('__Mundo__')
|
||||
endif
|
||||
if bufnr('__Mundo_Preview__') != -1
|
||||
exec 'bwipeout! ' . bufnr('__Mundo_Preview__')
|
||||
endif
|
||||
if bufnr('test') != -1
|
||||
exec 'bwipeout! ' . bufnr('test')
|
||||
endif
|
||||
if bufnr('test2') != -1
|
||||
exec 'bwipeout! ' . bufnr('test2')
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestPreviewBasic()"{{{
|
||||
" Make three linear changes, then a change that deletes the last line
|
||||
call g:TypeLineDone("ONE")
|
||||
call g:TypeLineDone("TWO")
|
||||
call g:TypeLineDone("THREE")
|
||||
normal k
|
||||
normal dd
|
||||
|
||||
" Open Mundo
|
||||
MundoToggle
|
||||
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("THREE")
|
||||
Assert g:CurrentLineContains("-THREE")
|
||||
|
||||
call g:Goto("__Mundo__")
|
||||
normal j
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("THREE")
|
||||
Assert g:CurrentLineContains("+THREE")
|
||||
|
||||
call g:Goto("__Mundo__")
|
||||
normal j
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("TWO")
|
||||
Assert g:CurrentLineContains("+TWO")
|
||||
|
||||
call g:Goto("__Mundo__")
|
||||
normal j
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("ONE")
|
||||
Assert g:CurrentLineContains("+ONE")
|
||||
|
||||
call g:Goto("__Mundo__")
|
||||
normal k
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("TWO")
|
||||
Assert g:CurrentLineContains("+TWO")
|
||||
|
||||
call g:Goto("__Mundo__")
|
||||
normal k
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("THREE")
|
||||
Assert g:CurrentLineContains("+THREE")
|
||||
|
||||
call g:Goto("__Mundo__")
|
||||
normal k
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("THREE")
|
||||
Assert g:CurrentLineContains("-THREE")
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestPreviewLinear()"{{{
|
||||
" Make four non-linear changes
|
||||
"
|
||||
" o [4]
|
||||
" |
|
||||
" | o [3]
|
||||
" | |
|
||||
" o | [2]
|
||||
" |/
|
||||
" o [1]
|
||||
|
||||
call g:TypeLineDone("ONE")
|
||||
call g:TypeLineDone("TWO")
|
||||
silent! undo
|
||||
call g:TypeLineDone("THREE")
|
||||
silent! undo 2
|
||||
call g:TypeLineDone("FOUR")
|
||||
|
||||
" Open Mundo
|
||||
MundoToggle
|
||||
|
||||
" Check state 4
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("FOUR")
|
||||
Assert g:CurrentLineContains("+FOUR")
|
||||
call g:GotoLineContaining("THREE")
|
||||
Assert !g:CurrentLineContains("THREE")
|
||||
|
||||
" Check state 3
|
||||
call g:Goto("__Mundo__")
|
||||
normal j
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("THREE")
|
||||
Assert g:CurrentLineContains("+THREE")
|
||||
call g:GotoLineContaining("FOUR")
|
||||
Assert !g:CurrentLineContains("FOUR")
|
||||
call g:GotoLineContaining("TWO")
|
||||
Assert !g:CurrentLineContains("TWO")
|
||||
call g:GotoLineContaining("ONE")
|
||||
Assert g:CurrentLineContains("ONE")
|
||||
|
||||
" Check state 2
|
||||
call g:Goto("__Mundo__")
|
||||
normal j
|
||||
call g:Goto("__Mundo_Preview__")
|
||||
call g:GotoLineContaining("TWO")
|
||||
Assert g:CurrentLineContains("+TWO")
|
||||
call g:GotoLineContaining("ONE")
|
||||
Assert g:CurrentLineContains("ONE")
|
||||
endfunction"}}}
|
123
bundle/vim-mundo/tests/test-toggle.vim
Normal file
123
bundle/vim-mundo/tests/test-toggle.vim
Normal file
@ -0,0 +1,123 @@
|
||||
UTSuite [Mundo] Testing Toggling
|
||||
|
||||
function! s:Setup()"{{{
|
||||
exec 'edit test'
|
||||
call g:Goto('test')
|
||||
endfunction"}}}
|
||||
function! s:Teardown()"{{{
|
||||
if bufwinnr(bufnr('__Mundo__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufwinnr(bufnr('__Mundo_Preview__')) != -1
|
||||
exec bufwinnr(bufnr('__Mundo_Preview__')) . 'wincmd w'
|
||||
quit
|
||||
endif
|
||||
if bufnr('__Mundo__') != -1
|
||||
exec 'bwipeout ' . bufnr('__Mundo__')
|
||||
endif
|
||||
if bufnr('__Mundo_Preview__') != -1
|
||||
exec 'bwipeout ' . bufnr('__Mundo_Preview__')
|
||||
endif
|
||||
if bufnr('test') != -1
|
||||
exec 'bwipeout ' . bufnr('test')
|
||||
endif
|
||||
if bufnr('test2') != -1
|
||||
exec 'bwipeout ' . bufnr('test2')
|
||||
endif
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestToggleBasic()"{{{
|
||||
" Make sure we're starting from scratch.
|
||||
Assert bufnr('__Mundo__') == -1
|
||||
Assert bufnr('__Mundo_Preview__') == -1
|
||||
Assert bufwinnr(bufnr('__Mundo__')) == -1
|
||||
Assert bufwinnr(bufnr('__Mundo_Preview__')) == -1
|
||||
|
||||
" Open Mundo
|
||||
MundoToggle
|
||||
|
||||
" Buffers and windows should exist.
|
||||
Assert bufnr('__Mundo__') != -1
|
||||
Assert bufnr('__Mundo_Preview__') != -1
|
||||
Assert bufwinnr(bufnr('__Mundo__')) != -1
|
||||
Assert bufwinnr(bufnr('__Mundo_Preview__')) != -1
|
||||
|
||||
" We should be in the Mundo pane.
|
||||
Assert expand('%') == '__Mundo__'
|
||||
|
||||
" Close Mundo
|
||||
MundoToggle
|
||||
|
||||
" Windows should have been closed, but buffers should remain.
|
||||
Assert bufnr('__Mundo__') != -1
|
||||
Assert bufnr('__Mundo_Preview__') != -1
|
||||
Assert bufwinnr(bufnr('__Mundo__')) == -1
|
||||
Assert bufwinnr(bufnr('__Mundo_Preview__')) == -1
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestToggleWhenMoved()"{{{
|
||||
" Make sure we're starting from scratch.
|
||||
Assert bufnr('__Mundo__') == -1
|
||||
Assert bufnr('__Mundo_Preview__') == -1
|
||||
Assert bufwinnr(bufnr('__Mundo__')) == -1
|
||||
Assert bufwinnr(bufnr('__Mundo_Preview__')) == -1
|
||||
|
||||
" Open Mundo
|
||||
MundoToggle
|
||||
|
||||
call g:Goto('test')
|
||||
Assert expand('%') == 'test'
|
||||
|
||||
" Close Mundo
|
||||
MundoToggle
|
||||
|
||||
" Windows should have been closed, but buffers should remain.
|
||||
Assert bufnr('__Mundo__') != -1
|
||||
Assert bufnr('__Mundo_Preview__') != -1
|
||||
Assert bufwinnr(bufnr('__Mundo__')) == -1
|
||||
Assert bufwinnr(bufnr('__Mundo_Preview__')) == -1
|
||||
|
||||
" Open Mundo
|
||||
MundoToggle
|
||||
|
||||
call g:Goto('__Mundo_Preview__')
|
||||
Assert expand('%') == '__Mundo_Preview__'
|
||||
|
||||
" Close Mundo
|
||||
MundoToggle
|
||||
|
||||
" Windows should have been closed, but buffers should remain.
|
||||
Assert bufnr('__Mundo__') != -1
|
||||
Assert bufnr('__Mundo_Preview__') != -1
|
||||
Assert bufwinnr(bufnr('__Mundo__')) == -1
|
||||
Assert bufwinnr(bufnr('__Mundo_Preview__')) == -1
|
||||
endfunction"}}}
|
||||
|
||||
function! s:TestToggleReturnToTarget()"{{{
|
||||
" Make sure we're starting from scratch.
|
||||
Assert bufnr('__Mundo__') == -1
|
||||
Assert bufnr('__Mundo_Preview__') == -1
|
||||
Assert bufwinnr(bufnr('__Mundo__')) == -1
|
||||
Assert bufwinnr(bufnr('__Mundo_Preview__')) == -1
|
||||
|
||||
exec 'new test2'
|
||||
call g:Goto('test')
|
||||
|
||||
" Toggle Mundo
|
||||
MundoToggle
|
||||
MundoToggle
|
||||
|
||||
" We should be returned to test
|
||||
Assert expand('%') == 'test'
|
||||
|
||||
" Move to test2
|
||||
call g:Goto('test2')
|
||||
|
||||
" Toggle Mundo
|
||||
MundoToggle
|
||||
MundoToggle
|
||||
|
||||
" We should be returned to test2
|
||||
Assert expand('%') == 'test2'
|
||||
endfunction"}}}
|
108
bundle/vim-mundo/tests/vim_test/colors/desert.vim
Normal file
108
bundle/vim-mundo/tests/vim_test/colors/desert.vim
Normal file
@ -0,0 +1,108 @@
|
||||
" Vim color file
|
||||
" Maintainer: Hans Fugal <hans@fugal.net>
|
||||
" Last Change: $Date: 2004/06/13 19:30:30 $
|
||||
" Last Change: $Date: 2004/06/13 19:30:30 $
|
||||
" URL: http://hans.fugal.net/vim/colors/desert.vim
|
||||
" Version: $Id: desert.vim,v 1.1 2004/06/13 19:30:30 vimboss Exp $
|
||||
|
||||
" cool help screens
|
||||
" :he group-name
|
||||
" :he highlight-groups
|
||||
" :he cterm-colors
|
||||
|
||||
set background=dark
|
||||
if version > 580
|
||||
" no guarantees for version 5.8 and below, but this makes it stop
|
||||
" complaining
|
||||
hi clear
|
||||
if exists("syntax_on")
|
||||
syntax reset
|
||||
endif
|
||||
endif
|
||||
let g:colors_name="desert"
|
||||
|
||||
hi Normal guifg=White guibg=grey20
|
||||
|
||||
" highlight groups
|
||||
hi Cursor guibg=khaki guifg=slategrey
|
||||
"hi CursorIM
|
||||
"hi Directory
|
||||
"hi DiffAdd
|
||||
"hi DiffChange
|
||||
"hi DiffDelete
|
||||
"hi DiffText
|
||||
"hi ErrorMsg
|
||||
hi VertSplit guibg=#c2bfa5 guifg=grey50 gui=none
|
||||
hi Folded guibg=grey30 guifg=gold
|
||||
hi FoldColumn guibg=grey30 guifg=tan
|
||||
hi IncSearch guifg=slategrey guibg=khaki
|
||||
"hi LineNr
|
||||
hi ModeMsg guifg=goldenrod
|
||||
hi MoreMsg guifg=SeaGreen
|
||||
hi NonText guifg=LightBlue guibg=grey30
|
||||
hi Question guifg=springgreen
|
||||
hi Search guibg=peru guifg=wheat
|
||||
hi SpecialKey guifg=yellowgreen
|
||||
hi StatusLine guibg=#c2bfa5 guifg=black gui=none
|
||||
hi StatusLineNC guibg=#c2bfa5 guifg=grey50 gui=none
|
||||
hi Title guifg=indianred
|
||||
hi Visual gui=none guifg=khaki guibg=olivedrab
|
||||
"hi VisualNOS
|
||||
hi WarningMsg guifg=salmon
|
||||
"hi WildMenu
|
||||
"hi Menu
|
||||
"hi Scrollbar
|
||||
"hi Tooltip
|
||||
|
||||
" syntax highlighting groups
|
||||
hi Comment guifg=SkyBlue
|
||||
hi Constant guifg=#ffa0a0
|
||||
hi Identifier guifg=palegreen
|
||||
hi Statement guifg=khaki
|
||||
hi PreProc guifg=indianred
|
||||
hi Type guifg=darkkhaki
|
||||
hi Special guifg=navajowhite
|
||||
"hi Underlined
|
||||
hi Ignore guifg=grey40
|
||||
"hi Error
|
||||
hi Todo guifg=orangered guibg=yellow2
|
||||
|
||||
" color terminal definitions
|
||||
hi SpecialKey ctermfg=darkgreen
|
||||
hi NonText cterm=bold ctermfg=darkblue
|
||||
hi Directory ctermfg=darkcyan
|
||||
hi ErrorMsg cterm=bold ctermfg=7 ctermbg=1
|
||||
hi IncSearch cterm=NONE ctermfg=yellow ctermbg=green
|
||||
hi Search cterm=NONE ctermfg=grey ctermbg=blue
|
||||
hi MoreMsg ctermfg=darkgreen
|
||||
hi ModeMsg cterm=NONE ctermfg=brown
|
||||
hi LineNr ctermfg=3
|
||||
hi Question ctermfg=green
|
||||
hi StatusLine cterm=bold,reverse
|
||||
hi StatusLineNC cterm=reverse
|
||||
hi VertSplit cterm=reverse
|
||||
hi Title ctermfg=5
|
||||
hi Visual cterm=reverse
|
||||
hi VisualNOS cterm=bold,underline
|
||||
hi WarningMsg ctermfg=1
|
||||
hi WildMenu ctermfg=0 ctermbg=3
|
||||
hi Folded ctermfg=darkgrey ctermbg=NONE
|
||||
hi FoldColumn ctermfg=darkgrey ctermbg=NONE
|
||||
hi DiffAdd ctermbg=4
|
||||
hi DiffChange ctermbg=5
|
||||
hi DiffDelete cterm=bold ctermfg=4 ctermbg=6
|
||||
hi DiffText cterm=bold ctermbg=1
|
||||
hi Comment ctermfg=darkcyan
|
||||
hi Constant ctermfg=brown
|
||||
hi Special ctermfg=5
|
||||
hi Identifier ctermfg=6
|
||||
hi Statement ctermfg=3
|
||||
hi PreProc ctermfg=5
|
||||
hi Type ctermfg=2
|
||||
hi Underlined cterm=underline ctermfg=5
|
||||
hi Ignore cterm=bold ctermfg=7
|
||||
hi Ignore ctermfg=darkgrey
|
||||
hi Error cterm=bold ctermfg=7 ctermbg=1
|
||||
|
||||
|
||||
"vim: sw=4
|
53
bundle/vim-mundo/tests/vim_test/plugin/mundo_test_utils.vim
Normal file
53
bundle/vim-mundo/tests/vim_test/plugin/mundo_test_utils.vim
Normal file
@ -0,0 +1,53 @@
|
||||
let s:undolevels_save = &undolevels
|
||||
|
||||
function! g:Goto(buffername)"{{{
|
||||
let l:winnr = bufwinnr(a:buffername)
|
||||
|
||||
if l:winnr == -1
|
||||
return
|
||||
endif
|
||||
|
||||
execute l:winnr . 'wincmd w'
|
||||
endfunction"}}}
|
||||
|
||||
function! g:GotoLineContaining(text)"{{{
|
||||
let index = match(getline(1, '$'), '\V' . escape(a:text, '\'))
|
||||
|
||||
if index == -1
|
||||
return
|
||||
endif
|
||||
|
||||
call cursor(index + 1, 0)
|
||||
endfunction"}}}
|
||||
|
||||
function! g:CurrentLineContains(text)"{{{
|
||||
return stridx(getline('.'), a:text) != -1
|
||||
endfunction"}}}
|
||||
|
||||
function! g:Contains(text)"{{{
|
||||
return match(getline(1, '$'), '\V' . escape(a:text, '\')) != -1
|
||||
endfunction"}}}
|
||||
|
||||
function! g:TypeLine(text)"{{{
|
||||
execute "normal i" . a:text . "\<C-g>u\n\e"
|
||||
endfunction"}}}
|
||||
|
||||
function! g:TypeLineDone(text)"{{{
|
||||
execute "normal i" . a:text . "\n\e"
|
||||
|
||||
" Break the undo chain
|
||||
let &undolevels = s:undolevels_save
|
||||
endfunction"}}}
|
||||
|
||||
function! g:PrintTheFuckingBuffer()"{{{
|
||||
echo join(getline(1, '$'), "\n")
|
||||
echo "SOMETIMES I HATE YOU VIM"
|
||||
endfunction"}}}
|
||||
|
||||
function! g:MoveUp()"{{{
|
||||
call cursor(line('.') - 1, 0)
|
||||
endfunction"}}}
|
||||
|
||||
function! g:MoveDown()"{{{
|
||||
call cursor(line('.') + 1, 0)
|
||||
endfunction"}}}
|
10
bundle/vim-mundo/tests/vimrc_test
Normal file
10
bundle/vim-mundo/tests/vimrc_test
Normal file
@ -0,0 +1,10 @@
|
||||
set nocompatible
|
||||
let mundo_root = simplify(expand("<sfile>:h:h"))
|
||||
let mundo_test_bundle = mundo_root .'/tests/bundled'
|
||||
let &runtimepath = mundo_root
|
||||
let &runtimepath .= ','. mundo_root .'/tests/vim_test'
|
||||
let &runtimepath .= ','. mundo_test_bundle .'/lh-vim-lib'
|
||||
let &runtimepath .= ','. mundo_test_bundle .'/ut'
|
||||
filetype plugin on
|
||||
nnoremap q :qa!<cr>
|
||||
color desert
|
@ -44,6 +44,7 @@ lang: zh
|
||||
- [增加或减小数字](#增加或减小数字)
|
||||
- [复制粘贴](#复制粘贴)
|
||||
- [增删注释](#增删注释)
|
||||
- [编辑历史](#编辑历史)
|
||||
- [文本编码格式](#文本编码格式)
|
||||
- [窗口管理](#窗口管理)
|
||||
- [常用编辑器窗口](#常用编辑器窗口)
|
||||
@ -1075,6 +1076,38 @@ echo "selected text" | curl -s -F "content=<-" http://dpaste.com/api/v2/
|
||||
用 `SPC ;` 可以启动一个注释操作符模式,在该模式下,可以使用移动命令确认注释的范围,
|
||||
比如 `SPC ; 4 j`,这个组合键会注释当前行以及下方的 4 行。这个数字即为相对行号,可在左侧看到。
|
||||
|
||||
#### 编辑历史
|
||||
|
||||
当前文件的编辑历史,可以使用快捷键 `F7` 查看,默认会在左侧打开一个编辑历史可视化窗口。
|
||||
若当前编辑器支持 `+python` 或者 `+python3`,则会使用 mundo 作为默认插件,否则则使用
|
||||
undotree。
|
||||
|
||||
在编辑历史窗口内的快捷键如下:
|
||||
|
||||
| 快捷键 | 功能描述 |
|
||||
| --------------- | ------------------- |
|
||||
| `G` | move_bottom |
|
||||
| `J` | move_older_write |
|
||||
| `K` | move_newer_write |
|
||||
| `N` | previous_match |
|
||||
| `P` | play_to |
|
||||
| `<2-LeftMouse>` | mouse_click |
|
||||
| `/` | search |
|
||||
| `<CR>` | preview |
|
||||
| `d` | diff |
|
||||
| `<down>` | move_older |
|
||||
| `<up>` | move_newer |
|
||||
| `i` | toggle_inline |
|
||||
| `j` | move_older |
|
||||
| `k` | move_newer |
|
||||
| `n` | next_match |
|
||||
| `o` | preview |
|
||||
| `p` | diff_current_buffer |
|
||||
| `q` | quit |
|
||||
| `r` | diff |
|
||||
| `gg` | move_top |
|
||||
| `?` | toggle_help |
|
||||
|
||||
#### 文本编码格式
|
||||
|
||||
SpaceVim 默认使用 `utf-8` 码进行编码。下面是 `utf-8` 编码的四个设置:
|
||||
|
@ -42,6 +42,7 @@ description: "General documentation about how to using SpaceVim, including the q
|
||||
- [Increase/Decrease numbers](#increasedecrease-numbers)
|
||||
- [Copy and paste](#copy-and-paste)
|
||||
- [Commenting](#commenting)
|
||||
- [Undo tree](#undo-tree)
|
||||
- [Multi-Encodings](#multi-encodings)
|
||||
- [Window manager](#window-manager)
|
||||
- [General Editor windows](#general-editor-windows)
|
||||
@ -1129,6 +1130,38 @@ Comments are handled by [nerdcommenter](https://github.com/scrooloose/nerdcommen
|
||||
**Tips:** `SPC ;` will start operator mode, in this mode, you can use motion command to comment lines.
|
||||
For example, `SPC ; 4 j` will comment current line and the following 4 lines.
|
||||
|
||||
#### Undo tree
|
||||
|
||||
Undo tree visualizes undo history and makes it easier to browse and switch between different undo branches.
|
||||
The default key binding is `F7`. If `+python` or `+python3` is enabled, mundo will be loaded,
|
||||
otherwise undotree will be loaded.
|
||||
|
||||
Key bindings within undo tree windows:
|
||||
|
||||
| key bindings | description |
|
||||
| --------------- | ------------------- |
|
||||
| `G` | move_bottom |
|
||||
| `J` | move_older_write |
|
||||
| `K` | move_newer_write |
|
||||
| `N` | previous_match |
|
||||
| `P` | play_to |
|
||||
| `<2-LeftMouse>` | mouse_click |
|
||||
| `/` | search |
|
||||
| `<CR>` | preview |
|
||||
| `d` | diff |
|
||||
| `<down>` | move_older |
|
||||
| `<up>` | move_newer |
|
||||
| `i` | toggle_inline |
|
||||
| `j` | move_older |
|
||||
| `k` | move_newer |
|
||||
| `n` | next_match |
|
||||
| `o` | preview |
|
||||
| `p` | diff_current_buffer |
|
||||
| `q` | quit |
|
||||
| `r` | diff |
|
||||
| `gg` | move_top |
|
||||
| `?` | toggle_help |
|
||||
|
||||
#### Multi-Encodings
|
||||
|
||||
SpaceVim uses utf-8 as default encoding. There are four options for these case:
|
||||
|
@ -16,7 +16,7 @@ description: "This layer provides some tools for vim"
|
||||
## Description
|
||||
|
||||
This layer provides some extra vim tools for SpaceVim. All tools can be
|
||||
called via command. no key bindings will be definded in this layer.
|
||||
called via command.
|
||||
|
||||
## Install
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user