Clean up plugins
This commit is contained in:
parent
3a637519e7
commit
a3c1287028
213
iterm/dive-blue.itermcolors
Normal file
213
iterm/dive-blue.itermcolors
Normal file
|
@ -0,0 +1,213 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Ansi 0 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.13863241792929293</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.13863241792929293</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.13863241792929293</real>
|
||||
</dict>
|
||||
<key>Ansi 1 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.73333334922790527</real>
|
||||
</dict>
|
||||
<key>Ansi 10 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.93863123655319214</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.81519259891667195</real>
|
||||
</dict>
|
||||
<key>Ansi 11 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.95831196345308145</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.90818294859853477</real>
|
||||
<key>Red Component</key>
|
||||
<real>1</real>
|
||||
</dict>
|
||||
<key>Ansi 12 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>1</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.35028249216144114</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.33228410804237429</real>
|
||||
</dict>
|
||||
<key>Ansi 13 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.95580336202768557</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.43898106009313798</real>
|
||||
<key>Red Component</key>
|
||||
<real>1</real>
|
||||
</dict>
|
||||
<key>Ansi 14 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>1</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.69175738096237183</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.18206536769866943</real>
|
||||
</dict>
|
||||
<key>Ansi 15 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>1</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.98374009132385254</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.96765059232711792</real>
|
||||
</dict>
|
||||
<key>Ansi 2 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>1</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.0</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.48821133375167847</real>
|
||||
</dict>
|
||||
<key>Ansi 3 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.44253450624810831</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.37018267775822222</real>
|
||||
<key>Red Component</key>
|
||||
<real>1</real>
|
||||
</dict>
|
||||
<key>Ansi 4 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>1</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.6520163853240426</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.0</real>
|
||||
</dict>
|
||||
<key>Ansi 5 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.9444358223077236</real>
|
||||
<key>Green Component</key>
|
||||
<real>1</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.0</real>
|
||||
</dict>
|
||||
<key>Ansi 6 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.63589870929718018</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.73333334922790527</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.063085161149501801</real>
|
||||
</dict>
|
||||
<key>Ansi 7 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.7519041080853881</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.71496204568995447</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.79409998655319214</real>
|
||||
</dict>
|
||||
<key>Ansi 8 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.33333333333333331</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.33333333333333331</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.33333333333333331</real>
|
||||
</dict>
|
||||
<key>Ansi 9 Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.3333333432674408</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.3333333432674408</real>
|
||||
<key>Red Component</key>
|
||||
<real>1</real>
|
||||
</dict>
|
||||
<key>Background Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.87079782196969691</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.1721805548914164</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.0</real>
|
||||
</dict>
|
||||
<key>Bold Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.87799109818097032</real>
|
||||
<key>Green Component</key>
|
||||
<real>1</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.75928070281883253</real>
|
||||
</dict>
|
||||
<key>Cursor Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.73333334922790527</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.73333334922790527</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.73333334922790527</real>
|
||||
</dict>
|
||||
<key>Cursor Text Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>1</real>
|
||||
<key>Green Component</key>
|
||||
<real>1</real>
|
||||
<key>Red Component</key>
|
||||
<real>1</real>
|
||||
</dict>
|
||||
<key>Foreground Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.94509803921568625</real>
|
||||
<key>Green Component</key>
|
||||
<real>1</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.94117647058823528</real>
|
||||
</dict>
|
||||
<key>Selected Text Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>1</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.18293527746864413</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.94237203617683463</real>
|
||||
</dict>
|
||||
<key>Selection Color</key>
|
||||
<dict>
|
||||
<key>Blue Component</key>
|
||||
<real>0.28296638257575757</real>
|
||||
<key>Green Component</key>
|
||||
<real>0.062421906360556716</real>
|
||||
<key>Red Component</key>
|
||||
<real>0.12213946629502002</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1 +1 @@
|
|||
Subproject commit 0b28e334e65b6628b0a61c412fcb45204a2f2bab
|
||||
Subproject commit cfd3b2d388a8c2e9903d7a9d80a65539aabfe933
|
2
vim/bundle/ag/.gitignore
vendored
2
vim/bundle/ag/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
tags
|
||||
ag-vim.tgz
|
|
@ -1,75 +0,0 @@
|
|||
# ag.vim #
|
||||
|
||||
This plugin is a front for ag, A.K.A.
|
||||
[the_silver_searcher](https://github.com/ggreer/the_silver_searcher). Ag can
|
||||
be used as a replacement for 153% of the uses of `ack`. This plugin will allow
|
||||
you to run ag from vim, and shows the results in a split window.
|
||||
|
||||
## Installation ##
|
||||
|
||||
### The Silver Searcher
|
||||
|
||||
You have to first install [ag](https://github.com/ggreer/the_silver_searcher), itself. On Mac+Homebrew, Gentoo Linux, several others, there's package named `the_silver_searcher`, but if your OS/distro don't have one, the GitHub repo installs fine:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/ggreer/the_silver_searcher ag && cd ag && ./build.sh && sudo make install
|
||||
```
|
||||
|
||||
* Then, if you're using [pathogen](https://github.com/tpope/vim-pathogen):
|
||||
|
||||
```sh
|
||||
cd ~/.vim/bundle && git clone https://github.com/rking/ag.vim ag && vim +Helptags
|
||||
```
|
||||
|
||||
* Or, if you're using [Vundle](https://github.com/gmarik/vundle):
|
||||
|
||||
```sh
|
||||
echo "Bundle 'rking/ag.vim'" >> ~/.vimrc && vim +BundleInstall
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
You can specify a custom ag name and path in your .vimrc like so:
|
||||
|
||||
let g:agprg="<custom-ag-path-goes-here> --column"
|
||||
|
||||
## Usage ##
|
||||
|
||||
:Ag [options] {pattern} [{directory}]
|
||||
|
||||
Search recursively in {directory} (which defaults to the current directory) for the {pattern}.
|
||||
|
||||
Files containing the search term will be listed in the split window, along with
|
||||
the line number of the occurrence, once for each occurrence. [Enter] on a line
|
||||
in this window will open the file, and place the cursor on the matching line.
|
||||
|
||||
Just like where you use :grep, :grepadd, :lgrep, and :lgrepadd, you can use `:Ag`, `:AgAdd`, `:LAg`, and `:LAgAdd` respectively. (See `doc/ag.txt`, or install and `:h Ag` for more information.)
|
||||
|
||||
### Gotchas ###
|
||||
|
||||
Some characters have special meaning, and need to be escaped your search pattern. For instance, '#'. You have to escape it like this `:Ag '\\\#define foo'` to search for `#define foo`. (From [blueyed in issue #5](https://github.com/mileszs/ack.vim/issues/5).)
|
||||
|
||||
Sometimes `git grep` is even faster, though in my experience it's not noticeably so.
|
||||
|
||||
### Keyboard Shortcuts ###
|
||||
|
||||
In the quickfix window, you can use:
|
||||
|
||||
e to open file and close the quickfix window
|
||||
o to open (same as enter)
|
||||
go to preview file (open but maintain focus on ag.vim results)
|
||||
t to open in new tab
|
||||
T to open in new tab silently
|
||||
h to open in horizontal split
|
||||
H to open in horizontal split silently
|
||||
v to open in vertical split
|
||||
gv to open in vertical split silently
|
||||
q to close the quickfix window
|
||||
|
||||
### Acknowledgements
|
||||
|
||||
This Vim plugin is derived (and by derived, I mean copied, almost entirely)
|
||||
from [milesz's ack.vim](https://github.com/mileszs/ack.vim), which I also
|
||||
recommend installing since you might be in a situation where you have ack but
|
||||
not ag, and don't want to stop to install ag. Also, ack supports `--type`, and
|
||||
a few other features.
|
|
@ -1,3 +0,0 @@
|
|||
task :tgz do
|
||||
sh 'cd ..; tar czvf ag/ag-vim.tgz ag/{plugin,autoload,doc}'
|
||||
end
|
|
@ -1,147 +0,0 @@
|
|||
" NOTE: You must, of course, install ag / the_silver_searcher
|
||||
|
||||
" Location of the ag utility
|
||||
if !exists("g:agprg")
|
||||
let g:agprg="ag --column"
|
||||
endif
|
||||
|
||||
if !exists("g:ag_apply_qmappings")
|
||||
let g:ag_apply_qmappings=1
|
||||
endif
|
||||
|
||||
if !exists("g:ag_apply_lmappings")
|
||||
let g:ag_apply_lmappings=1
|
||||
endif
|
||||
|
||||
if !exists("g:ag_qhandler")
|
||||
let g:ag_qhandler="botright copen"
|
||||
endif
|
||||
|
||||
if !exists("g:ag_lhandler")
|
||||
let g:ag_lhandler="botright lopen"
|
||||
endif
|
||||
|
||||
if !exists("g:ag_mapping_message")
|
||||
let g:ag_mapping_message=1
|
||||
endif
|
||||
|
||||
function! ag#Ag(cmd, args)
|
||||
let l:ag_executable = get(split(g:agprg, " "), 0)
|
||||
|
||||
" Ensure that `ag` is installed
|
||||
if !executable(l:ag_executable)
|
||||
echoe "Ag command '" . l:ag_executable . "' was not found. Is the silver searcher installed and on your $PATH?"
|
||||
return
|
||||
endif
|
||||
|
||||
" If no pattern is provided, search for the word under the cursor
|
||||
if empty(a:args)
|
||||
let l:grepargs = expand("<cword>")
|
||||
else
|
||||
let l:grepargs = a:args . join(a:000, ' ')
|
||||
end
|
||||
|
||||
" Format, used to manage column jump
|
||||
if a:cmd =~# '-g$'
|
||||
let s:agformat_backup=g:agformat
|
||||
let g:agformat="%f"
|
||||
elseif exists("s:agformat_backup")
|
||||
let g:agformat=s:agformat_backup
|
||||
elseif !exists("g:agformat")
|
||||
let g:agformat="%f:%l:%c:%m"
|
||||
endif
|
||||
|
||||
let l:grepprg_bak=&grepprg
|
||||
let l:grepformat_bak=&grepformat
|
||||
let l:t_ti_bak=&t_ti
|
||||
let l:t_te_bak=&t_te
|
||||
try
|
||||
let &grepprg=g:agprg
|
||||
let &grepformat=g:agformat
|
||||
set t_ti=
|
||||
set t_te=
|
||||
silent execute a:cmd . " " . escape(l:grepargs, '|')
|
||||
finally
|
||||
let &grepprg=l:grepprg_bak
|
||||
let &grepformat=l:grepformat_bak
|
||||
let &t_ti=l:t_ti_bak
|
||||
let &t_te=l:t_te_bak
|
||||
endtry
|
||||
|
||||
if a:cmd =~# '^l'
|
||||
let l:match_count = len(getloclist(winnr()))
|
||||
else
|
||||
let l:match_count = len(getqflist())
|
||||
endif
|
||||
|
||||
if a:cmd =~# '^l' && l:match_count
|
||||
exe g:ag_lhandler
|
||||
let l:apply_mappings = g:ag_apply_lmappings
|
||||
let l:matches_window_prefix = 'l' " we're using the location list
|
||||
elseif l:match_count
|
||||
exe g:ag_qhandler
|
||||
let l:apply_mappings = g:ag_apply_qmappings
|
||||
let l:matches_window_prefix = 'c' " we're using the quickfix window
|
||||
endif
|
||||
|
||||
" If highlighting is on, highlight the search keyword.
|
||||
if exists("g:aghighlight")
|
||||
let @/=a:args
|
||||
set hlsearch
|
||||
end
|
||||
|
||||
redraw!
|
||||
|
||||
if l:match_count
|
||||
if l:apply_mappings
|
||||
nnoremap <silent> <buffer> h <C-W><CR><C-w>K
|
||||
nnoremap <silent> <buffer> H <C-W><CR><C-w>K<C-w>b
|
||||
nnoremap <silent> <buffer> o <CR>
|
||||
nnoremap <silent> <buffer> t <C-w><CR><C-w>T
|
||||
nnoremap <silent> <buffer> T <C-w><CR><C-w>TgT<C-W><C-W>
|
||||
nnoremap <silent> <buffer> v <C-w><CR><C-w>H<C-W>b<C-W>J<C-W>t
|
||||
|
||||
exe 'nnoremap <silent> <buffer> e <CR><C-w><C-w>:' . l:matches_window_prefix .'close<CR>'
|
||||
exe 'nnoremap <silent> <buffer> go <CR>:' . l:matches_window_prefix . 'open<CR>'
|
||||
exe 'nnoremap <silent> <buffer> q :' . l:matches_window_prefix . 'close<CR>'
|
||||
|
||||
exe 'nnoremap <silent> <buffer> gv :let b:height=winheight(0)<CR><C-w><CR><C-w>H:' . l:matches_window_prefix . 'open<CR><C-w>J:exe printf(":normal %d\<lt>c-w>_", b:height)<CR>'
|
||||
" Interpretation:
|
||||
" :let b:height=winheight(0)<CR> Get the height of the quickfix/location list window
|
||||
" <CR><C-w> Open the current item in a new split
|
||||
" <C-w>H Slam the newly opened window against the left edge
|
||||
" :copen<CR> -or- :lopen<CR> Open either the quickfix window or the location list (whichever we were using)
|
||||
" <C-w>J Slam the quickfix/location list window against the bottom edge
|
||||
" :exe printf(":normal %d\<lt>c-w>_", b:height)<CR> Restore the quickfix/location list window's height from before we opened the match
|
||||
|
||||
if g:ag_mapping_message && l:apply_mappings
|
||||
echom "ag.vim keys: q=quit <cr>/e/t/h/v=enter/edit/tab/split/vsplit go/T/H/gv=preview versions of same"
|
||||
endif
|
||||
endif
|
||||
else
|
||||
echom 'No matches for "'.a:args.'"'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! ag#AgFromSearch(cmd, args)
|
||||
let search = getreg('/')
|
||||
" translate vim regular expression to perl regular expression.
|
||||
let search = substitute(search,'\(\\<\|\\>\)','\\b','g')
|
||||
call ag#Ag(a:cmd, '"' . search .'" '. a:args)
|
||||
endfunction
|
||||
|
||||
function! ag#GetDocLocations()
|
||||
let dp = ''
|
||||
for p in split(&runtimepath,',')
|
||||
let p = p.'/doc/'
|
||||
if isdirectory(p)
|
||||
let dp = p.'*.txt '.dp
|
||||
endif
|
||||
endfor
|
||||
return dp
|
||||
endfunction
|
||||
|
||||
function! ag#AgHelp(cmd,args)
|
||||
let args = a:args.' '.ag#GetDocLocations()
|
||||
call ag#Ag(a:cmd,args)
|
||||
endfunction
|
|
@ -1,142 +0,0 @@
|
|||
*ag.txt* Plugin that integrates ag with Vim
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *ag*
|
||||
|
||||
This plugin is a front for the_silver_searcher: ag. Ag can be used as a
|
||||
replacement for ack. This plugin will allow you to run ag from vim, and
|
||||
shows the results in a split window.
|
||||
|
||||
:Ag[!] [options] {pattern} [{directory}] *:Ag*
|
||||
|
||||
Search recursively in {directory} (which defaults to the current
|
||||
directory) for the {pattern}. Behaves just like the |:grep| command, but
|
||||
will open the |Quickfix| window for you. If [!] is not given the first
|
||||
error is jumped to.
|
||||
|
||||
:AgAdd [options] {pattern} [{directory}] *:AgAdd*
|
||||
|
||||
Just like |:Ag|, but instead of making a new list, the matches are
|
||||
appended to the current |quickfix| list.
|
||||
|
||||
:AgFromSearch [{directory}] *:AgFromSearch*
|
||||
|
||||
Just like |:Ag| but the pattern is from previous search.
|
||||
|
||||
:LAg [options] {pattern} [{directory}] *:LAg*
|
||||
|
||||
Just like |:Ag| but instead of the |quickfix| list, matches are placed in
|
||||
the current |location-list|.
|
||||
|
||||
:LAgAdd [options] {pattern} [{directory}] *:LAgAdd*
|
||||
|
||||
Just like |:AgAdd| but instead of the |quickfix| list, matches are added
|
||||
to the current |location-list|
|
||||
|
||||
:AgFile [options] {pattern} [{directory}] *:AgFile*
|
||||
|
||||
Search recursively in {directory} (which defaults to the current
|
||||
directory) for filenames matching the {pattern}. Behaves just like the
|
||||
|:grep| command, but will open the |Quickfix| window for you.
|
||||
|
||||
:AgHelp[!] [options] {pattern} *:AgHelp*
|
||||
|
||||
Search vim documentation files for the {pattern}. Behaves just like the
|
||||
|:Ag| command, but searches only vim documentation .txt files
|
||||
|
||||
:LAgHelp [options] {pattern} *:LAgHelp*
|
||||
|
||||
Just like |:AgHelp| but instead of the |quickfix| list, matches are placed
|
||||
in the current |location-list|.
|
||||
|
||||
Files containing the search term will be listed in the split window, along
|
||||
with the line number of the occurrence, once for each occurrence. <Enter> on
|
||||
a line in this window will open the file, and place the cursor on the matching
|
||||
line.
|
||||
|
||||
See http://geoff.greer.fm/2011/12/27/the-silver-searcher-better-than-ack/ for
|
||||
more information.
|
||||
|
||||
==============================================================================
|
||||
OPTIONS *ag-options*
|
||||
|
||||
*g:agprg*
|
||||
The location of the Ag program, and any options you want passed to it before
|
||||
searching. Default: "ag --column". Example: >
|
||||
let g:agprg="ag --column --smart-case"
|
||||
<
|
||||
|
||||
*g:aghighlight*
|
||||
If 1, highlight the search terms after searching. Default: 0. Example: >
|
||||
let g:aghighlight=1
|
||||
<
|
||||
|
||||
*g:agformat*
|
||||
Format to recognize the matches. See 'errorformat' for more info. Default:
|
||||
"%f" when searching for files, "%f:%l:%c:%m" if not otherwise set. For
|
||||
example, if your `g:agprg` is set to just "ag" (no column numbers in the
|
||||
output, so when you jump to a match your cursor will be on the start of the
|
||||
line): >
|
||||
let g:agformat="%f:%l:%m"
|
||||
<
|
||||
|
||||
*g:ag_apply_lmappings*
|
||||
Whether or not to add custom mappings to location list windows opened by this
|
||||
plugin. Only applies if you're using the location list. Default 1. Example: >
|
||||
let g:ag_apply_lmappings=0
|
||||
<
|
||||
|
||||
*g:ag_apply_qmappings*
|
||||
Whether or not to add custom mappings to quickfix windows opened by this
|
||||
plugin. Only applies if you're using the error list. Default 1. Example: >
|
||||
let g:ag_apply_qmappings=0
|
||||
<
|
||||
|
||||
*g:ag_lhandler*
|
||||
A custom command used to open the location list after it's populated.
|
||||
Default: "botright lopen". You might want to set this to change where the
|
||||
location list is opened, or what size it is. Example: >
|
||||
let g:ag_lhandler="topleft lopen"
|
||||
<
|
||||
|
||||
*g:ag_qhandler*
|
||||
A custom command used to open the error list after it's populated. Default:
|
||||
"botright copen". You might want to set this to change where the quickfix
|
||||
window is opened, or what size it is. Example: >
|
||||
let g:ag_qhandler="copen 20"
|
||||
<
|
||||
|
||||
*g:ag_mapping_message*
|
||||
Whether or not to show the message explaining the extra mappings that are
|
||||
added to the results list this plugin populates. This message is not shown if
|
||||
the mappings are not applied (see |g:ag_apply_qmappings| and
|
||||
|g:ag_apply_lmappings| for more info. Default 1. Example: >
|
||||
let g:ag_mapping_message=0
|
||||
<
|
||||
|
||||
==============================================================================
|
||||
MAPPINGS *ag-mappings*
|
||||
|
||||
The following keyboard shortcuts are available in the quickfix window:
|
||||
|
||||
e open file and close the quickfix window.
|
||||
|
||||
o open file (same as enter).
|
||||
|
||||
go preview file (open but maintain focus on ag.vim results).
|
||||
|
||||
t open in a new tab.
|
||||
|
||||
T open in new tab silently.
|
||||
|
||||
h open in horizontal split.
|
||||
|
||||
H open in horizontal split silently.
|
||||
|
||||
v open in vertical split.
|
||||
|
||||
gv open in vertical split silently.
|
||||
|
||||
q close the quickfix window.
|
||||
|
||||
vim:tw=78:fo=tcq2:ft=help:norl:
|
|
@ -1,9 +0,0 @@
|
|||
" NOTE: You must, of course, install ag / the_silver_searcher
|
||||
command! -bang -nargs=* -complete=file Ag call ag#Ag('grep<bang>',<q-args>)
|
||||
command! -bang -nargs=* -complete=file AgAdd call ag#Ag('grepadd<bang>', <q-args>)
|
||||
command! -bang -nargs=* -complete=file AgFromSearch call ag#AgFromSearch('grep<bang>', <q-args>)
|
||||
command! -bang -nargs=* -complete=file LAg call ag#Ag('lgrep<bang>', <q-args>)
|
||||
command! -bang -nargs=* -complete=file LAgAdd call ag#Ag('lgrepadd<bang>', <q-args>)
|
||||
command! -bang -nargs=* -complete=file AgFile call ag#Ag('grep<bang> -g', <q-args>)
|
||||
command! -bang -nargs=* -complete=help AgHelp call ag#AgHelp('grep<bang>',<q-args>)
|
||||
command! -bang -nargs=* -complete=help LAgHelp call ag#AgHelp('lgrep<bang>',<q-args>)
|
|
@ -1,11 +0,0 @@
|
|||
all : gist-vim.zip
|
||||
|
||||
remove-zip:
|
||||
-rm -f doc/tags
|
||||
-rm -f gist-vim.zip
|
||||
|
||||
gist-vim.zip: remove-zip
|
||||
zip -r gist-vim.zip autoload plugin doc README.mkd
|
||||
|
||||
release: gist-vim.zip
|
||||
vimup update-script gist.vim
|
|
@ -1,224 +0,0 @@
|
|||
### Gist.vim
|
||||
|
||||
This is a vimscript for creating gists (http://gist.github.com).
|
||||
|
||||
For the latest version please see https://github.com/mattn/gist-vim.
|
||||
|
||||
## Usage:
|
||||
|
||||
- Post current buffer to gist, using default privacy option.
|
||||
|
||||
:Gist
|
||||
|
||||
- Post selected text to gist, using default privacy option.
|
||||
This applies to all permutations listed below (except multi).
|
||||
|
||||
:'<,'>Gist
|
||||
|
||||
- Create a private gist.
|
||||
|
||||
:Gist -p
|
||||
|
||||
- Create a public gist.
|
||||
(Only relevant if you've set gists to be private by default.)
|
||||
|
||||
:Gist -P
|
||||
|
||||
> This is only relevant if you've set gists to be private by default;
|
||||
> if you get an empty gist list, try ":Gist --abandon".
|
||||
|
||||
- Create a gist anonymously.
|
||||
|
||||
:Gist -a
|
||||
|
||||
- Create a gist with all open buffers.
|
||||
|
||||
:Gist -m
|
||||
|
||||
- Edit the gist (you need to have opened the gist buffer first).
|
||||
You can update the gist with the ":w" command within the gist buffer.
|
||||
|
||||
:Gist -e
|
||||
|
||||
- Edit the gist with name 'foo.js' (you need to have opened the gist buffer
|
||||
first).
|
||||
|
||||
:Gist -e foo.js
|
||||
|
||||
- Post/Edit with the description " (you need to have opened the gist buffer
|
||||
first). >
|
||||
|
||||
:Gist -s something
|
||||
:Gist -e -s something
|
||||
|
||||
- Delete the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed.
|
||||
|
||||
:Gist -d
|
||||
|
||||
- Fork the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed.
|
||||
|
||||
:Gist -f
|
||||
|
||||
- Star the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed.
|
||||
|
||||
:Gist +1
|
||||
|
||||
- Unstar the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed.
|
||||
|
||||
:Gist -1
|
||||
|
||||
- Get gist XXXXX.
|
||||
|
||||
:Gist XXXXX
|
||||
|
||||
- Get gist XXXXX and add to clipboard.
|
||||
|
||||
:Gist -c XXXXX
|
||||
|
||||
- List your public gists.
|
||||
|
||||
:Gist -l
|
||||
|
||||
- List gists from user "mattn".
|
||||
|
||||
:Gist -l mattn
|
||||
|
||||
- List everyone's gists.
|
||||
|
||||
:Gist -la
|
||||
|
||||
- List gists from your starred gists.
|
||||
|
||||
:Gist -ls
|
||||
|
||||
## Tips:
|
||||
|
||||
If you set g:gist_clip_command, gist.vim will copy the gist code with option
|
||||
'-c'.
|
||||
|
||||
- Mac:
|
||||
|
||||
let g:gist_clip_command = 'pbcopy'
|
||||
|
||||
- Linux:
|
||||
|
||||
let g:gist_clip_command = 'xclip -selection clipboard'
|
||||
|
||||
- Others (cygwin?):
|
||||
|
||||
let g:gist_clip_command = 'putclip'
|
||||
|
||||
If you want to detect filetype from the filename:
|
||||
|
||||
let g:gist_detect_filetype = 1
|
||||
|
||||
If you want to open browser after the post:
|
||||
|
||||
let g:gist_open_browser_after_post = 1
|
||||
|
||||
If you want to change the browser:
|
||||
|
||||
let g:gist_browser_command = 'w3m %URL%'
|
||||
|
||||
or:
|
||||
|
||||
let g:gist_browser_command = 'opera %URL% &'
|
||||
|
||||
On windows, this should work with your user settings.
|
||||
|
||||
If you want to show your private gists with ":Gist -l":
|
||||
|
||||
let g:gist_show_privates = 1
|
||||
|
||||
If you want your gist to be private by default:
|
||||
|
||||
let g:gist_post_private = 1
|
||||
|
||||
If you want to manipulate multiple files in a gist:
|
||||
|
||||
let g:gist_get_multiplefile = 1
|
||||
|
||||
If you want to use on Github Enterprise:
|
||||
|
||||
let g:github_api_url = 'http://your-github-enterprise-domain/api/v3'
|
||||
|
||||
You need to either set global git config:
|
||||
|
||||
$ git config --global github.user Username
|
||||
|
||||
## License:
|
||||
|
||||
Copyright 2010 by Yasuhiro Matsumoto
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
## Install:
|
||||
|
||||
Copy it to your plugin directory.
|
||||
gist.vim will create a curl cookie-jar file in your runtimepath.
|
||||
|
||||
- rtp:
|
||||
- autoload/gist.vim
|
||||
- plugin/gist.vim
|
||||
|
||||
If you want to uninstall gist.vim, remember to also remove `~/.gist-vim`.
|
||||
|
||||
You need to install webapi-vim also:
|
||||
|
||||
http://www.vim.org/scripts/script.php?script_id=4019
|
||||
|
||||
If you want to use latest one:
|
||||
|
||||
https://github.com/mattn/webapi-vim
|
||||
|
||||
### Install with [Vundle](https://github.com/gmarik/vundle)
|
||||
|
||||
Add the following lines to your `.vimrc`.
|
||||
|
||||
Bundle 'mattn/webapi-vim'
|
||||
Bundle 'mattn/gist-vim'
|
||||
|
||||
Now restart Vim and run `:BundleInstall`.
|
||||
|
||||
## Requirements:
|
||||
|
||||
- curl command (http://curl.haxx.se/)
|
||||
- webapi-vim (https://github.com/mattn/webapi-vim)
|
||||
- and if you want to use your git profile, the git command-line client.
|
||||
|
||||
## Setup:
|
||||
|
||||
This plugin uses github API v3. Setting value is stored in `~/.gist-vim`.
|
||||
gist-vim have two ways to access APIs.
|
||||
|
||||
First, you need to set your Github username in global git config:
|
||||
|
||||
$ git config --global github.user Username
|
||||
|
||||
Then, gist.vim will ask for your password to create an authorization when you
|
||||
first use it. The password is not stored and only the OAuth access token will
|
||||
be kept for later use. You can revoke the token at any time from the list of
|
||||
["Authorized applications" on Github's "Account Settings" page](https://github.com/settings/applications).
|
|
@ -1,919 +0,0 @@
|
|||
"=============================================================================
|
||||
" File: gist.vim
|
||||
" Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" Last Change: 21-Jan-2013.
|
||||
" Version: 7.1
|
||||
" WebPage: http://github.com/mattn/gist-vim
|
||||
" License: BSD
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
if !exists('g:github_user') && !executable('git')
|
||||
echohl ErrorMsg | echomsg "Gist: require 'git' command" | echohl None
|
||||
finish
|
||||
endif
|
||||
|
||||
if !executable('curl')
|
||||
echohl ErrorMsg | echomsg "Gist: require 'curl' command" | echohl None
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:configfile = expand('~/.gist-vim')
|
||||
|
||||
if !exists('g:github_user')
|
||||
let s:system = function(get(g:, 'webapi#system_function', 'system'))
|
||||
let g:github_user = substitute(s:system('git config --get github.user'), "\n", '', '')
|
||||
if strlen(g:github_user) == 0
|
||||
let g:github_user = $GITHUB_USER
|
||||
end
|
||||
endif
|
||||
|
||||
if !exists('g:github_api_url')
|
||||
let g:github_api_url = 'https://api.github.com'
|
||||
endif
|
||||
|
||||
if !exists('g:gist_update_on_write')
|
||||
let g:gist_update_on_write = 1
|
||||
endif
|
||||
|
||||
function! s:get_browser_command()
|
||||
let gist_browser_command = get(g:, 'gist_browser_command', '')
|
||||
if gist_browser_command == ''
|
||||
if has('win32') || has('win64')
|
||||
let gist_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'
|
||||
elseif has('mac') || has('macunix') || has('gui_macvim') || system('uname') =~? '^darwin'
|
||||
let gist_browser_command = 'open %URL%'
|
||||
elseif executable('xdg-open')
|
||||
let gist_browser_command = 'xdg-open %URL%'
|
||||
elseif executable('firefox')
|
||||
let gist_browser_command = 'firefox %URL% &'
|
||||
else
|
||||
let gist_browser_command = ''
|
||||
endif
|
||||
endif
|
||||
return gist_browser_command
|
||||
endfunction
|
||||
|
||||
function! s:open_browser(url)
|
||||
let cmd = s:get_browser_command()
|
||||
if len(cmd) == 0
|
||||
redraw
|
||||
echohl WarningMsg
|
||||
echo "It seems that you don't have general web browser. Open URL below."
|
||||
echohl None
|
||||
echo a:url
|
||||
return
|
||||
endif
|
||||
if cmd =~ '^!'
|
||||
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
|
||||
silent! exec cmd
|
||||
elseif cmd =~ '^:[A-Z]'
|
||||
let cmd = substitute(cmd, '%URL%', '\=a:url', 'g')
|
||||
exec cmd
|
||||
else
|
||||
let cmd = substitute(cmd, '%URL%', '\=shellescape(a:url)', 'g')
|
||||
call system(cmd)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:shellwords(str)
|
||||
let words = split(a:str, '\%(\([^ \t\''"]\+\)\|''\([^\'']*\)''\|"\(\%([^\"\\]\|\\.\)*\)"\)\zs\s*\ze')
|
||||
let words = map(words, 'substitute(v:val, ''\\\([\\ ]\)'', ''\1'', "g")')
|
||||
let words = map(words, 'matchstr(v:val, ''^\%\("\zs\(.*\)\ze"\|''''\zs\(.*\)\ze''''\|.*\)$'')')
|
||||
return words
|
||||
endfunction
|
||||
|
||||
function! s:format_gist(gist)
|
||||
let files = sort(keys(a:gist.files))
|
||||
if empty(files)
|
||||
return ""
|
||||
endif
|
||||
let file = a:gist.files[files[0]]
|
||||
if has_key(file, "content")
|
||||
let code = file.content
|
||||
let code = "\n".join(map(split(code, "\n"), '" ".v:val'), "\n")
|
||||
else
|
||||
let code = ""
|
||||
endif
|
||||
return printf("gist: %s %s%s", a:gist.id, type(a:gist.description)==0?"": a:gist.description, code)
|
||||
endfunction
|
||||
|
||||
" Note: A colon in the file name has side effects on Windows due to NTFS Alternate Data Streams; avoid it.
|
||||
let s:bufprefix = 'gist' . (has('unix') ? ':' : '_')
|
||||
function! s:GistList(gistls, page)
|
||||
if a:gistls == '-all'
|
||||
let url = g:github_api_url.'/gists/public'
|
||||
elseif get(g:, 'gist_show_privates', 0) && a:gistls == 'starred'
|
||||
let url = g:github_api_url.'/gists/starred'
|
||||
elseif get(g:, 'gist_show_privates') && a:gistls == 'mine'
|
||||
let url = g:github_api_url.'/gists'
|
||||
else
|
||||
let url = g:github_api_url.'/users/'.a:gistls.'/gists'
|
||||
endif
|
||||
let winnum = bufwinnr(bufnr(s:bufprefix.a:gistls))
|
||||
if winnum != -1
|
||||
if winnum != bufwinnr('%')
|
||||
exe winnum 'wincmd w'
|
||||
endif
|
||||
setlocal modifiable
|
||||
else
|
||||
exec 'silent noautocmd split' s:bufprefix.a:gistls
|
||||
endif
|
||||
if a:page > 1
|
||||
let oldlines = getline(0, line('$'))
|
||||
let url = url . '?page=' . a:page
|
||||
endif
|
||||
|
||||
setlocal modifiable
|
||||
let old_undolevels = &undolevels
|
||||
let oldlines = []
|
||||
silent %d _
|
||||
|
||||
redraw | echon 'Listing gists... '
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
bw!
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
return
|
||||
endif
|
||||
let res = webapi#http#get(url, '', { "Authorization": auth })
|
||||
if v:shell_error != 0
|
||||
bw!
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg 'Gists not found' | echohl None
|
||||
return
|
||||
endif
|
||||
let content = webapi#json#decode(res.content)
|
||||
if type(content) == 4 && has_key(content, 'message') && len(content.message)
|
||||
bw!
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg content.message | echohl None
|
||||
if content.message == 'Bad credentials'
|
||||
call delete(s:configfile)
|
||||
endif
|
||||
return
|
||||
endif
|
||||
|
||||
let lines = map(filter(content, '!empty(v:val.files)'), 's:format_gist(v:val)')
|
||||
call setline(1, split(join(lines, "\n"), "\n"))
|
||||
|
||||
$put='more...'
|
||||
|
||||
let b:gistls = a:gistls
|
||||
let b:page = a:page
|
||||
setlocal buftype=nofile bufhidden=hide noswapfile
|
||||
setlocal nomodified
|
||||
setlocal nomodifiable
|
||||
syntax match SpecialKey /^gist:/he=e-1
|
||||
nnoremap <silent> <buffer> <cr> :call <SID>GistListAction(0)<cr>
|
||||
nnoremap <silent> <buffer> <s-cr> :call <SID>GistListAction(1)<cr>
|
||||
|
||||
cal cursor(1+len(oldlines),1)
|
||||
nohlsearch
|
||||
redraw | echo ''
|
||||
endfunction
|
||||
|
||||
function! gist#list(user, ...)
|
||||
let page = get(a:000, 0, 0)
|
||||
if a:user == '-all'
|
||||
let url = g:github_api_url.'/gists/public'
|
||||
elseif get(g:, 'gist_show_privates', 0) && a:user == 'starred'
|
||||
let url = g:github_api_url.'/gists/starred'
|
||||
elseif get(g:, 'gist_show_privates') && a:user == 'mine'
|
||||
let url = g:github_api_url.'/gists'
|
||||
else
|
||||
let url = g:github_api_url.'/users/'.a:user.'/gists'
|
||||
endif
|
||||
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
return []
|
||||
endif
|
||||
let res = webapi#http#get(url, '', { "Authorization": auth })
|
||||
return webapi#json#decode(res.content)
|
||||
endfunction
|
||||
|
||||
function! s:GistGetFileName(gistid)
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
return ''
|
||||
endif
|
||||
let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": auth })
|
||||
let gist = webapi#json#decode(res.content)
|
||||
if has_key(gist, 'files')
|
||||
return sort(keys(gist.files))[0]
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:GistDetectFiletype(gistid)
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
return ''
|
||||
endif
|
||||
let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": auth })
|
||||
let gist = webapi#json#decode(res.content)
|
||||
let filename = sort(keys(gist.files))[0]
|
||||
let ext = fnamemodify(filename, ':e')
|
||||
if has_key(s:extmap, ext)
|
||||
let type = s:extmap[ext]
|
||||
else
|
||||
let type = get(gist.files[filename], "type", "text")
|
||||
endif
|
||||
silent! exec "setlocal ft=".tolower(type)
|
||||
endfunction
|
||||
|
||||
function! s:GistWrite(fname)
|
||||
if substitute(a:fname, '\\', '/', 'g') == expand("%:p:gs@\\@/@")
|
||||
if g:gist_update_on_write != 2 || v:cmdbang
|
||||
Gist -e
|
||||
else
|
||||
echohl ErrorMsg | echomsg 'Please type ":w!" to update a gist.' | echohl None
|
||||
endif
|
||||
else
|
||||
exe "w".(v:cmdbang ? "!" : "") fnameescape(v:cmdarg) fnameescape(a:fname)
|
||||
silent! exe "file" fnameescape(a:fname)
|
||||
silent! au! BufWriteCmd <buffer>
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:GistGet(gistid, clipboard)
|
||||
redraw | echon 'Getting gist... '
|
||||
let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": s:GistGetAuthHeader() })
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
let gist = webapi#json#decode(res.content)
|
||||
if get(g:, 'gist_get_multiplefile', 0) != 0
|
||||
let num_file = len(keys(gist.files))
|
||||
else
|
||||
let num_file = 1
|
||||
endif
|
||||
redraw
|
||||
if num_file > len(keys(gist.files))
|
||||
echohl ErrorMsg | echomsg 'Gist not found' | echohl None
|
||||
return
|
||||
endif
|
||||
for n in range(num_file)
|
||||
try
|
||||
let old_undolevels = &undolevels
|
||||
let filename = sort(keys(gist.files))[n]
|
||||
|
||||
let winnum = bufwinnr(bufnr(s:bufprefix.a:gistid."/".filename))
|
||||
if winnum != -1
|
||||
if winnum != bufwinnr('%')
|
||||
exe winnum 'wincmd w'
|
||||
endif
|
||||
setlocal modifiable
|
||||
else
|
||||
exec 'silent noautocmd new'
|
||||
setlocal noswapfile
|
||||
exec 'noautocmd file' s:bufprefix.a:gistid."/".fnameescape(filename)
|
||||
endif
|
||||
set undolevels=-1
|
||||
filetype detect
|
||||
silent %d _
|
||||
|
||||
let content = gist.files[filename].content
|
||||
call setline(1, split(content, "\n"))
|
||||
let b:gist = {
|
||||
\ "filename": filename,
|
||||
\ "id": gist.id,
|
||||
\ "description": gist.description,
|
||||
\ "private": gist.public =~ 'true',
|
||||
\}
|
||||
catch
|
||||
let &undolevels = old_undolevels
|
||||
bw!
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg 'Gist contains binary' | echohl None
|
||||
return
|
||||
endtry
|
||||
let &undolevels = old_undolevels
|
||||
setlocal buftype=acwrite bufhidden=delete noswapfile
|
||||
setlocal nomodified
|
||||
doau StdinReadPost,BufRead,BufReadPost
|
||||
let gist_detect_filetype = get(g:, 'gist_detect_filetype', 0)
|
||||
if (&ft == '' && gist_detect_filetype == 1) || gist_detect_filetype == 2
|
||||
call s:GistDetectFiletype(a:gistid)
|
||||
endif
|
||||
if a:clipboard
|
||||
if exists('g:gist_clip_command')
|
||||
exec 'silent w !'.g:gist_clip_command
|
||||
elseif has('clipboard')
|
||||
silent! %yank +
|
||||
else
|
||||
%yank
|
||||
endif
|
||||
endif
|
||||
1
|
||||
au! BufWriteCmd <buffer> call s:GistWrite(expand("<amatch>"))
|
||||
endfor
|
||||
else
|
||||
bw!
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg 'Gist not found' | echohl None
|
||||
return
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:GistListAction(shift)
|
||||
let line = getline('.')
|
||||
let mx = '^gist:\s*\zs\(\w\+\)\ze.*'
|
||||
if line =~# mx
|
||||
let gistid = matchstr(line, mx)
|
||||
if a:shift
|
||||
call s:open_browser("https://gist.github.com/" . gistid)
|
||||
else
|
||||
call s:GistGet(gistid, 0)
|
||||
endif
|
||||
return
|
||||
endif
|
||||
if line =~# '^more\.\.\.$'
|
||||
call s:GistList(b:gistls, b:page+1)
|
||||
return
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:GistUpdate(content, gistid, gistnm, desc)
|
||||
let gist = { "id": a:gistid, "files" : {}, "description": "","public": function('webapi#json#true') }
|
||||
if exists('b:gist')
|
||||
if has_key(b:gist, 'private') && b:gist.private | let gist["public"] = function('webapi#json#false') | endif
|
||||
if has_key(b:gist, 'description') | let gist["description"] = b:gist.description | endif
|
||||
if has_key(b:gist, 'filename') | let filename = b:gist.filename | endif
|
||||
else
|
||||
let filename = a:gistnm
|
||||
if len(filename) == 0 | let filename = s:GistGetFileName(a:gistid) | endif
|
||||
if len(filename) == 0 | let filename = s:get_current_filename(1) | endif
|
||||
endif
|
||||
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
return
|
||||
endif
|
||||
|
||||
" Update description
|
||||
" If no new description specified, keep the old description
|
||||
if a:desc != ' '
|
||||
let gist["description"] = a:desc
|
||||
else
|
||||
let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": auth })
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
let old_gist = webapi#json#decode(res.content)
|
||||
let gist["description"] = old_gist.description
|
||||
endif
|
||||
endif
|
||||
|
||||
let gist.files[filename] = { "content": a:content, "filename": filename }
|
||||
|
||||
redraw | echon 'Updating gist... '
|
||||
let res = webapi#http#post(g:github_api_url.'/gists/' . a:gistid,
|
||||
\ webapi#json#encode(gist), {
|
||||
\ "Authorization": auth,
|
||||
\ "Content-Type": "application/json",
|
||||
\})
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
let obj = webapi#json#decode(res.content)
|
||||
let loc = obj["html_url"]
|
||||
redraw | echomsg 'Done: '.loc
|
||||
let b:gist = {"id": a:gistid, "filename": filename}
|
||||
setlocal nomodified
|
||||
else
|
||||
let loc = ''
|
||||
let status = matchstr(status, '^\d\+\s*\zs.*')
|
||||
echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
|
||||
endif
|
||||
return loc
|
||||
endfunction
|
||||
|
||||
function! s:GistDelete(gistid)
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
return
|
||||
endif
|
||||
|
||||
redraw | echon 'Deleting gist... '
|
||||
let res = webapi#http#post(g:github_api_url.'/gists/'.a:gistid, '', {
|
||||
\ "Authorization": auth,
|
||||
\ "Content-Type": "application/json",
|
||||
\}, 'DELETE')
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
redraw | echomsg 'Done: '
|
||||
if exists('b:gist')
|
||||
unlet b:gist
|
||||
endif
|
||||
else
|
||||
let status = matchstr(status, '^\d\+\s*\zs.*')
|
||||
echohl ErrorMsg | echomsg 'Delete failed: '.status | echohl None
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:get_current_filename(no)
|
||||
let filename = expand('%:t')
|
||||
if len(filename) == 0 && &ft != ''
|
||||
let pair = filter(items(s:extmap), 'v:val[1] == &ft')
|
||||
if len(pair) > 0
|
||||
let filename = printf('gistfile%d%s', a:no, pair[0][0])
|
||||
endif
|
||||
endif
|
||||
if filename == ''
|
||||
let filename = printf('gistfile%d.txt', a:no)
|
||||
endif
|
||||
return filename
|
||||
endfunction
|
||||
|
||||
" GistPost function:
|
||||
" Post new gist to github
|
||||
"
|
||||
" if there is an embedded gist url or gist id in your file,
|
||||
" it will just update it.
|
||||
" -- by c9s
|
||||
"
|
||||
" embedded gist url format:
|
||||
"
|
||||
" Gist: https://gist.github.com/123123
|
||||
"
|
||||
" embedded gist id format:
|
||||
"
|
||||
" GistID: 123123
|
||||
"
|
||||
function! s:GistPost(content, private, desc, anonymous)
|
||||
let gist = { "files" : {}, "description": "","public": function('webapi#json#true') }
|
||||
if a:desc != ' ' | let gist["description"] = a:desc | endif
|
||||
if a:private | let gist["public"] = function('webapi#json#false') | endif
|
||||
let filename = s:get_current_filename(1)
|
||||
let gist.files[filename] = { "content": a:content, "filename": filename }
|
||||
|
||||
let header = {"Content-Type": "application/json"}
|
||||
if !a:anonymous
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
return
|
||||
endif
|
||||
let header["Authorization"] = auth
|
||||
endif
|
||||
|
||||
redraw | echon 'Posting it to gist... '
|
||||
let res = webapi#http#post(g:github_api_url.'/gists', webapi#json#encode(gist), header)
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
let obj = webapi#json#decode(res.content)
|
||||
let loc = obj["html_url"]
|
||||
redraw | echomsg 'Done: '.loc
|
||||
let b:gist = {
|
||||
\ "filename": filename,
|
||||
\ "id": matchstr(loc, '[^/]\+$'),
|
||||
\ "description": gist['description'],
|
||||
\ "private": a:private,
|
||||
\}
|
||||
else
|
||||
let loc = ''
|
||||
let status = matchstr(status, '^\d\+\s*\zs.*')
|
||||
echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
|
||||
endif
|
||||
return loc
|
||||
endfunction
|
||||
|
||||
function! s:GistPostBuffers(private, desc, anonymous)
|
||||
let bufnrs = range(1, bufnr("$"))
|
||||
let bn = bufnr('%')
|
||||
let query = []
|
||||
|
||||
let gist = { "files" : {}, "description": "","public": function('webapi#json#true') }
|
||||
if a:desc != ' ' | let gist["description"] = a:desc | endif
|
||||
if a:private | let gist["public"] = function('webapi#json#false') | endif
|
||||
|
||||
let index = 1
|
||||
for bufnr in bufnrs
|
||||
if !bufexists(bufnr) || buflisted(bufnr) == 0
|
||||
continue
|
||||
endif
|
||||
echo "Creating gist content".index."... "
|
||||
silent! exec "buffer!" bufnr
|
||||
let content = join(getline(1, line('$')), "\n")
|
||||
let filename = s:get_current_filename(index)
|
||||
let gist.files[filename] = { "content": content, "filename": filename }
|
||||
let index = index + 1
|
||||
endfor
|
||||
silent! exec "buffer!" bn
|
||||
|
||||
let header = {"Content-Type": "application/json"}
|
||||
if !a:anonymous
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
redraw
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
return
|
||||
endif
|
||||
let header["Authorization"] = auth
|
||||
endif
|
||||
|
||||
redraw | echon 'Posting it to gist... '
|
||||
let res = webapi#http#post(g:github_api_url.'/gists', webapi#json#encode(gist), header)
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
let obj = webapi#json#decode(res.content)
|
||||
let loc = obj["html_url"]
|
||||
redraw | echomsg 'Done: '.loc
|
||||
let b:gist = {"id": matchstr(loc, '[^/]\+$'), "filename": filename, "private": a:private}
|
||||
else
|
||||
let loc = ''
|
||||
let status = matchstr(status, '^\d\+\s*\zs.*')
|
||||
echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
|
||||
endif
|
||||
return loc
|
||||
endfunction
|
||||
|
||||
function! gist#Gist(count, line1, line2, ...)
|
||||
redraw
|
||||
if strlen(g:github_user) == 0
|
||||
echohl ErrorMsg | echomsg "You don't have github account. read ':help gist-vim-setup'." | echohl None
|
||||
return
|
||||
endif
|
||||
let bufname = bufname("%")
|
||||
" find GistID: in content , then we should just update
|
||||
let gistid = ''
|
||||
let gistls = ''
|
||||
let gistnm = ''
|
||||
let gistdesc = ' '
|
||||
let private = get(g:, 'gist_post_private', 0)
|
||||
let multibuffer = 0
|
||||
let clipboard = 0
|
||||
let deletepost = 0
|
||||
let editpost = 0
|
||||
let anonymous = 0
|
||||
let listmx = '^\%(-l\|--list\)\s*\([^\s]\+\)\?$'
|
||||
let bufnamemx = '^' . s:bufprefix .'\(\zs[0-9a-f]\+\ze\|\zs[0-9a-f]\+\ze[/\\].*\)$'
|
||||
if bufname =~ bufnamemx
|
||||
let gistidbuf = matchstr(bufname, bufnamemx)
|
||||
else
|
||||
let gistidbuf = matchstr(join(getline(a:line1, a:line2), "\n"), 'GistID:\s*\zs\w\+')
|
||||
endif
|
||||
|
||||
let args = (a:0 > 0) ? s:shellwords(a:1) : []
|
||||
for arg in args
|
||||
if arg =~ '^\(-h\|--help\)$\C'
|
||||
help :Gist
|
||||
return
|
||||
elseif arg =~ '^\(-la\|--listall\)$\C'
|
||||
let gistls = '-all'
|
||||
elseif arg =~ '^\(-ls\|--liststar\)$\C'
|
||||
let gistls = 'starred'
|
||||
elseif arg =~ '^\(-l\|--list\)$\C'
|
||||
if get(g:, 'gist_show_privates')
|
||||
let gistls = 'mine'
|
||||
else
|
||||
let gistls = g:github_user
|
||||
endif
|
||||
elseif arg =~ '^\(-m\|--multibuffer\)$\C'
|
||||
let multibuffer = 1
|
||||
elseif arg =~ '^\(-p\|--private\)$\C'
|
||||
let private = 1
|
||||
elseif arg =~ '^\(-P\|--public\)$\C'
|
||||
let private = 0
|
||||
elseif arg =~ '^\(-a\|--anonymous\)$\C'
|
||||
let anonymous = 1
|
||||
elseif arg =~ '^\(-s\|--description\)$\C'
|
||||
let gistdesc = ''
|
||||
elseif arg =~ '^\(-c\|--clipboard\)$\C'
|
||||
let clipboard = 1
|
||||
elseif arg =~ '^--rawurl$\C' && gistidbuf != '' && g:github_api_url == 'https://api.github.com'
|
||||
let gistid = gistidbuf
|
||||
echo 'https://gist.github.com/raw/'.gistid
|
||||
return
|
||||
elseif arg =~ '^\(-d\|--delete\)$\C' && gistidbuf != ''
|
||||
let gistid = gistidbuf
|
||||
let deletepost = 1
|
||||
elseif arg =~ '^\(-e\|--edit\)$\C' && gistidbuf != ''
|
||||
let gistid = gistidbuf
|
||||
let editpost = 1
|
||||
elseif arg =~ '^\(+1\|--star\)$\C' && gistidbuf != ''
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
else
|
||||
let gistid = gistidbuf
|
||||
let res = webapi#http#post(g:github_api_url.'/gists/'.gistid.'/star', '', { "Authorization": auth }, 'PUT')
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
echomsg "Stared" gistid
|
||||
else
|
||||
echohl ErrorMsg | echomsg 'Star failed' | echohl None
|
||||
endif
|
||||
endif
|
||||
return
|
||||
elseif arg =~ '^\(-1\|--unstar\)$\C' && gistidbuf != ''
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
else
|
||||
let gistid = gistidbuf
|
||||
let res = webapi#http#post(g:github_api_url.'/gists/'.gistid.'/star', '', { "Authorization": auth }, 'DELETE')
|
||||
if status =~ '^2'
|
||||
echomsg "Unstared" gistid
|
||||
else
|
||||
echohl ErrorMsg | echomsg 'Unstar failed' | echohl None
|
||||
endif
|
||||
endif
|
||||
return
|
||||
elseif arg =~ '^\(-f\|--fork\)$\C' && gistidbuf != ''
|
||||
let auth = s:GistGetAuthHeader()
|
||||
if len(auth) == 0
|
||||
echohl ErrorMsg | echomsg v:errmsg | echohl None
|
||||
return
|
||||
else
|
||||
let gistid = gistidbuf
|
||||
let res = webapi#http#post(g:github_api_url.'/gists/'.gistid.'/fork', '', { "Authorization": auth })
|
||||
let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
|
||||
if status =~ '^2'
|
||||
let obj = webapi#json#decode(res.content)
|
||||
let gistid = obj["id"]
|
||||
else
|
||||
echohl ErrorMsg | echomsg 'Fork failed' | echohl None
|
||||
return
|
||||
endif
|
||||
endif
|
||||
elseif arg !~ '^-' && len(gistnm) == 0
|
||||
if gistdesc != ' '
|
||||
let gistdesc = matchstr(arg, '^\s*\zs.*\ze\s*$')
|
||||
elseif editpost == 1 || deletepost == 1
|
||||
let gistnm = arg
|
||||
elseif len(gistls) > 0 && arg != '^\w\+$\C'
|
||||
let gistls = arg
|
||||
elseif arg =~ '^[0-9a-z]\+$\C'
|
||||
let gistid = arg
|
||||
else
|
||||
echohl ErrorMsg | echomsg 'Invalid arguments: '.arg | echohl None
|
||||
unlet args
|
||||
return 0
|
||||
endif
|
||||
elseif len(arg) > 0
|
||||
echohl ErrorMsg | echomsg 'Invalid arguments: '.arg | echohl None
|
||||
unlet args
|
||||
return 0
|
||||
endif
|
||||
endfor
|
||||
unlet args
|
||||
"echo "gistid=".gistid
|
||||
"echo "gistls=".gistls
|
||||
"echo "gistnm=".gistnm
|
||||
"echo "gistdesc=".gistdesc
|
||||
"echo "private=".private
|
||||
"echo "clipboard=".clipboard
|
||||
"echo "editpost=".editpost
|
||||
"echo "deletepost=".deletepost
|
||||
|
||||
if gistidbuf != '' && gistid == '' && editpost == 0 && deletepost == 0
|
||||
let editpost = 1
|
||||
let gistid = gistidbuf
|
||||
endif
|
||||
|
||||
if len(gistls) > 0
|
||||
call s:GistList(gistls, 1)
|
||||
elseif len(gistid) > 0 && editpost == 0 && deletepost == 0
|
||||
call s:GistGet(gistid, clipboard)
|
||||
else
|
||||
let url = ''
|
||||
if multibuffer == 1
|
||||
let url = s:GistPostBuffers(private, gistdesc, anonymous)
|
||||
else
|
||||
if a:count < 1
|
||||
let content = join(getline(a:line1, a:line2), "\n")
|
||||
else
|
||||
let save_regcont = @"
|
||||
let save_regtype = getregtype('"')
|
||||
silent! normal! gvy
|
||||
let content = @"
|
||||
call setreg('"', save_regcont, save_regtype)
|
||||
endif
|
||||
if editpost == 1
|
||||
let url = s:GistUpdate(content, gistid, gistnm, gistdesc)
|
||||
elseif deletepost == 1
|
||||
call s:GistDelete(gistid)
|
||||
else
|
||||
let url = s:GistPost(content, private, gistdesc, anonymous)
|
||||
endif
|
||||
if a:count >= 1 && get(g:, 'gist_keep_selection', 0) == 1
|
||||
silent! normal! gv
|
||||
endif
|
||||
endif
|
||||
if len(url) > 0
|
||||
if get(g:, 'gist_open_browser_after_post', 0) == 1
|
||||
call s:open_browser(url)
|
||||
endif
|
||||
let gist_put_url_to_clipboard_after_post = get(g:, 'gist_put_url_to_clipboard_after_post', 1)
|
||||
if gist_put_url_to_clipboard_after_post > 0
|
||||
if gist_put_url_to_clipboard_after_post == 2
|
||||
let url = url . "\n"
|
||||
endif
|
||||
if exists('g:gist_clip_command')
|
||||
call system(g:gist_clip_command, url)
|
||||
elseif has('unix') && !has('xterm_clipboard')
|
||||
let @" = url
|
||||
else
|
||||
let @+ = url
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! s:GistGetAuthHeader()
|
||||
if get(g:, 'gist_use_password_in_gitconfig', 0) != 0
|
||||
let password = substitute(system('git config --get github.password'), "\n", '', '')
|
||||
if password =~ '^!' | let password = system(password[1:]) | endif
|
||||
return printf("basic %s", webapi#base64#b64encode(g:github_user.":".password))
|
||||
endif
|
||||
let auth = ""
|
||||
if filereadable(s:configfile)
|
||||
let str = join(readfile(s:configfile), "")
|
||||
if type(str) == 1
|
||||
let auth = str
|
||||
endif
|
||||
endif
|
||||
if len(auth) > 0
|
||||
return auth
|
||||
endif
|
||||
|
||||
redraw
|
||||
echohl WarningMsg
|
||||
echo 'Gist.vim requires authorization to use the Github API. These settings are stored in "~/.gist-vim". If you want to revoke, do "rm ~/.gist-vim".'
|
||||
echohl None
|
||||
let password = inputsecret("Github Password for ".g:github_user.":")
|
||||
if len(password) > 0
|
||||
let insecureSecret = printf("basic %s", webapi#base64#b64encode(g:github_user.":".password))
|
||||
let res = webapi#http#post(g:github_api_url.'/authorizations', webapi#json#encode({
|
||||
\ "scopes" : ["gist"],
|
||||
\ "note" : "Gist.vim on ".hostname(),
|
||||
\ "note_url" : "http://www.vim.org/scripts/script.php?script_id=2423"
|
||||
\}), {
|
||||
\ "Content-Type" : "application/json",
|
||||
\ "Authorization" : insecureSecret,
|
||||
\})
|
||||
let authorization = webapi#json#decode(res.content)
|
||||
if has_key(authorization, 'token')
|
||||
let secret = printf("token %s", authorization.token)
|
||||
call writefile([secret], s:configfile)
|
||||
if !(has('win32') || has('win64'))
|
||||
call system("chmod go= ".s:configfile)
|
||||
endif
|
||||
elseif has_key(authorization, 'message')
|
||||
let secret = ''
|
||||
let v:errmsg = authorization.message
|
||||
endif
|
||||
else
|
||||
let secret = ''
|
||||
let v:errmsg = 'Canceled'
|
||||
endif
|
||||
return secret
|
||||
endfunction
|
||||
|
||||
let s:extmap = {
|
||||
\".adb": "ada",
|
||||
\".ahk": "ahk",
|
||||
\".arc": "arc",
|
||||
\".as": "actionscript",
|
||||
\".asm": "asm",
|
||||
\".asp": "asp",
|
||||
\".aw": "php",
|
||||
\".b": "b",
|
||||
\".bat": "bat",
|
||||
\".befunge": "befunge",
|
||||
\".bmx": "bmx",
|
||||
\".boo": "boo",
|
||||
\".c-objdump": "c-objdump",
|
||||
\".c": "c",
|
||||
\".cfg": "cfg",
|
||||
\".cfm": "cfm",
|
||||
\".ck": "ck",
|
||||
\".cl": "cl",
|
||||
\".clj": "clj",
|
||||
\".cmake": "cmake",
|
||||
\".coffee": "coffee",
|
||||
\".cpp": "cpp",
|
||||
\".cppobjdump": "cppobjdump",
|
||||
\".cs": "csharp",
|
||||
\".css": "css",
|
||||
\".cw": "cw",
|
||||
\".d-objdump": "d-objdump",
|
||||
\".d": "d",
|
||||
\".darcspatch": "darcspatch",
|
||||
\".diff": "diff",
|
||||
\".duby": "duby",
|
||||
\".dylan": "dylan",
|
||||
\".e": "e",
|
||||
\".ebuild": "ebuild",
|
||||
\".eclass": "eclass",
|
||||
\".el": "lisp",
|
||||
\".erb": "erb",
|
||||
\".erl": "erlang",
|
||||
\".f90": "f90",
|
||||
\".factor": "factor",
|
||||
\".feature": "feature",
|
||||
\".fs": "fs",
|
||||
\".fy": "fy",
|
||||
\".go": "go",
|
||||
\".groovy": "groovy",
|
||||
\".gs": "gs",
|
||||
\".gsp": "gsp",
|
||||
\".haml": "haml",
|
||||
\".hs": "haskell",
|
||||
\".html": "html",
|
||||
\".hx": "hx",
|
||||
\".ik": "ik",
|
||||
\".ino": "ino",
|
||||
\".io": "io",
|
||||
\".j": "j",
|
||||
\".java": "java",
|
||||
\".js": "javascript",
|
||||
\".json": "json",
|
||||
\".jsp": "jsp",
|
||||
\".kid": "kid",
|
||||
\".lhs": "lhs",
|
||||
\".lisp": "lisp",
|
||||
\".ll": "ll",
|
||||
\".lua": "lua",
|
||||
\".ly": "ly",
|
||||
\".m": "objc",
|
||||
\".mak": "mak",
|
||||
\".man": "man",
|
||||
\".mao": "mao",
|
||||
\".matlab": "matlab",
|
||||
\".md": "markdown",
|
||||
\".minid": "minid",
|
||||
\".ml": "ml",
|
||||
\".moo": "moo",
|
||||
\".mu": "mu",
|
||||
\".mustache": "mustache",
|
||||
\".mxt": "mxt",
|
||||
\".myt": "myt",
|
||||
\".n": "n",
|
||||
\".nim": "nim",
|
||||
\".nu": "nu",
|
||||
\".numpy": "numpy",
|
||||
\".objdump": "objdump",
|
||||
\".ooc": "ooc",
|
||||
\".parrot": "parrot",
|
||||
\".pas": "pas",
|
||||
\".pasm": "pasm",
|
||||
\".pd": "pd",
|
||||
\".phtml": "phtml",
|
||||
\".pir": "pir",
|
||||
\".pl": "perl",
|
||||
\".po": "po",
|
||||
\".py": "python",
|
||||
\".pytb": "pytb",
|
||||
\".pyx": "pyx",
|
||||
\".r": "r",
|
||||
\".raw": "raw",
|
||||
\".rb": "ruby",
|
||||
\".rhtml": "rhtml",
|
||||
\".rkt": "rkt",
|
||||
\".rs": "rs",
|
||||
\".rst": "rst",
|
||||
\".s": "s",
|
||||
\".sass": "sass",
|
||||
\".sc": "sc",
|
||||
\".scala": "scala",
|
||||
\".scm": "scheme",
|
||||
\".scpt": "scpt",
|
||||
\".scss": "scss",
|
||||
\".self": "self",
|
||||
\".sh": "sh",
|
||||
\".sml": "sml",
|
||||
\".sql": "sql",
|
||||
\".st": "smalltalk",
|
||||
\".tcl": "tcl",
|
||||
\".tcsh": "tcsh",
|
||||
\".tex": "tex",
|
||||
\".textile": "textile",
|
||||
\".tpl": "smarty",
|
||||
\".twig": "twig",
|
||||
\".txt" : "text",
|
||||
\".v": "verilog",
|
||||
\".vala": "vala",
|
||||
\".vb": "vbnet",
|
||||
\".vhd": "vhdl",
|
||||
\".vim": "vim",
|
||||
\".weechatlog": "weechatlog",
|
||||
\".xml": "xml",
|
||||
\".xq": "xquery",
|
||||
\".xs": "xs",
|
||||
\".yml": "yaml",
|
||||
\}
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,279 +0,0 @@
|
|||
*Gist.vim* Vimscript for creating gists (http://gist.github.com)
|
||||
|
||||
Usage |gist-vim-usage|
|
||||
Tips |gist-vim-tips|
|
||||
License |gist-vim-license|
|
||||
Install |gist-vim-install|
|
||||
Requirements |gist-vim-requirements|
|
||||
Setup |gist-vim-setup|
|
||||
|
||||
This is a vimscript for creating gists (http://gist.github.com)
|
||||
|
||||
For the latest version please see https://github.com/mattn/gist-vim.
|
||||
|
||||
==============================================================================
|
||||
USAGE *:Gist* *gist-vim-usage*
|
||||
|
||||
- Post current buffer to gist, using default privacy option. >
|
||||
|
||||
:Gist
|
||||
<
|
||||
- Post selected text to gist, using defualt privacy option.
|
||||
This applies to all permutations listed below (except multi). >
|
||||
|
||||
:'<,'>Gist
|
||||
<
|
||||
- Create a private gist. >
|
||||
|
||||
:Gist -p
|
||||
<
|
||||
- Create a public gist.
|
||||
(Only relevant if you've set gists to be private by default.) >
|
||||
|
||||
:Gist -P
|
||||
<
|
||||
- Post whole text to gist as public.
|
||||
This is only relevant if you've set gists to be private by default.
|
||||
>
|
||||
:Gist -P
|
||||
<
|
||||
- Create a gist anonymously. >
|
||||
|
||||
:Gist -a
|
||||
<
|
||||
- Create a gist with all open buffers. >
|
||||
|
||||
:Gist -m
|
||||
<
|
||||
- Edit the gist (you need to have opened the gist buffer first).
|
||||
You can update the gist with the {:w} command within the gist buffer. >
|
||||
|
||||
:Gist -e
|
||||
<
|
||||
- Edit the gist with name "foo.js" (you need to have opened the gist buffer
|
||||
first). >
|
||||
|
||||
:Gist -e foo.js
|
||||
<
|
||||
- Post/Edit with the description " (you need to have opened the gist buffer
|
||||
first). >
|
||||
|
||||
:Gist -s something
|
||||
:Gist -e -s something
|
||||
<
|
||||
- Delete the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed. >
|
||||
|
||||
:Gist -d
|
||||
<
|
||||
- Fork the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed. >
|
||||
|
||||
:Gist -f
|
||||
<
|
||||
- Star the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed.
|
||||
>
|
||||
:Gist +1
|
||||
<
|
||||
- Unstar the gist (you need to have opened the gist buffer first).
|
||||
Password authentication is needed.
|
||||
>
|
||||
:Gist -1
|
||||
<
|
||||
- Get gist XXXXX. >
|
||||
|
||||
:Gist XXXXX
|
||||
<
|
||||
- Get gist XXXXX and add to clipboard. >
|
||||
|
||||
:Gist -c XXXXX
|
||||
<
|
||||
- List your public gists. >
|
||||
|
||||
:Gist -l
|
||||
<
|
||||
- List gists from user "mattn". >
|
||||
|
||||
:Gist -l mattn
|
||||
<
|
||||
- List everyone's gists. >
|
||||
|
||||
:Gist -la
|
||||
<
|
||||
- List gists from your starred gists.
|
||||
>
|
||||
:Gist -ls
|
||||
<
|
||||
==============================================================================
|
||||
TIPS *gist-vim-tips*
|
||||
|
||||
If you set "g:gist_clip_command", gist.vim will copy the gist code with option
|
||||
"-c".
|
||||
|
||||
- Mac: >
|
||||
let g:gist_clip_command = 'pbcopy'
|
||||
<
|
||||
- Linux: >
|
||||
let g:gist_clip_command = 'xclip -selection clipboard'
|
||||
<
|
||||
- Others (cygwin?): >
|
||||
let g:gist_clip_command = 'putclip'
|
||||
<
|
||||
If you want to detect filetype from the filename: >
|
||||
|
||||
let g:gist_detect_filetype = 1
|
||||
<
|
||||
If you want to open the browser after the post: >
|
||||
|
||||
let g:gist_open_browser_after_post = 1
|
||||
<
|
||||
If you want to change the browser: >
|
||||
|
||||
let g:gist_browser_command = 'w3m %URL%'
|
||||
<
|
||||
or: >
|
||||
|
||||
let g:gist_browser_command = 'opera %URL% &'
|
||||
<
|
||||
On windows, this should work with your user settings.
|
||||
|
||||
If you want to show your private gists with ":Gist -l": >
|
||||
|
||||
let g:gist_show_privates = 1
|
||||
<
|
||||
If you want your gist to be private by default: >
|
||||
|
||||
let g:gist_post_private = 1
|
||||
|
||||
<
|
||||
If you want to edit all files for gists containing more than one: >
|
||||
|
||||
let g:gist_get_multiplefile = 1
|
||||
<
|
||||
|
||||
If you want to use on Github Enterprise: >
|
||||
|
||||
let g:github_api_url = 'http://your-github-enterprise-domain/api/v3'
|
||||
<
|
||||
|
||||
If you want to update a gist, embed >
|
||||
|
||||
GistID: xxxxx
|
||||
>
|
||||
in your local file, then call >
|
||||
|
||||
:Gist
|
||||
>
|
||||
|
||||
If you want to update a gist when only |:w!|: >
|
||||
|
||||
" :w and :w! update a gist.
|
||||
let g:gist_update_on_write = 1
|
||||
|
||||
" Only :w! updates a gist.
|
||||
let g:gist_update_on_write = 2
|
||||
>
|
||||
All other values are treated as 1.
|
||||
This variable's value is 1 by default.
|
||||
|
||||
==============================================================================
|
||||
LICENSE *gist-vim-license*
|
||||
|
||||
|
||||
Copyright 2010 by Yasuhiro Matsumoto
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==============================================================================
|
||||
INSTALL *gist-vim-install*
|
||||
|
||||
Copy following files into your plugin directory.
|
||||
|
||||
rtp:
|
||||
- autoload/gist.vim
|
||||
- plugin/gist.vim
|
||||
|
||||
If you want to uninstall gist.vim, remember to also remove `~/.gist-vim`.
|
||||
|
||||
You need to install webapi-vim also:
|
||||
|
||||
http://www.vim.org/scripts/script.php?script_id=4019
|
||||
|
||||
If you want to use latest one:
|
||||
|
||||
https://github.com/mattn/webapi-vim
|
||||
|
||||
==============================================================================
|
||||
REQUIREMENTS *gist-vim-requirements*
|
||||
|
||||
- curl command (http://curl.haxx.se/)
|
||||
- webapi-vim (https://github.com/mattn/webapi-vim)
|
||||
- and, if you want to use your git profile, the git command-line client.
|
||||
|
||||
==============================================================================
|
||||
SETUP *gist-vim-setup*
|
||||
|
||||
This plugin uses github API v3. Setting value is stored in `~/.gist.vim`.
|
||||
gist-vim have two ways to access APIs.
|
||||
|
||||
First, you need to set your Github username in global git config:
|
||||
>
|
||||
$ git config --global github.user Username
|
||||
<
|
||||
Then, gist.vim will ask for your password to create an authorization when you
|
||||
first use it. The password is not stored and only the OAuth access token will
|
||||
be kept for later use. You can revoke the token at any time from the list of
|
||||
"Authorized applications" on Github's "Account Settings" page.
|
||||
(https://github.com/settings/applications)
|
||||
|
||||
If you happen to have your password already written in ~/.gitconfig like
|
||||
below:
|
||||
>
|
||||
[github]
|
||||
password = xxxxx
|
||||
<
|
||||
Then, add following into your ~/.vimrc
|
||||
>
|
||||
let g:gist_use_password_in_gitconfig = 1
|
||||
<
|
||||
This is not secure at all, so strongly discouraged.
|
||||
|
||||
==============================================================================
|
||||
THANKS *gist-vim-thanks*
|
||||
|
||||
AD7six
|
||||
Bruno Bigras
|
||||
c9s
|
||||
Daniel Bretoi
|
||||
Jeremy Michael Cantrell
|
||||
Kien N
|
||||
kongo2002
|
||||
MATSUU Takuto
|
||||
Matthew Weier O'Phinney
|
||||
ornicar
|
||||
Roland Schilter
|
||||
steve
|
||||
tyru
|
||||
Will Gray
|
||||
netj
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
|
@ -1,9 +0,0 @@
|
|||
:Gist gist-vim.txt /*:Gist*
|
||||
Gist.vim gist-vim.txt /*Gist.vim*
|
||||
gist-vim-install gist-vim.txt /*gist-vim-install*
|
||||
gist-vim-license gist-vim.txt /*gist-vim-license*
|
||||
gist-vim-requirements gist-vim.txt /*gist-vim-requirements*
|
||||
gist-vim-setup gist-vim.txt /*gist-vim-setup*
|
||||
gist-vim-thanks gist-vim.txt /*gist-vim-thanks*
|
||||
gist-vim-tips gist-vim.txt /*gist-vim-tips*
|
||||
gist-vim-usage gist-vim.txt /*gist-vim-usage*
|
|
@ -1,297 +0,0 @@
|
|||
script_name: Gist.vim
|
||||
script_id: '2423'
|
||||
script_type: utility
|
||||
script_package: gist-vim.zip
|
||||
script_version: '7.1'
|
||||
required_vim_version: '7.0'
|
||||
summary: vimscript for gist
|
||||
|
||||
detailed_description: |
|
||||
This is vimscript for gist (http://gist.github.com)
|
||||
|
||||
Usage:
|
||||
|
||||
:Gist
|
||||
post whole text to gist.
|
||||
|
||||
:'<,'>Gist
|
||||
post selected text to gist.
|
||||
|
||||
:Gist -p
|
||||
post whole text to gist with private.
|
||||
if you got empty gist list, try :Gist --abandon
|
||||
|
||||
:Gist -a
|
||||
post whole text to gist with anonymous.
|
||||
|
||||
:Gist -m
|
||||
post multi buffer to gist.
|
||||
|
||||
:Gist -e
|
||||
edit the gist. (shoud be work on gist buffer)
|
||||
you can update the gist with :w command on gist buffer.
|
||||
|
||||
:Gist -e foo.js
|
||||
edit the gist with name 'foo.js'. (shoud be work on gist buffer)
|
||||
|
||||
:Gist -d
|
||||
delete the gist. (should be work on gist buffer)
|
||||
authentication required.
|
||||
|
||||
:Gist -f
|
||||
fork the gist. (should be work on gist buffer)
|
||||
authentication required.
|
||||
|
||||
:Gist XXXXX
|
||||
get gist XXXXX.
|
||||
|
||||
:Gist -c XXXXX.
|
||||
get gist XXXXX and put to clipboard.
|
||||
|
||||
:Gist -l
|
||||
list gists from mine.
|
||||
|
||||
:Gist -la
|
||||
list gists from all.
|
||||
|
||||
Tips:
|
||||
if set g:gist_clip_command, gist.vim will copy the gist code
|
||||
with option '-c'.
|
||||
|
||||
# mac
|
||||
let g:gist_clip_command = 'pbcopy'
|
||||
|
||||
# linux
|
||||
let g:gist_clip_command = 'xclip -selection clipboard'
|
||||
|
||||
# others(cygwin?)
|
||||
let g:gist_clip_command = 'putclip'
|
||||
|
||||
if you want to detect filetype from filename...
|
||||
|
||||
let g:gist_detect_filetype = 1
|
||||
|
||||
if you want to open browser after the post...
|
||||
|
||||
let g:gist_open_browser_after_post = 1
|
||||
|
||||
if you want to change the browser...
|
||||
|
||||
let g:gist_browser_command = 'w3m %URL%'
|
||||
|
||||
or
|
||||
|
||||
let g:gist_browser_command = 'opera %URL% &'
|
||||
|
||||
on windows, should work with original setting.
|
||||
|
||||
Require:
|
||||
curl command (http://curl.haxx.se/)
|
||||
and if you want to use profile of git, it require git command.
|
||||
|
||||
install_details: |
|
||||
copy it to your plugin directory.
|
||||
|
||||
gist.vim leave cookie-jar file into runtimepath.
|
||||
|
||||
rtp:
|
||||
plugin/gist.vim
|
||||
cookies/github
|
||||
|
||||
See also: https://github.com/mattn/gist-vim/blob/master/README.mkd
|
||||
|
||||
versions:
|
||||
- '7.1': |
|
||||
This is an upgrade for Gist.vim: updated installation notes.
|
||||
|
||||
- '7.0': |
|
||||
This is an upgrade for Gist.vim: fixed few bugs.
|
||||
|
||||
- '6.9': |
|
||||
This is an upgrade for Gist.vim: fixed few bugs.
|
||||
|
||||
- '6.8': |
|
||||
This is an upgrade for Gist.vim: changed authentication. removed password authentication. if you want to keep using password authentication, let gist_use_password_in_gitconfig to 1.
|
||||
|
||||
- '6.7': |
|
||||
This is an upgrade for Gist.vim: fix behavior of g:gist_browser_command = ':OpenBrowser %URL%'.
|
||||
|
||||
- '6.6': |
|
||||
This is an upgrade for Gist.vim: fixed detecting filetype.
|
||||
|
||||
- '6.5': |
|
||||
This is an upgrade for Gist.vim: use webapi namespace. NOTE: please upgrade webapi-vim also.
|
||||
|
||||
- '6.4': |
|
||||
This is an upgrade for Gist.vim: fixed updating with description.
|
||||
|
||||
- '6.3': |
|
||||
This is an upgrade for Gist.vim: fixed typos.
|
||||
|
||||
- '6.2': |
|
||||
This is an upgrade for Gist.vim: fixed some bugs.
|
||||
|
||||
- '6.1': |
|
||||
This is an upgrade for Gist.vim: fixed opening browser.
|
||||
|
||||
- '6.0': |
|
||||
This is an upgrade for Gist.vim: changed to use github APIs. Note to remove cookies directory if you used.
|
||||
|
||||
- '5.9': |
|
||||
This is an upgrade for Gist.vim: add support anonymous post. fixed many bugs.
|
||||
|
||||
- '5.8': |
|
||||
This is an upgrade for Gist.vim: add support for description. you can post description using -s option.
|
||||
|
||||
- '5.7': |
|
||||
This is an upgrade for Gist.vim: post with filetype more cleverly.
|
||||
|
||||
- '5.6': |
|
||||
This is an upgrade for Gist.vim: fix '--abandon'.
|
||||
|
||||
- '5.5': |
|
||||
This is an upgrade for Gist.vim: fix: forgot to upload autoload/gist.vim.
|
||||
|
||||
- '5.4': |
|
||||
This is an upgrade for Gist.vim: fix: does not work correctly with blockwize selection.
|
||||
|
||||
- '5.3': |
|
||||
This is an upgrade for Gist.vim: upd: support autoload.
|
||||
|
||||
- '5.2': |
|
||||
This is an upgrade for Gist.vim: add: support block-wise selection.
|
||||
|
||||
- '5.1': |
|
||||
This is an upgrade for Gist.vim: fix: can't update privates.
|
||||
|
||||
- '5.0': |
|
||||
This is an upgrade for Gist.vim: follow update of gist.github.com
|
||||
|
||||
- '4.9': |
|
||||
fix: don't add new line after "Done: xxx".
|
||||
fix: show WHY FAILED' when failed to post.
|
||||
add: support for :OpenBrowser.
|
||||
add: new option 'gist_curl_options'.
|
||||
|
||||
- '4.8': |
|
||||
This is an upgrade for Gist.vim: fix: can't open private gist with ":Gist XXXXX".
|
||||
|
||||
- '4.7': |
|
||||
This is an upgrade for Gist.vim: fix: filetype detection.
|
||||
|
||||
- '4.6': |
|
||||
This is an upgrade for Gist.vim: fix: strange cookies folder.
|
||||
|
||||
- '4.5': |
|
||||
This is an upgrade for Gist.vim: fix: use gist_clip_command for copying URL to clipboard. this fix strange behavior on Mac OSX.
|
||||
|
||||
- '4.4': |
|
||||
This is an upgrade for Gist.vim: fix: gist is now only using https.
|
||||
|
||||
- '4.3': |
|
||||
This is an upgrade for Gist.vim: add new option '-f' for fork.
|
||||
|
||||
- '4.2': |
|
||||
This is an upgrade for Gist.vim: fixed code for login.
|
||||
|
||||
- '4.1': |
|
||||
This is an upgrade for Gist.vim: fixed code cleanup.
|
||||
|
||||
- '4.0': |
|
||||
This is an upgrade for Gist.vim: fixed deleting gist, listing privates.
|
||||
|
||||
- '3.9': |
|
||||
This is an upgrade for Gist.vim: fixed :w handler in gist buffer.
|
||||
|
||||
- '3.8': |
|
||||
This is an upgrade for Gist.vim: 'more...' on gist list.
|
||||
|
||||
- '3.7': |
|
||||
This is an upgrade for Gist.vim: fix problem that break "gist list" window at twice.
|
||||
|
||||
- '3.6': |
|
||||
This is an upgrade for Gist.vim: fix filetype detection for 'vimscript'.
|
||||
|
||||
- '3.5': |
|
||||
This is an upgrade for Gist.vim: fix filetype detection.
|
||||
|
||||
- '3.4': |
|
||||
This is an upgrade for Gist.vim: use '+' register on unix only if built with 'xterm_clipboard'. and some bug fixes.
|
||||
|
||||
- '3.3': |
|
||||
This is an upgrade for Gist.vim: fix problem that append empty line when getting gist.
|
||||
|
||||
- '3.2': |
|
||||
This is an upgrade for Gist.vim: added Gist header to recognize the gist. added script type header for Vimana.
|
||||
|
||||
- '3.1': |
|
||||
This is an upgrade for Gist.vim: fix checking redirect url.
|
||||
|
||||
- '3.0': |
|
||||
This is an upgrade for Gist.vim: fix for official changes(private button name was changed).
|
||||
|
||||
- '2.9': |
|
||||
This is an upgrade for Gist.vim: fix for official changes(private button name was changed).
|
||||
|
||||
- '2.8': |
|
||||
This is an upgrade for Gist.vim: be able to post multi buffer. currently updating or showing not supported. and ':Gist -d' delete the gist.
|
||||
|
||||
- '2.7': |
|
||||
This is an upgrade for Gist.vim: be able to write the gist to local file with ':w foo.txt'.
|
||||
|
||||
- '2.6': |
|
||||
This is an upgrade for Gist.vim: fixed problem that does not work 'Gist XXXX'.
|
||||
|
||||
- '2.5': |
|
||||
This is an upgrade for Gist.vim: use existing buffer when open the list or gist.
|
||||
|
||||
- '2.4': |
|
||||
This is an upgrade for Gist.vim: show error message when no any github settings.
|
||||
|
||||
- '2.3': |
|
||||
This is an upgrade for Gist.vim: added :w BufWriteCmd for GistUpdate.
|
||||
|
||||
- '2.2': |
|
||||
This is an upgrade for Gist.vim: fixed a bug for anonymous post. and new option '-a' for anonymous post.
|
||||
|
||||
- '2.1': |
|
||||
This is an upgrade for Gist.vim: support changing gist filename.
|
||||
|
||||
- '2.0': |
|
||||
This is an upgrade for Gist.vim: bugfix for listing gists in specified user.
|
||||
|
||||
- '1.9': |
|
||||
This is an upgrade for Gist.vim: added support editing the gist. and bits bug fix.
|
||||
|
||||
- '1.8': |
|
||||
This is an upgrade for Gist.vim: added new option g:gist_open_browser_after_post/g:gist_browser_command to open posted gist.
|
||||
|
||||
- '1.7': |
|
||||
This is an upgrade for Gist.vim: now changed argument for putting clipboard as ':Gist -c XXXXX'.
|
||||
|
||||
- '1.6': |
|
||||
This is an upgrade for Gist.vim: add gist's author in gist list.
|
||||
|
||||
- '1.5': |
|
||||
This is an upgrade for Gist.vim: oops. bugfix for auto-detection.
|
||||
|
||||
- '1.4': |
|
||||
This is an upgrade for Gist.vim: bugfix for auto-detection.
|
||||
|
||||
- '1.3': |
|
||||
This is an upgrade for Gist.vim: more auto-detection for filetype.
|
||||
|
||||
- '1.2': |
|
||||
This is an upgrade for Gist.vim: added new option for detect filetype from filename.
|
||||
|
||||
- '1.1': |
|
||||
This is an upgrade for Gist.vim: calling StdinReadPost.
|
||||
|
||||
- '1.0': |
|
||||
This is an upgrade for Gist.vim: treat literal "-" as part of username.
|
||||
|
||||
- '0.9': |
|
||||
This is an upgrade for Gist.vim: added new option 'g:gist_clip_command' that copy the gist code.
|
||||
|
||||
# __END__
|
||||
# vim: filetype=yaml
|
|
@ -1,16 +0,0 @@
|
|||
"=============================================================================
|
||||
" File: gist.vim
|
||||
" Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" WebPage: http://github.com/mattn/gist-vim
|
||||
" License: BSD
|
||||
" GetLatestVimScripts: 2423 1 :AutoInstall: gist.vim
|
||||
" script type: plugin
|
||||
|
||||
if &cp || (exists('g:loaded_gist_vim') && g:loaded_gist_vim)
|
||||
finish
|
||||
endif
|
||||
let g:loaded_gist_vim = 1
|
||||
|
||||
command! -nargs=? -range=% Gist :call gist#Gist(<count>, <line1>, <line2>, <f-args>)
|
||||
|
||||
" vim:set et:
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 0761708c890becd3e027551068e0ae272da003e0
|
3
vim/bundle/nerdtree/.gitignore
vendored
3
vim/bundle/nerdtree/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
*~
|
||||
*.swp
|
||||
tags
|
|
@ -1,108 +0,0 @@
|
|||
The NERD Tree
|
||||
=============
|
||||
|
||||
Intro
|
||||
-----
|
||||
|
||||
The NERD tree allows you to explore your filesystem and to open files and
|
||||
directories. It presents the filesystem to you in the form of a tree which you
|
||||
manipulate with the keyboard and/or mouse. It also allows you to perform
|
||||
simple filesystem operations.
|
||||
|
||||
The following features and functionality are provided by the NERD tree:
|
||||
|
||||
* Files and directories are displayed in a hierarchical tree structure
|
||||
* Different highlighting is provided for the following types of nodes:
|
||||
* files
|
||||
* directories
|
||||
* sym-links
|
||||
* windows .lnk files
|
||||
* read-only files
|
||||
* executable files
|
||||
* Many (customisable) mappings are provided to manipulate the tree:
|
||||
* Mappings to open/close/explore directory nodes
|
||||
* Mappings to open files in new/existing windows/tabs
|
||||
* Mappings to change the current root of the tree
|
||||
* Mappings to navigate around the tree
|
||||
* ...
|
||||
* Directories and files can be bookmarked.
|
||||
* Most NERD tree navigation can also be done with the mouse
|
||||
* Filtering of tree content (can be toggled at runtime)
|
||||
* custom file filters to prevent e.g. vim backup files being displayed
|
||||
* optional displaying of hidden files (. files)
|
||||
* files can be "turned off" so that only directories are displayed
|
||||
* The position and size of the NERD tree window can be customised
|
||||
* The order in which the nodes in the tree are listed can be customised.
|
||||
* A model of your filesystem is created/maintained as you explore it. This
|
||||
has several advantages:
|
||||
* All filesystem information is cached and is only re-read on demand
|
||||
* If you revisit a part of the tree that you left earlier in your
|
||||
session, the directory nodes will be opened/closed as you left them
|
||||
* The script remembers the cursor position and window position in the NERD
|
||||
tree so you can toggle it off (or just close the tree window) and then
|
||||
reopen it (with NERDTreeToggle) the NERD tree window will appear exactly
|
||||
as you left it
|
||||
* You can have a separate NERD tree for each tab, share trees across tabs,
|
||||
or a mix of both.
|
||||
* By default the script overrides the default file browser (netrw), so if
|
||||
you :edit a directory a (slightly modified) NERD tree will appear in the
|
||||
current window
|
||||
* A programmable menu system is provided (simulates right clicking on a node)
|
||||
* one default menu plugin is provided to perform basic filesystem
|
||||
operations (create/delete/move/copy files/directories)
|
||||
* There's an API for adding your own keymappings
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
[pathogen.vim](https://github.com/tpope/vim-pathogen) is the recommended way to install nerdtree.
|
||||
|
||||
cd ~/.vim/bundle
|
||||
git clone https://github.com/scrooloose/nerdtree.git
|
||||
|
||||
Then reload vim, run `:helptags`, and check out `:help NERD_tree.txt`.
|
||||
|
||||
|
||||
Faq
|
||||
---
|
||||
|
||||
__Q. Can I have the nerdtree on every tab automatically?__
|
||||
|
||||
A. Nope. If this is something you want then chances are you aren't using tabs
|
||||
and buffers as they were intended to be used. Read this
|
||||
http://stackoverflow.com/questions/102384/using-vims-tabs-like-buffers
|
||||
|
||||
If you are interested in this behaviour then consider [vim-nerdtree-tabs](https://github.com/jistr/vim-nerdtree-tabs)
|
||||
|
||||
__Q. How can I open a NERDTree automatically when vim starts up?__
|
||||
|
||||
A. Stick this in your vimrc: `autocmd vimenter * NERDTree`
|
||||
|
||||
__Q. How can I open a NERDTree automatically when vim starts up if no files were specified?__
|
||||
|
||||
A. Stick this in your vimrc `autocmd vimenter * if !argc() | NERDTree | endif`
|
||||
|
||||
__Q. How can I map a specific key or shortcut to open NERDTree?__
|
||||
|
||||
A. Stick this in your vimrc to open NERDTree with `Ctrl+n` (you can set whatever key you want): `map <C-n> :NERDTreeToggle<CR>`
|
||||
|
||||
__Q. How can I close vim if the only window left open is a NERDTree?__
|
||||
|
||||
A. Stick this in your vimrc:
|
||||
|
||||
`autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif`
|
||||
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
4.2.0 (2011-12-28)
|
||||
|
||||
* Add NERDTreeDirArrows option to make the UI use pretty arrow chars instead of the old +~| chars to define the tree structure (sickill)
|
||||
* shift the syntax highlighting out into its own syntax file (gnap) * add some mac specific options to the filesystem menu - for macvim only (andersonfreitas)
|
||||
* Add NERDTreeMinimalUI option to remove some non functional parts of the nerdtree ui (camthompson)
|
||||
* tweak the behaviour of :NERDTreeFind - see :help :NERDTreeFind for the new behaviour (benjamingeiger)
|
||||
* if no name is given to :Bookmark, make it default to the name of the target file/dir (minyoung)
|
||||
* use 'file' completion when doing copying, create, and move operations (EvanDotPro)
|
||||
* lots of misc bug fixes (paddyoloughlin, sdewald, camthompson, Vitaly Bogdanov, AndrewRadev, mathias, scottstvnsn, kml, wycats, me RAWR!)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,315 +0,0 @@
|
|||
"CLASS: Bookmark
|
||||
"============================================================
|
||||
let s:Bookmark = {}
|
||||
let g:NERDTreeBookmark = s:Bookmark
|
||||
|
||||
" FUNCTION: Bookmark.activate() {{{1
|
||||
function! s:Bookmark.activate(...)
|
||||
call self.open(a:0 ? a:1 : {})
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.AddBookmark(name, path) {{{1
|
||||
" Class method to add a new bookmark to the list, if a previous bookmark exists
|
||||
" with the same name, just update the path for that bookmark
|
||||
function! s:Bookmark.AddBookmark(name, path)
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
if i.name ==# a:name
|
||||
let i.path = a:path
|
||||
return
|
||||
endif
|
||||
endfor
|
||||
call add(s:Bookmark.Bookmarks(), s:Bookmark.New(a:name, a:path))
|
||||
call s:Bookmark.Sort()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.Bookmarks() {{{1
|
||||
" Class method to get all bookmarks. Lazily initializes the bookmarks global
|
||||
" variable
|
||||
function! s:Bookmark.Bookmarks()
|
||||
if !exists("g:NERDTreeBookmarks")
|
||||
let g:NERDTreeBookmarks = []
|
||||
endif
|
||||
return g:NERDTreeBookmarks
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.BookmarkExistsFor(name) {{{1
|
||||
" class method that returns 1 if a bookmark with the given name is found, 0
|
||||
" otherwise
|
||||
function! s:Bookmark.BookmarkExistsFor(name)
|
||||
try
|
||||
call s:Bookmark.BookmarkFor(a:name)
|
||||
return 1
|
||||
catch /^NERDTree.BookmarkNotFoundError/
|
||||
return 0
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.BookmarkFor(name) {{{1
|
||||
" Class method to get the bookmark that has the given name. {} is return if no
|
||||
" bookmark is found
|
||||
function! s:Bookmark.BookmarkFor(name)
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
if i.name ==# a:name
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
throw "NERDTree.BookmarkNotFoundError: no bookmark found for name: \"". a:name .'"'
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.BookmarkNames() {{{1
|
||||
" Class method to return an array of all bookmark names
|
||||
function! s:Bookmark.BookmarkNames()
|
||||
let names = []
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
call add(names, i.name)
|
||||
endfor
|
||||
return names
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.CacheBookmarks(silent) {{{1
|
||||
" Class method to read all bookmarks from the bookmarks file initialize
|
||||
" bookmark objects for each one.
|
||||
"
|
||||
" Args:
|
||||
" silent - dont echo an error msg if invalid bookmarks are found
|
||||
function! s:Bookmark.CacheBookmarks(silent)
|
||||
if filereadable(g:NERDTreeBookmarksFile)
|
||||
let g:NERDTreeBookmarks = []
|
||||
let g:NERDTreeInvalidBookmarks = []
|
||||
let bookmarkStrings = readfile(g:NERDTreeBookmarksFile)
|
||||
let invalidBookmarksFound = 0
|
||||
for i in bookmarkStrings
|
||||
|
||||
"ignore blank lines
|
||||
if i != ''
|
||||
|
||||
let name = substitute(i, '^\(.\{-}\) .*$', '\1', '')
|
||||
let path = substitute(i, '^.\{-} \(.*\)$', '\1', '')
|
||||
|
||||
try
|
||||
let bookmark = s:Bookmark.New(name, g:NERDTreePath.New(path))
|
||||
call add(g:NERDTreeBookmarks, bookmark)
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call add(g:NERDTreeInvalidBookmarks, i)
|
||||
let invalidBookmarksFound += 1
|
||||
endtry
|
||||
endif
|
||||
endfor
|
||||
if invalidBookmarksFound
|
||||
call s:Bookmark.Write()
|
||||
if !a:silent
|
||||
call nerdtree#echo(invalidBookmarksFound . " invalid bookmarks were read. See :help NERDTreeInvalidBookmarks for info.")
|
||||
endif
|
||||
endif
|
||||
call s:Bookmark.Sort()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.compareTo(otherbookmark) {{{1
|
||||
" Compare these two bookmarks for sorting purposes
|
||||
function! s:Bookmark.compareTo(otherbookmark)
|
||||
return a:otherbookmark.name < self.name
|
||||
endfunction
|
||||
" FUNCTION: Bookmark.ClearAll() {{{1
|
||||
" Class method to delete all bookmarks.
|
||||
function! s:Bookmark.ClearAll()
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
call i.delete()
|
||||
endfor
|
||||
call s:Bookmark.Write()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.delete() {{{1
|
||||
" Delete this bookmark. If the node for this bookmark is under the current
|
||||
" root, then recache bookmarks for its Path object
|
||||
function! s:Bookmark.delete()
|
||||
let node = {}
|
||||
try
|
||||
let node = self.getNode(1)
|
||||
catch /^NERDTree.BookmarkedNodeNotFoundError/
|
||||
endtry
|
||||
call remove(s:Bookmark.Bookmarks(), index(s:Bookmark.Bookmarks(), self))
|
||||
if !empty(node)
|
||||
call node.path.cacheDisplayString()
|
||||
endif
|
||||
call s:Bookmark.Write()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.getNode(searchFromAbsoluteRoot) {{{1
|
||||
" Gets the treenode for this bookmark
|
||||
"
|
||||
" Args:
|
||||
" searchFromAbsoluteRoot: specifies whether we should search from the current
|
||||
" tree root, or the highest cached node
|
||||
function! s:Bookmark.getNode(searchFromAbsoluteRoot)
|
||||
let searchRoot = a:searchFromAbsoluteRoot ? g:NERDTreeDirNode.AbsoluteTreeRoot() : b:NERDTreeRoot
|
||||
let targetNode = searchRoot.findNode(self.path)
|
||||
if empty(targetNode)
|
||||
throw "NERDTree.BookmarkedNodeNotFoundError: no node was found for bookmark: " . self.name
|
||||
endif
|
||||
return targetNode
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.GetNodeForName(name, searchFromAbsoluteRoot) {{{1
|
||||
" Class method that finds the bookmark with the given name and returns the
|
||||
" treenode for it.
|
||||
function! s:Bookmark.GetNodeForName(name, searchFromAbsoluteRoot)
|
||||
let bookmark = s:Bookmark.BookmarkFor(a:name)
|
||||
return bookmark.getNode(a:searchFromAbsoluteRoot)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.GetSelected() {{{1
|
||||
" returns the Bookmark the cursor is over, or {}
|
||||
function! s:Bookmark.GetSelected()
|
||||
let line = getline(".")
|
||||
let name = substitute(line, '^>\(.\{-}\) .\+$', '\1', '')
|
||||
if name != line
|
||||
try
|
||||
return s:Bookmark.BookmarkFor(name)
|
||||
catch /^NERDTree.BookmarkNotFoundError/
|
||||
return {}
|
||||
endtry
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.InvalidBookmarks() {{{1
|
||||
" Class method to get all invalid bookmark strings read from the bookmarks
|
||||
" file
|
||||
function! s:Bookmark.InvalidBookmarks()
|
||||
if !exists("g:NERDTreeInvalidBookmarks")
|
||||
let g:NERDTreeInvalidBookmarks = []
|
||||
endif
|
||||
return g:NERDTreeInvalidBookmarks
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.mustExist() {{{1
|
||||
function! s:Bookmark.mustExist()
|
||||
if !self.path.exists()
|
||||
call s:Bookmark.CacheBookmarks(1)
|
||||
throw "NERDTree.BookmarkPointsToInvalidLocationError: the bookmark \"".
|
||||
\ self.name ."\" points to a non existing location: \"". self.path.str()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.New(name, path) {{{1
|
||||
" Create a new bookmark object with the given name and path object
|
||||
function! s:Bookmark.New(name, path)
|
||||
if a:name =~# ' '
|
||||
throw "NERDTree.IllegalBookmarkNameError: illegal name:" . a:name
|
||||
endif
|
||||
|
||||
let newBookmark = copy(self)
|
||||
let newBookmark.name = a:name
|
||||
let newBookmark.path = a:path
|
||||
return newBookmark
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.open([options]) {{{1
|
||||
"Args:
|
||||
"A dictionary containing the following keys (all optional):
|
||||
" 'where': Specifies whether the node should be opened in new split/tab or in
|
||||
" the previous window. Can be either 'v' (vertical split), 'h'
|
||||
" (horizontal split), 't' (new tab) or 'p' (previous window).
|
||||
" 'reuse': if a window is displaying the file then jump the cursor there
|
||||
" 'keepopen': dont close the tree window
|
||||
" 'stay': open the file, but keep the cursor in the tree win
|
||||
"
|
||||
function! s:Bookmark.open(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
|
||||
if self.path.isDirectory && !has_key(opts, 'where')
|
||||
call self.toRoot()
|
||||
else
|
||||
let opener = g:NERDTreeOpener.New(self.path, opts)
|
||||
call opener.open(self)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.openInNewTab(options) {{{1
|
||||
" Create a new bookmark object with the given name and path object
|
||||
function! s:Bookmark.openInNewTab(options)
|
||||
call nerdtree#deprecated('Bookmark.openInNewTab', 'is deprecated, use open() instead')
|
||||
call self.open(a:options)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.setPath(path) {{{1
|
||||
" makes this bookmark point to the given path
|
||||
function! s:Bookmark.setPath(path)
|
||||
let self.path = a:path
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.Sort() {{{1
|
||||
" Class method that sorts all bookmarks
|
||||
function! s:Bookmark.Sort()
|
||||
let CompareFunc = function("nerdtree#compareBookmarks")
|
||||
call sort(s:Bookmark.Bookmarks(), CompareFunc)
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.str() {{{1
|
||||
" Get the string that should be rendered in the view for this bookmark
|
||||
function! s:Bookmark.str()
|
||||
let pathStrMaxLen = winwidth(nerdtree#getTreeWinNum()) - 4 - len(self.name)
|
||||
if &nu
|
||||
let pathStrMaxLen = pathStrMaxLen - &numberwidth
|
||||
endif
|
||||
|
||||
let pathStr = self.path.str({'format': 'UI'})
|
||||
if len(pathStr) > pathStrMaxLen
|
||||
let pathStr = '<' . strpart(pathStr, len(pathStr) - pathStrMaxLen)
|
||||
endif
|
||||
return '>' . self.name . ' ' . pathStr
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.toRoot() {{{1
|
||||
" Make the node for this bookmark the new tree root
|
||||
function! s:Bookmark.toRoot()
|
||||
if self.validate()
|
||||
try
|
||||
let targetNode = self.getNode(1)
|
||||
catch /^NERDTree.BookmarkedNodeNotFoundError/
|
||||
let targetNode = g:NERDTreeFileNode.New(s:Bookmark.BookmarkFor(self.name).path)
|
||||
endtry
|
||||
call targetNode.makeRoot()
|
||||
call nerdtree#renderView()
|
||||
call targetNode.putCursorHere(0, 0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.ToRoot(name) {{{1
|
||||
" Make the node for this bookmark the new tree root
|
||||
function! s:Bookmark.ToRoot(name)
|
||||
let bookmark = s:Bookmark.BookmarkFor(a:name)
|
||||
call bookmark.toRoot()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.validate() {{{1
|
||||
function! s:Bookmark.validate()
|
||||
if self.path.exists()
|
||||
return 1
|
||||
else
|
||||
call s:Bookmark.CacheBookmarks(1)
|
||||
call nerdtree#renderView()
|
||||
call nerdtree#echo(self.name . "now points to an invalid location. See :help NERDTreeInvalidBookmarks for info.")
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Bookmark.Write() {{{1
|
||||
" Class method to write all bookmarks to the bookmarks file
|
||||
function! s:Bookmark.Write()
|
||||
let bookmarkStrings = []
|
||||
for i in s:Bookmark.Bookmarks()
|
||||
call add(bookmarkStrings, i.name . ' ' . i.path.str())
|
||||
endfor
|
||||
|
||||
"add a blank line before the invalid ones
|
||||
call add(bookmarkStrings, "")
|
||||
|
||||
for j in s:Bookmark.InvalidBookmarks()
|
||||
call add(bookmarkStrings, j)
|
||||
endfor
|
||||
call writefile(bookmarkStrings, g:NERDTreeBookmarksFile)
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,322 +0,0 @@
|
|||
"CLASS: Creator
|
||||
"Creates primary/secondary/mirror nerdtree windows. Sets up all the window and
|
||||
"buffer options and key mappings etc.
|
||||
"============================================================
|
||||
let s:Creator = {}
|
||||
let g:NERDTreeCreator = s:Creator
|
||||
|
||||
"FUNCTION: s:Creator._bindMappings() {{{1
|
||||
function! s:Creator._bindMappings()
|
||||
"make <cr> do the same as the default 'o' mapping
|
||||
exec "nnoremap <silent> <buffer> <cr> :call nerdtree#invokeKeyMap('". g:NERDTreeMapActivateNode ."')<cr>"
|
||||
|
||||
call g:NERDTreeKeyMap.BindAll()
|
||||
|
||||
command! -buffer -nargs=? Bookmark :call nerdtree#bookmarkNode('<args>')
|
||||
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 RevealBookmark :call nerdtree#revealBookmark('<args>')
|
||||
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=1 OpenBookmark :call nerdtree#openBookmark('<args>')
|
||||
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=* ClearBookmarks call nerdtree#clearBookmarks('<args>')
|
||||
command! -buffer -complete=customlist,nerdtree#completeBookmarks -nargs=+ BookmarkToRoot call g:NERDTreeBookmark.ToRoot('<args>')
|
||||
command! -buffer -nargs=0 ClearAllBookmarks call g:NERDTreeBookmark.ClearAll() <bar> call nerdtree#renderView()
|
||||
command! -buffer -nargs=0 ReadBookmarks call g:NERDTreeBookmark.CacheBookmarks(0) <bar> call nerdtree#renderView()
|
||||
command! -buffer -nargs=0 WriteBookmarks call g:NERDTreeBookmark.Write()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator._broadcastInitEvent() {{{1
|
||||
function! s:Creator._broadcastInitEvent()
|
||||
silent doautocmd User NERDTreeInit
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator.BufNamePrefix() {{{2
|
||||
function! s:Creator.BufNamePrefix()
|
||||
return 'NERD_tree_'
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.CreatePrimary(a:name) {{{1
|
||||
function! s:Creator.CreatePrimary(name)
|
||||
let creator = s:Creator.New()
|
||||
call creator.createPrimary(a:name)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.createPrimary(a:name) {{{1
|
||||
"name: the name of a bookmark or a directory
|
||||
function! s:Creator.createPrimary(name)
|
||||
let path = self._pathForString(a:name)
|
||||
|
||||
"if instructed to, then change the vim CWD to the dir the NERDTree is
|
||||
"inited in
|
||||
if g:NERDTreeChDirMode != 0
|
||||
call path.changeToDir()
|
||||
endif
|
||||
|
||||
if nerdtree#treeExistsForTab()
|
||||
if nerdtree#isTreeOpen()
|
||||
call nerdtree#closeTree()
|
||||
endif
|
||||
unlet t:NERDTreeBufName
|
||||
endif
|
||||
|
||||
let newRoot = g:NERDTreeDirNode.New(path)
|
||||
call newRoot.open()
|
||||
|
||||
call self._createTreeWin()
|
||||
let b:treeShowHelp = 0
|
||||
let b:NERDTreeIgnoreEnabled = 1
|
||||
let b:NERDTreeShowFiles = g:NERDTreeShowFiles
|
||||
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
|
||||
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
|
||||
let b:NERDTreeRoot = newRoot
|
||||
let b:NERDTreeType = "primary"
|
||||
|
||||
call nerdtree#renderView()
|
||||
call b:NERDTreeRoot.putCursorHere(0, 0)
|
||||
|
||||
call self._broadcastInitEvent()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.CreateSecondary(dir) {{{1
|
||||
function! s:Creator.CreateSecondary(dir)
|
||||
let creator = s:Creator.New()
|
||||
call creator.createSecondary(a:dir)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.createSecondary(dir) {{{1
|
||||
function! s:Creator.createSecondary(dir)
|
||||
try
|
||||
let path = g:NERDTreePath.New(a:dir)
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call nerdtree#echo("Invalid directory name:" . a:name)
|
||||
return
|
||||
endtry
|
||||
|
||||
"we want the directory buffer to disappear when we do the :edit below
|
||||
setlocal bufhidden=wipe
|
||||
|
||||
let previousBuf = expand("#")
|
||||
|
||||
"we need a unique name for each secondary tree buffer to ensure they are
|
||||
"all independent
|
||||
exec "silent edit " . self._nextBufferName()
|
||||
|
||||
let b:NERDTreePreviousBuf = bufnr(previousBuf)
|
||||
|
||||
let b:NERDTreeRoot = g:NERDTreeDirNode.New(path)
|
||||
call b:NERDTreeRoot.open()
|
||||
|
||||
call self._setCommonBufOptions()
|
||||
let b:NERDTreeType = "secondary"
|
||||
|
||||
call nerdtree#renderView()
|
||||
|
||||
call self._broadcastInitEvent()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator.CreateMirror() {{{1
|
||||
function! s:Creator.CreateMirror()
|
||||
let creator = s:Creator.New()
|
||||
call creator.createMirror()
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator.createMirror() {{{1
|
||||
function! s:Creator.createMirror()
|
||||
"get the names off all the nerd tree buffers
|
||||
let treeBufNames = []
|
||||
for i in range(1, tabpagenr("$"))
|
||||
let nextName = nerdtree#tabpagevar(i, 'NERDTreeBufName')
|
||||
if nextName != -1 && (!exists("t:NERDTreeBufName") || nextName != t:NERDTreeBufName)
|
||||
call add(treeBufNames, nextName)
|
||||
endif
|
||||
endfor
|
||||
let treeBufNames = nerdtree#unique(treeBufNames)
|
||||
|
||||
"map the option names (that the user will be prompted with) to the nerd
|
||||
"tree buffer names
|
||||
let options = {}
|
||||
let i = 0
|
||||
while i < len(treeBufNames)
|
||||
let bufName = treeBufNames[i]
|
||||
let treeRoot = getbufvar(bufName, "NERDTreeRoot")
|
||||
let options[i+1 . '. ' . treeRoot.path.str() . ' (buf name: ' . bufName . ')'] = bufName
|
||||
let i = i + 1
|
||||
endwhile
|
||||
|
||||
"work out which tree to mirror, if there is more than 1 then ask the user
|
||||
let bufferName = ''
|
||||
if len(keys(options)) > 1
|
||||
let choices = ["Choose a tree to mirror"]
|
||||
let choices = extend(choices, sort(keys(options)))
|
||||
let choice = inputlist(choices)
|
||||
if choice < 1 || choice > len(options) || choice ==# ''
|
||||
return
|
||||
endif
|
||||
|
||||
let bufferName = options[sort(keys(options))[choice-1]]
|
||||
elseif len(keys(options)) ==# 1
|
||||
let bufferName = values(options)[0]
|
||||
else
|
||||
call nerdtree#echo("No trees to mirror")
|
||||
return
|
||||
endif
|
||||
|
||||
if nerdtree#treeExistsForTab() && nerdtree#isTreeOpen()
|
||||
call nerdtree#closeTree()
|
||||
endif
|
||||
|
||||
let t:NERDTreeBufName = bufferName
|
||||
call self._createTreeWin()
|
||||
exec 'buffer ' . bufferName
|
||||
if !&hidden
|
||||
call nerdtree#renderView()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator._createTreeWin() {{{1
|
||||
"Inits the NERD tree window. ie. opens it, sizes it, sets all the local
|
||||
"options etc
|
||||
function! s:Creator._createTreeWin()
|
||||
"create the nerd tree window
|
||||
let splitLocation = g:NERDTreeWinPos ==# "left" ? "topleft " : "botright "
|
||||
let splitSize = g:NERDTreeWinSize
|
||||
|
||||
if !exists('t:NERDTreeBufName')
|
||||
let t:NERDTreeBufName = self._nextBufferName()
|
||||
silent! exec splitLocation . 'vertical ' . splitSize . ' new'
|
||||
silent! exec "edit " . t:NERDTreeBufName
|
||||
else
|
||||
silent! exec splitLocation . 'vertical ' . splitSize . ' split'
|
||||
silent! exec "buffer " . t:NERDTreeBufName
|
||||
endif
|
||||
|
||||
setlocal winfixwidth
|
||||
call self._setCommonBufOptions()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.New() {{{1
|
||||
function! s:Creator.New()
|
||||
let newCreator = copy(self)
|
||||
return newCreator
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator._nextBufferName() {{{2
|
||||
" returns the buffer name for the next nerd tree
|
||||
function! s:Creator._nextBufferName()
|
||||
let name = s:Creator.BufNamePrefix() . self._nextBufferNumber()
|
||||
return name
|
||||
endfunction
|
||||
|
||||
" FUNCTION: s:Creator._nextBufferNumber() {{{2
|
||||
" the number to add to the nerd tree buffer name to make the buf name unique
|
||||
function! s:Creator._nextBufferNumber()
|
||||
if !exists("s:Creator._NextBufNum")
|
||||
let s:Creator._NextBufNum = 1
|
||||
else
|
||||
let s:Creator._NextBufNum += 1
|
||||
endif
|
||||
|
||||
return s:Creator._NextBufNum
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator._pathForString(str) {{{1
|
||||
"find a bookmark or adirectory for the given string
|
||||
function! s:Creator._pathForString(str)
|
||||
let path = {}
|
||||
if g:NERDTreeBookmark.BookmarkExistsFor(a:str)
|
||||
let path = g:NERDTreeBookmark.BookmarkFor(a:str).path
|
||||
else
|
||||
let dir = a:str ==# '' ? getcwd() : a:str
|
||||
|
||||
"hack to get an absolute path if a relative path is given
|
||||
if dir =~# '^\.'
|
||||
let dir = getcwd() . g:NERDTreePath.Slash() . dir
|
||||
endif
|
||||
let dir = g:NERDTreePath.Resolve(dir)
|
||||
|
||||
try
|
||||
let path = g:NERDTreePath.New(dir)
|
||||
catch /^NERDTree.InvalidArgumentsError/
|
||||
call nerdtree#echo("No bookmark or directory found for: " . a:str)
|
||||
return
|
||||
endtry
|
||||
endif
|
||||
if !path.isDirectory
|
||||
let path = path.getParent()
|
||||
endif
|
||||
|
||||
return path
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator._setCommonBufOptions() {{{1
|
||||
function! s:Creator._setCommonBufOptions()
|
||||
"throwaway buffer options
|
||||
setlocal noswapfile
|
||||
setlocal buftype=nofile
|
||||
setlocal bufhidden=hide
|
||||
setlocal nowrap
|
||||
setlocal foldcolumn=0
|
||||
setlocal foldmethod=manual
|
||||
setlocal nofoldenable
|
||||
setlocal nobuflisted
|
||||
setlocal nospell
|
||||
if g:NERDTreeShowLineNumbers
|
||||
setlocal nu
|
||||
else
|
||||
setlocal nonu
|
||||
if v:version >= 703
|
||||
setlocal nornu
|
||||
endif
|
||||
endif
|
||||
|
||||
iabc <buffer>
|
||||
|
||||
if g:NERDTreeHighlightCursorline
|
||||
setlocal cursorline
|
||||
endif
|
||||
|
||||
call self._setupStatusline()
|
||||
|
||||
let b:treeShowHelp = 0
|
||||
let b:NERDTreeIgnoreEnabled = 1
|
||||
let b:NERDTreeShowFiles = g:NERDTreeShowFiles
|
||||
let b:NERDTreeShowHidden = g:NERDTreeShowHidden
|
||||
let b:NERDTreeShowBookmarks = g:NERDTreeShowBookmarks
|
||||
setfiletype nerdtree
|
||||
call self._bindMappings()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator._setupStatusline() {{{1
|
||||
function! s:Creator._setupStatusline()
|
||||
if g:NERDTreeStatusline != -1
|
||||
let &l:statusline = g:NERDTreeStatusline
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.TogglePrimary(dir) {{{1
|
||||
function! s:Creator.TogglePrimary(dir)
|
||||
let creator = s:Creator.New()
|
||||
call creator.togglePrimary(a:dir)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:Creator.togglePrimary(dir) {{{1
|
||||
"Toggles the NERD tree. I.e the NERD tree is open, it is closed, if it is
|
||||
"closed it is restored or initialized (if it doesnt exist)
|
||||
"
|
||||
"Args:
|
||||
"dir: the full path for the root node (is only used if the NERD tree is being
|
||||
"initialized.
|
||||
function! s:Creator.togglePrimary(dir)
|
||||
if nerdtree#treeExistsForTab()
|
||||
if !nerdtree#isTreeOpen()
|
||||
call self._createTreeWin()
|
||||
if !&hidden
|
||||
call nerdtree#renderView()
|
||||
endif
|
||||
call nerdtree#restoreScreenState()
|
||||
else
|
||||
call nerdtree#closeTree()
|
||||
endif
|
||||
else
|
||||
call self.createPrimary(a:dir)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,143 +0,0 @@
|
|||
"CLASS: KeyMap
|
||||
"============================================================
|
||||
let s:KeyMap = {}
|
||||
let g:NERDTreeKeyMap = s:KeyMap
|
||||
|
||||
"FUNCTION: KeyMap.All() {{{1
|
||||
function! s:KeyMap.All()
|
||||
if !exists("s:keyMaps")
|
||||
let s:keyMaps = []
|
||||
endif
|
||||
return s:keyMaps
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.FindFor(key, scope) {{{1
|
||||
function! s:KeyMap.FindFor(key, scope)
|
||||
for i in s:KeyMap.All()
|
||||
if i.key ==# a:key && i.scope ==# a:scope
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.BindAll() {{{1
|
||||
function! s:KeyMap.BindAll()
|
||||
for i in s:KeyMap.All()
|
||||
call i.bind()
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.bind() {{{1
|
||||
function! s:KeyMap.bind()
|
||||
" If the key sequence we're trying to map contains any '<>' notation, we
|
||||
" must replace each of the '<' characters with '<lt>' to ensure the string
|
||||
" is not translated into its corresponding keycode during the later part
|
||||
" of the map command below
|
||||
" :he <>
|
||||
let specialNotationRegex = '\m<\([[:alnum:]_-]\+>\)'
|
||||
if self.key =~# specialNotationRegex
|
||||
let keymapInvokeString = substitute(self.key, specialNotationRegex, '<lt>\1', 'g')
|
||||
else
|
||||
let keymapInvokeString = self.key
|
||||
endif
|
||||
|
||||
let premap = self.key == "<LeftRelease>" ? " <LeftRelease>" : " "
|
||||
|
||||
exec 'nnoremap <buffer> <silent> '. self.key . premap . ':call nerdtree#invokeKeyMap("'. keymapInvokeString .'")<cr>'
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.Remove(key, scope) {{{1
|
||||
function! s:KeyMap.Remove(key, scope)
|
||||
let maps = s:KeyMap.All()
|
||||
for i in range(len(maps))
|
||||
if maps[i].key ==# a:key && maps[i].scope ==# a:scope
|
||||
return remove(maps, i)
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.invoke() {{{1
|
||||
"Call the KeyMaps callback function
|
||||
function! s:KeyMap.invoke(...)
|
||||
let Callback = function(self.callback)
|
||||
if a:0
|
||||
call Callback(a:1)
|
||||
else
|
||||
call Callback()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.Invoke() {{{1
|
||||
"Find a keymapping for a:key and the current scope invoke it.
|
||||
"
|
||||
"Scope is determined as follows:
|
||||
" * if the cursor is on a dir node then "DirNode"
|
||||
" * if the cursor is on a file node then "FileNode"
|
||||
" * if the cursor is on a bookmark then "Bookmark"
|
||||
"
|
||||
"If a keymap has the scope of "all" then it will be called if no other keymap
|
||||
"is found for a:key and the scope.
|
||||
function! s:KeyMap.Invoke(key)
|
||||
let node = g:NERDTreeFileNode.GetSelected()
|
||||
if !empty(node)
|
||||
|
||||
"try file node
|
||||
if !node.path.isDirectory
|
||||
let km = s:KeyMap.FindFor(a:key, "FileNode")
|
||||
if !empty(km)
|
||||
return km.invoke(node)
|
||||
endif
|
||||
endif
|
||||
|
||||
"try dir node
|
||||
if node.path.isDirectory
|
||||
let km = s:KeyMap.FindFor(a:key, "DirNode")
|
||||
if !empty(km)
|
||||
return km.invoke(node)
|
||||
endif
|
||||
endif
|
||||
|
||||
"try generic node
|
||||
let km = s:KeyMap.FindFor(a:key, "Node")
|
||||
if !empty(km)
|
||||
return km.invoke(node)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
"try bookmark
|
||||
let bm = g:NERDTreeBookmark.GetSelected()
|
||||
if !empty(bm)
|
||||
let km = s:KeyMap.FindFor(a:key, "Bookmark")
|
||||
if !empty(km)
|
||||
return km.invoke(bm)
|
||||
endif
|
||||
endif
|
||||
|
||||
"try all
|
||||
let km = s:KeyMap.FindFor(a:key, "all")
|
||||
if !empty(km)
|
||||
return km.invoke()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.Create(options) {{{1
|
||||
function! s:KeyMap.Create(options)
|
||||
let newKeyMap = copy(self)
|
||||
let opts = extend({'scope': 'all', 'quickhelpText': ''}, copy(a:options))
|
||||
let newKeyMap.key = opts['key']
|
||||
let newKeyMap.quickhelpText = opts['quickhelpText']
|
||||
let newKeyMap.callback = opts['callback']
|
||||
let newKeyMap.scope = opts['scope']
|
||||
|
||||
call s:KeyMap.Add(newKeyMap)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: KeyMap.Add(keymap) {{{1
|
||||
function! s:KeyMap.Add(keymap)
|
||||
call s:KeyMap.Remove(a:keymap.key, a:keymap.scope)
|
||||
call add(s:KeyMap.All(), a:keymap)
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,180 +0,0 @@
|
|||
"CLASS: MenuController
|
||||
"============================================================
|
||||
let s:MenuController = {}
|
||||
let g:NERDTreeMenuController = s:MenuController
|
||||
|
||||
"FUNCTION: MenuController.New(menuItems) {{{1
|
||||
"create a new menu controller that operates on the given menu items
|
||||
function! s:MenuController.New(menuItems)
|
||||
let newMenuController = copy(self)
|
||||
if a:menuItems[0].isSeparator()
|
||||
let newMenuController.menuItems = a:menuItems[1:-1]
|
||||
else
|
||||
let newMenuController.menuItems = a:menuItems
|
||||
endif
|
||||
return newMenuController
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController.showMenu() {{{1
|
||||
"start the main loop of the menu and get the user to choose/execute a menu
|
||||
"item
|
||||
function! s:MenuController.showMenu()
|
||||
call self._saveOptions()
|
||||
|
||||
try
|
||||
let self.selection = 0
|
||||
|
||||
let done = 0
|
||||
while !done
|
||||
redraw!
|
||||
call self._echoPrompt()
|
||||
let key = nr2char(getchar())
|
||||
let done = self._handleKeypress(key)
|
||||
endwhile
|
||||
finally
|
||||
call self._restoreOptions()
|
||||
endtry
|
||||
|
||||
if self.selection != -1
|
||||
let m = self._current()
|
||||
call m.execute()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._echoPrompt() {{{1
|
||||
function! s:MenuController._echoPrompt()
|
||||
echo "NERDTree Menu. Use j/k/enter and the shortcuts indicated"
|
||||
echo "=========================================================="
|
||||
|
||||
for i in range(0, len(self.menuItems)-1)
|
||||
if self.selection == i
|
||||
echo "> " . self.menuItems[i].text
|
||||
else
|
||||
echo " " . self.menuItems[i].text
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._current(key) {{{1
|
||||
"get the MenuItem that is currently selected
|
||||
function! s:MenuController._current()
|
||||
return self.menuItems[self.selection]
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._handleKeypress(key) {{{1
|
||||
"change the selection (if appropriate) and return 1 if the user has made
|
||||
"their choice, 0 otherwise
|
||||
function! s:MenuController._handleKeypress(key)
|
||||
if a:key == 'j'
|
||||
call self._cursorDown()
|
||||
elseif a:key == 'k'
|
||||
call self._cursorUp()
|
||||
elseif a:key == nr2char(27) "escape
|
||||
let self.selection = -1
|
||||
return 1
|
||||
elseif a:key == "\r" || a:key == "\n" "enter and ctrl-j
|
||||
return 1
|
||||
else
|
||||
let index = self._nextIndexFor(a:key)
|
||||
if index != -1
|
||||
let self.selection = index
|
||||
if len(self._allIndexesFor(a:key)) == 1
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._allIndexesFor(shortcut) {{{1
|
||||
"get indexes to all menu items with the given shortcut
|
||||
function! s:MenuController._allIndexesFor(shortcut)
|
||||
let toReturn = []
|
||||
|
||||
for i in range(0, len(self.menuItems)-1)
|
||||
if self.menuItems[i].shortcut == a:shortcut
|
||||
call add(toReturn, i)
|
||||
endif
|
||||
endfor
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._nextIndexFor(shortcut) {{{1
|
||||
"get the index to the next menu item with the given shortcut, starts from the
|
||||
"current cursor location and wraps around to the top again if need be
|
||||
function! s:MenuController._nextIndexFor(shortcut)
|
||||
for i in range(self.selection+1, len(self.menuItems)-1)
|
||||
if self.menuItems[i].shortcut == a:shortcut
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
|
||||
for i in range(0, self.selection)
|
||||
if self.menuItems[i].shortcut == a:shortcut
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._setCmdheight() {{{1
|
||||
"sets &cmdheight to whatever is needed to display the menu
|
||||
function! s:MenuController._setCmdheight()
|
||||
let &cmdheight = len(self.menuItems) + 3
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._saveOptions() {{{1
|
||||
"set any vim options that are required to make the menu work (saving their old
|
||||
"values)
|
||||
function! s:MenuController._saveOptions()
|
||||
let self._oldLazyredraw = &lazyredraw
|
||||
let self._oldCmdheight = &cmdheight
|
||||
set nolazyredraw
|
||||
call self._setCmdheight()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._restoreOptions() {{{1
|
||||
"restore the options we saved in _saveOptions()
|
||||
function! s:MenuController._restoreOptions()
|
||||
let &cmdheight = self._oldCmdheight
|
||||
let &lazyredraw = self._oldLazyredraw
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._cursorDown() {{{1
|
||||
"move the cursor to the next menu item, skipping separators
|
||||
function! s:MenuController._cursorDown()
|
||||
let done = 0
|
||||
while !done
|
||||
if self.selection < len(self.menuItems)-1
|
||||
let self.selection += 1
|
||||
else
|
||||
let self.selection = 0
|
||||
endif
|
||||
|
||||
if !self._current().isSeparator()
|
||||
let done = 1
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuController._cursorUp() {{{1
|
||||
"move the cursor to the previous menu item, skipping separators
|
||||
function! s:MenuController._cursorUp()
|
||||
let done = 0
|
||||
while !done
|
||||
if self.selection > 0
|
||||
let self.selection -= 1
|
||||
else
|
||||
let self.selection = len(self.menuItems)-1
|
||||
endif
|
||||
|
||||
if !self._current().isSeparator()
|
||||
let done = 1
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,114 +0,0 @@
|
|||
"CLASS: MenuItem
|
||||
"============================================================
|
||||
let s:MenuItem = {}
|
||||
let g:NERDTreeMenuItem = s:MenuItem
|
||||
|
||||
"FUNCTION: MenuItem.All() {{{1
|
||||
"get all top level menu items
|
||||
function! s:MenuItem.All()
|
||||
if !exists("s:menuItems")
|
||||
let s:menuItems = []
|
||||
endif
|
||||
return s:menuItems
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.AllEnabled() {{{1
|
||||
"get all top level menu items that are currently enabled
|
||||
function! s:MenuItem.AllEnabled()
|
||||
let toReturn = []
|
||||
for i in s:MenuItem.All()
|
||||
if i.enabled()
|
||||
call add(toReturn, i)
|
||||
endif
|
||||
endfor
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.Create(options) {{{1
|
||||
"make a new menu item and add it to the global list
|
||||
function! s:MenuItem.Create(options)
|
||||
let newMenuItem = copy(self)
|
||||
|
||||
let newMenuItem.text = a:options['text']
|
||||
let newMenuItem.shortcut = a:options['shortcut']
|
||||
let newMenuItem.children = []
|
||||
|
||||
let newMenuItem.isActiveCallback = -1
|
||||
if has_key(a:options, 'isActiveCallback')
|
||||
let newMenuItem.isActiveCallback = a:options['isActiveCallback']
|
||||
endif
|
||||
|
||||
let newMenuItem.callback = -1
|
||||
if has_key(a:options, 'callback')
|
||||
let newMenuItem.callback = a:options['callback']
|
||||
endif
|
||||
|
||||
if has_key(a:options, 'parent')
|
||||
call add(a:options['parent'].children, newMenuItem)
|
||||
else
|
||||
call add(s:MenuItem.All(), newMenuItem)
|
||||
endif
|
||||
|
||||
return newMenuItem
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.CreateSeparator(options) {{{1
|
||||
"make a new separator menu item and add it to the global list
|
||||
function! s:MenuItem.CreateSeparator(options)
|
||||
let standard_options = { 'text': '--------------------',
|
||||
\ 'shortcut': -1,
|
||||
\ 'callback': -1 }
|
||||
let options = extend(a:options, standard_options, "force")
|
||||
|
||||
return s:MenuItem.Create(options)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.CreateSubmenu(options) {{{1
|
||||
"make a new submenu and add it to global list
|
||||
function! s:MenuItem.CreateSubmenu(options)
|
||||
let standard_options = { 'callback': -1 }
|
||||
let options = extend(a:options, standard_options, "force")
|
||||
|
||||
return s:MenuItem.Create(options)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.enabled() {{{1
|
||||
"return 1 if this menu item should be displayed
|
||||
"
|
||||
"delegates off to the isActiveCallback, and defaults to 1 if no callback was
|
||||
"specified
|
||||
function! s:MenuItem.enabled()
|
||||
if self.isActiveCallback != -1
|
||||
return {self.isActiveCallback}()
|
||||
endif
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.execute() {{{1
|
||||
"perform the action behind this menu item, if this menuitem has children then
|
||||
"display a new menu for them, otherwise deletegate off to the menuitem's
|
||||
"callback
|
||||
function! s:MenuItem.execute()
|
||||
if len(self.children)
|
||||
let mc = s:MenuController.New(self.children)
|
||||
call mc.showMenu()
|
||||
else
|
||||
if self.callback != -1
|
||||
call {self.callback}()
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.isSeparator() {{{1
|
||||
"return 1 if this menuitem is a separator
|
||||
function! s:MenuItem.isSeparator()
|
||||
return self.callback == -1 && self.children == []
|
||||
endfunction
|
||||
|
||||
"FUNCTION: MenuItem.isSubmenu() {{{1
|
||||
"return 1 if this menuitem is a submenu
|
||||
function! s:MenuItem.isSubmenu()
|
||||
return self.callback == -1 && !empty(self.children)
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,264 +0,0 @@
|
|||
"CLASS: Opener
|
||||
"============================================================
|
||||
let s:Opener = {}
|
||||
let g:NERDTreeOpener = s:Opener
|
||||
|
||||
"FUNCTION: Opener._checkToCloseTree(newtab) {{{1
|
||||
"Check the class options and global options (i.e. NERDTreeQuitOnOpen) to see
|
||||
"if the tree should be closed now.
|
||||
"
|
||||
"Args:
|
||||
"a:newtab - boolean. If set, only close the tree now if we are opening the
|
||||
"target in a new tab. This is needed because we have to close tree before we
|
||||
"leave the tab
|
||||
function! s:Opener._checkToCloseTree(newtab)
|
||||
if self._keepopen
|
||||
return
|
||||
endif
|
||||
|
||||
if (a:newtab && self._where == 't') || !a:newtab
|
||||
call nerdtree#closeTreeIfQuitOnOpen()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._gotoTargetWin() {{{1
|
||||
function! s:Opener._gotoTargetWin()
|
||||
if b:NERDTreeType ==# "secondary"
|
||||
if self._where == 'v'
|
||||
vsplit
|
||||
elseif self._where == 'h'
|
||||
split
|
||||
elseif self._where == 't'
|
||||
tabnew
|
||||
endif
|
||||
else
|
||||
call self._checkToCloseTree(1)
|
||||
|
||||
if self._where == 'v'
|
||||
call self._newVSplit()
|
||||
elseif self._where == 'h'
|
||||
call self._newSplit()
|
||||
elseif self._where == 't'
|
||||
tabnew
|
||||
elseif self._where == 'p'
|
||||
call self._previousWindow()
|
||||
endif
|
||||
|
||||
call self._checkToCloseTree(0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener.New(path, opts) {{{1
|
||||
"Args:
|
||||
"
|
||||
"a:path: The path object that is to be opened.
|
||||
"
|
||||
"a:opts:
|
||||
"
|
||||
"A dictionary containing the following keys (all optional):
|
||||
" 'where': Specifies whether the node should be opened in new split/tab or in
|
||||
" the previous window. Can be either 'v' or 'h' or 't' (for open in
|
||||
" new tab)
|
||||
" 'reuse': if a window is displaying the file then jump the cursor there
|
||||
" 'keepopen': dont close the tree window
|
||||
" 'stay': open the file, but keep the cursor in the tree win
|
||||
function! s:Opener.New(path, opts)
|
||||
let newObj = copy(self)
|
||||
|
||||
let newObj._path = a:path
|
||||
let newObj._stay = nerdtree#has_opt(a:opts, 'stay')
|
||||
let newObj._reuse = nerdtree#has_opt(a:opts, 'reuse')
|
||||
let newObj._keepopen = nerdtree#has_opt(a:opts, 'keepopen')
|
||||
let newObj._where = has_key(a:opts, 'where') ? a:opts['where'] : ''
|
||||
let newObj._treetype = b:NERDTreeType
|
||||
call newObj._saveCursorPos()
|
||||
|
||||
return newObj
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._newSplit() {{{1
|
||||
function! s:Opener._newSplit()
|
||||
" Save the user's settings for splitbelow and splitright
|
||||
let savesplitbelow=&splitbelow
|
||||
let savesplitright=&splitright
|
||||
|
||||
" 'there' will be set to a command to move from the split window
|
||||
" back to the explorer window
|
||||
"
|
||||
" 'back' will be set to a command to move from the explorer window
|
||||
" back to the newly split window
|
||||
"
|
||||
" 'right' and 'below' will be set to the settings needed for
|
||||
" splitbelow and splitright IF the explorer is the only window.
|
||||
"
|
||||
let there= g:NERDTreeWinPos ==# "left" ? "wincmd h" : "wincmd l"
|
||||
let back = g:NERDTreeWinPos ==# "left" ? "wincmd l" : "wincmd h"
|
||||
let right= g:NERDTreeWinPos ==# "left"
|
||||
let below=0
|
||||
|
||||
" Attempt to go to adjacent window
|
||||
call nerdtree#exec(back)
|
||||
|
||||
let onlyOneWin = (winnr("$") ==# 1)
|
||||
|
||||
" If no adjacent window, set splitright and splitbelow appropriately
|
||||
if onlyOneWin
|
||||
let &splitright=right
|
||||
let &splitbelow=below
|
||||
else
|
||||
" found adjacent window - invert split direction
|
||||
let &splitright=!right
|
||||
let &splitbelow=!below
|
||||
endif
|
||||
|
||||
let splitMode = onlyOneWin ? "vertical" : ""
|
||||
|
||||
" Open the new window
|
||||
try
|
||||
exec(splitMode." sp ")
|
||||
catch /^Vim\%((\a\+)\)\=:E37/
|
||||
call nerdtree#putCursorInTreeWin()
|
||||
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
|
||||
catch /^Vim\%((\a\+)\)\=:/
|
||||
"do nothing
|
||||
endtry
|
||||
|
||||
"resize the tree window if no other window was open before
|
||||
if onlyOneWin
|
||||
let size = exists("b:NERDTreeOldWindowSize") ? b:NERDTreeOldWindowSize : g:NERDTreeWinSize
|
||||
call nerdtree#exec(there)
|
||||
exec("silent ". splitMode ." resize ". size)
|
||||
call nerdtree#exec('wincmd p')
|
||||
endif
|
||||
|
||||
" Restore splitmode settings
|
||||
let &splitbelow=savesplitbelow
|
||||
let &splitright=savesplitright
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._newVSplit() {{{1
|
||||
function! s:Opener._newVSplit()
|
||||
let winwidth = winwidth(".")
|
||||
if winnr("$")==#1
|
||||
let winwidth = g:NERDTreeWinSize
|
||||
endif
|
||||
|
||||
call nerdtree#exec("wincmd p")
|
||||
vnew
|
||||
|
||||
"resize the nerd tree back to the original size
|
||||
call nerdtree#putCursorInTreeWin()
|
||||
exec("silent vertical resize ". winwidth)
|
||||
call nerdtree#exec('wincmd p')
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener.open(target) {{{1
|
||||
function! s:Opener.open(target)
|
||||
if self._path.isDirectory
|
||||
call self._openDirectory(a:target)
|
||||
else
|
||||
call self._openFile()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._openFile() {{{1
|
||||
function! s:Opener._openFile()
|
||||
if self._reuse && self._reuseWindow()
|
||||
return
|
||||
endif
|
||||
|
||||
call self._gotoTargetWin()
|
||||
|
||||
if self._treetype ==# "secondary"
|
||||
call self._path.edit()
|
||||
else
|
||||
call self._path.edit()
|
||||
|
||||
|
||||
if self._stay
|
||||
call self._restoreCursorPos()
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._openDirectory(node) {{{1
|
||||
function! s:Opener._openDirectory(node)
|
||||
if self._treetype ==# "secondary"
|
||||
call self._gotoTargetWin()
|
||||
call g:NERDTreeCreator.CreateSecondary(a:node.path.str())
|
||||
else
|
||||
call self._gotoTargetWin()
|
||||
if empty(self._where)
|
||||
call a:node.makeRoot()
|
||||
call nerdtree#renderView()
|
||||
call a:node.putCursorHere(0, 0)
|
||||
elseif self._where == 't'
|
||||
call g:NERDTreeCreator.CreatePrimary(a:node.path.str())
|
||||
else
|
||||
call g:NERDTreeCreator.CreateSecondary(a:node.path.str())
|
||||
endif
|
||||
endif
|
||||
|
||||
if self._stay
|
||||
call self._restoreCursorPos()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._previousWindow() {{{1
|
||||
function! s:Opener._previousWindow()
|
||||
if !nerdtree#isWindowUsable(winnr("#")) && nerdtree#firstUsableWindow() ==# -1
|
||||
call self._newSplit()
|
||||
else
|
||||
try
|
||||
if !nerdtree#isWindowUsable(winnr("#"))
|
||||
call nerdtree#exec(nerdtree#firstUsableWindow() . "wincmd w")
|
||||
else
|
||||
call nerdtree#exec('wincmd p')
|
||||
endif
|
||||
catch /^Vim\%((\a\+)\)\=:E37/
|
||||
call nerdtree#putCursorInTreeWin()
|
||||
throw "NERDTree.FileAlreadyOpenAndModifiedError: ". self._path.str() ." is already open and modified."
|
||||
catch /^Vim\%((\a\+)\)\=:/
|
||||
echo v:exception
|
||||
endtry
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._restoreCursorPos(){{{1
|
||||
function! s:Opener._restoreCursorPos()
|
||||
call nerdtree#exec('normal ' . self._tabnr . 'gt')
|
||||
call nerdtree#exec(bufwinnr(self._bufnr) . 'wincmd w')
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._reuseWindow(){{{1
|
||||
"put the cursor in the first window we find for this file
|
||||
"
|
||||
"return 1 if we were successful
|
||||
function! s:Opener._reuseWindow()
|
||||
"check the current tab for the window
|
||||
let winnr = bufwinnr('^' . self._path.str() . '$')
|
||||
if winnr != -1
|
||||
call nerdtree#exec(winnr . "wincmd w")
|
||||
call self._checkToCloseTree(0)
|
||||
return 1
|
||||
else
|
||||
"check other tabs
|
||||
let tabnr = self._path.tabnr()
|
||||
if tabnr
|
||||
call self._checkToCloseTree(1)
|
||||
call nerdtree#exec('normal! ' . tabnr . 'gt')
|
||||
let winnr = bufwinnr('^' . self._path.str() . '$')
|
||||
call nerdtree#exec(winnr . "wincmd w")
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Opener._saveCursorPos(){{{1
|
||||
function! s:Opener._saveCursorPos()
|
||||
let self._bufnr = bufnr("")
|
||||
let self._tabnr = tabpagenr()
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,724 +0,0 @@
|
|||
"we need to use this number many times for sorting... so we calculate it only
|
||||
"once here
|
||||
let s:NERDTreeSortStarIndex = index(g:NERDTreeSortOrder, '*')
|
||||
|
||||
"CLASS: Path
|
||||
"============================================================
|
||||
let s:Path = {}
|
||||
let g:NERDTreePath = s:Path
|
||||
|
||||
"FUNCTION: Path.AbsolutePathFor(str) {{{1
|
||||
function! s:Path.AbsolutePathFor(str)
|
||||
let prependCWD = 0
|
||||
if nerdtree#runningWindows()
|
||||
let prependCWD = a:str !~# '^.:\(\\\|\/\)' && a:str !~# '^\(\\\\\|\/\/\)'
|
||||
else
|
||||
let prependCWD = a:str !~# '^/'
|
||||
endif
|
||||
|
||||
let toReturn = a:str
|
||||
if prependCWD
|
||||
let toReturn = getcwd() . s:Path.Slash() . a:str
|
||||
endif
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.bookmarkNames() {{{1
|
||||
function! s:Path.bookmarkNames()
|
||||
if !exists("self._bookmarkNames")
|
||||
call self.cacheDisplayString()
|
||||
endif
|
||||
return self._bookmarkNames
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.cacheDisplayString() {{{1
|
||||
function! s:Path.cacheDisplayString()
|
||||
let self.cachedDisplayString = self.getLastPathComponent(1)
|
||||
|
||||
if self.isExecutable
|
||||
let self.cachedDisplayString = self.cachedDisplayString . '*'
|
||||
endif
|
||||
|
||||
let self._bookmarkNames = []
|
||||
for i in g:NERDTreeBookmark.Bookmarks()
|
||||
if i.path.equals(self)
|
||||
call add(self._bookmarkNames, i.name)
|
||||
endif
|
||||
endfor
|
||||
if !empty(self._bookmarkNames)
|
||||
let self.cachedDisplayString .= ' {' . join(self._bookmarkNames) . '}'
|
||||
endif
|
||||
|
||||
if self.isSymLink
|
||||
let self.cachedDisplayString .= ' -> ' . self.symLinkDest
|
||||
endif
|
||||
|
||||
if self.isReadOnly
|
||||
let self.cachedDisplayString .= ' [RO]'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.changeToDir() {{{1
|
||||
function! s:Path.changeToDir()
|
||||
let dir = self.str({'format': 'Cd'})
|
||||
if self.isDirectory ==# 0
|
||||
let dir = self.getParent().str({'format': 'Cd'})
|
||||
endif
|
||||
|
||||
try
|
||||
execute "cd " . dir
|
||||
call nerdtree#echo("CWD is now: " . getcwd())
|
||||
catch
|
||||
throw "NERDTree.PathChangeError: cannot change CWD to " . dir
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.compareTo() {{{1
|
||||
"
|
||||
"Compares this Path to the given path and returns 0 if they are equal, -1 if
|
||||
"this Path is "less than" the given path, or 1 if it is "greater".
|
||||
"
|
||||
"Args:
|
||||
"path: the path object to compare this to
|
||||
"
|
||||
"Return:
|
||||
"1, -1 or 0
|
||||
function! s:Path.compareTo(path)
|
||||
let thisPath = self.getLastPathComponent(1)
|
||||
let thatPath = a:path.getLastPathComponent(1)
|
||||
|
||||
"if the paths are the same then clearly we return 0
|
||||
if thisPath ==# thatPath
|
||||
return 0
|
||||
endif
|
||||
|
||||
let thisSS = self.getSortOrderIndex()
|
||||
let thatSS = a:path.getSortOrderIndex()
|
||||
|
||||
"compare the sort sequences, if they are different then the return
|
||||
"value is easy
|
||||
if thisSS < thatSS
|
||||
return -1
|
||||
elseif thisSS > thatSS
|
||||
return 1
|
||||
else
|
||||
"if the sort sequences are the same then compare the paths
|
||||
"alphabetically
|
||||
let pathCompare = g:NERDTreeCaseSensitiveSort ? thisPath <# thatPath : thisPath <? thatPath
|
||||
if pathCompare
|
||||
return -1
|
||||
else
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.Create(fullpath) {{{1
|
||||
"
|
||||
"Factory method.
|
||||
"
|
||||
"Creates a path object with the given path. The path is also created on the
|
||||
"filesystem. If the path already exists, a NERDTree.Path.Exists exception is
|
||||
"thrown. If any other errors occur, a NERDTree.Path exception is thrown.
|
||||
"
|
||||
"Args:
|
||||
"fullpath: the full filesystem path to the file/dir to create
|
||||
function! s:Path.Create(fullpath)
|
||||
"bail if the a:fullpath already exists
|
||||
if isdirectory(a:fullpath) || filereadable(a:fullpath)
|
||||
throw "NERDTree.CreatePathError: Directory Exists: '" . a:fullpath . "'"
|
||||
endif
|
||||
|
||||
try
|
||||
|
||||
"if it ends with a slash, assume its a dir create it
|
||||
if a:fullpath =~# '\(\\\|\/\)$'
|
||||
"whack the trailing slash off the end if it exists
|
||||
let fullpath = substitute(a:fullpath, '\(\\\|\/\)$', '', '')
|
||||
|
||||
call mkdir(fullpath, 'p')
|
||||
|
||||
"assume its a file and create
|
||||
else
|
||||
call writefile([], a:fullpath)
|
||||
endif
|
||||
catch
|
||||
throw "NERDTree.CreatePathError: Could not create path: '" . a:fullpath . "'"
|
||||
endtry
|
||||
|
||||
return s:Path.New(a:fullpath)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.copy(dest) {{{1
|
||||
"
|
||||
"Copies the file/dir represented by this Path to the given location
|
||||
"
|
||||
"Args:
|
||||
"dest: the location to copy this dir/file to
|
||||
function! s:Path.copy(dest)
|
||||
if !s:Path.CopyingSupported()
|
||||
throw "NERDTree.CopyingNotSupportedError: Copying is not supported on this OS"
|
||||
endif
|
||||
|
||||
let dest = s:Path.WinToUnixPath(a:dest)
|
||||
|
||||
let cmd = g:NERDTreeCopyCmd . " " . escape(self.str(), nerdtree#escChars()) . " " . escape(dest, nerdtree#escChars())
|
||||
let success = system(cmd)
|
||||
if success != 0
|
||||
throw "NERDTree.CopyError: Could not copy ''". self.str() ."'' to: '" . a:dest . "'"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.CopyingSupported() {{{1
|
||||
"
|
||||
"returns 1 if copying is supported for this OS
|
||||
function! s:Path.CopyingSupported()
|
||||
return exists('g:NERDTreeCopyCmd')
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.copyingWillOverwrite(dest) {{{1
|
||||
"
|
||||
"returns 1 if copy this path to the given location will cause files to
|
||||
"overwritten
|
||||
"
|
||||
"Args:
|
||||
"dest: the location this path will be copied to
|
||||
function! s:Path.copyingWillOverwrite(dest)
|
||||
if filereadable(a:dest)
|
||||
return 1
|
||||
endif
|
||||
|
||||
if isdirectory(a:dest)
|
||||
let path = s:Path.JoinPathStrings(a:dest, self.getLastPathComponent(0))
|
||||
if filereadable(path)
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.delete() {{{1
|
||||
"
|
||||
"Deletes the file represented by this path.
|
||||
"Deletion of directories is not supported
|
||||
"
|
||||
"Throws NERDTree.Path.Deletion exceptions
|
||||
function! s:Path.delete()
|
||||
if self.isDirectory
|
||||
|
||||
let cmd = g:NERDTreeRemoveDirCmd . self.str({'escape': 1})
|
||||
let success = system(cmd)
|
||||
|
||||
if v:shell_error != 0
|
||||
throw "NERDTree.PathDeletionError: Could not delete directory: '" . self.str() . "'"
|
||||
endif
|
||||
else
|
||||
let success = delete(self.str())
|
||||
if success != 0
|
||||
throw "NERDTree.PathDeletionError: Could not delete file: '" . self.str() . "'"
|
||||
endif
|
||||
endif
|
||||
|
||||
"delete all bookmarks for this path
|
||||
for i in self.bookmarkNames()
|
||||
let bookmark = g:NERDTreeBookmark.BookmarkFor(i)
|
||||
call bookmark.delete()
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.displayString() {{{1
|
||||
"
|
||||
"Returns a string that specifies how the path should be represented as a
|
||||
"string
|
||||
function! s:Path.displayString()
|
||||
if self.cachedDisplayString ==# ""
|
||||
call self.cacheDisplayString()
|
||||
endif
|
||||
|
||||
return self.cachedDisplayString
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.edit() {{{1
|
||||
function! s:Path.edit()
|
||||
exec "edit " . self.str({'format': 'Edit'})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.extractDriveLetter(fullpath) {{{1
|
||||
"
|
||||
"If running windows, cache the drive letter for this path
|
||||
function! s:Path.extractDriveLetter(fullpath)
|
||||
if nerdtree#runningWindows()
|
||||
if a:fullpath =~ '^\(\\\\\|\/\/\)'
|
||||
"For network shares, the 'drive' consists of the first two parts of the path, i.e. \\boxname\share
|
||||
let self.drive = substitute(a:fullpath, '^\(\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\).*', '\1', '')
|
||||
let self.drive = substitute(self.drive, '/', '\', "g")
|
||||
else
|
||||
let self.drive = substitute(a:fullpath, '\(^[a-zA-Z]:\).*', '\1', '')
|
||||
endif
|
||||
else
|
||||
let self.drive = ''
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.exists() {{{1
|
||||
"return 1 if this path points to a location that is readable or is a directory
|
||||
function! s:Path.exists()
|
||||
let p = self.str()
|
||||
return filereadable(p) || isdirectory(p)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getDir() {{{1
|
||||
"
|
||||
"Returns this path if it is a directory, else this paths parent.
|
||||
"
|
||||
"Return:
|
||||
"a Path object
|
||||
function! s:Path.getDir()
|
||||
if self.isDirectory
|
||||
return self
|
||||
else
|
||||
return self.getParent()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getParent() {{{1
|
||||
"
|
||||
"Returns a new path object for this paths parent
|
||||
"
|
||||
"Return:
|
||||
"a new Path object
|
||||
function! s:Path.getParent()
|
||||
if nerdtree#runningWindows()
|
||||
let path = self.drive . '\' . join(self.pathSegments[0:-2], '\')
|
||||
else
|
||||
let path = '/'. join(self.pathSegments[0:-2], '/')
|
||||
endif
|
||||
|
||||
return s:Path.New(path)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getLastPathComponent(dirSlash) {{{1
|
||||
"
|
||||
"Gets the last part of this path.
|
||||
"
|
||||
"Args:
|
||||
"dirSlash: if 1 then a trailing slash will be added to the returned value for
|
||||
"directory nodes.
|
||||
function! s:Path.getLastPathComponent(dirSlash)
|
||||
if empty(self.pathSegments)
|
||||
return ''
|
||||
endif
|
||||
let toReturn = self.pathSegments[-1]
|
||||
if a:dirSlash && self.isDirectory
|
||||
let toReturn = toReturn . '/'
|
||||
endif
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.getSortOrderIndex() {{{1
|
||||
"returns the index of the pattern in g:NERDTreeSortOrder that this path matches
|
||||
function! s:Path.getSortOrderIndex()
|
||||
let i = 0
|
||||
while i < len(g:NERDTreeSortOrder)
|
||||
if self.getLastPathComponent(1) =~# g:NERDTreeSortOrder[i]
|
||||
return i
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
return s:NERDTreeSortStarIndex
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.isUnixHiddenFile() {{{1
|
||||
"check for unix hidden files
|
||||
function! s:Path.isUnixHiddenFile()
|
||||
return self.getLastPathComponent(0) =~# '^\.'
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.isUnixHiddenPath() {{{1
|
||||
"check for unix path with hidden components
|
||||
function! s:Path.isUnixHiddenPath()
|
||||
if self.getLastPathComponent(0) =~# '^\.'
|
||||
return 1
|
||||
else
|
||||
for segment in self.pathSegments
|
||||
if segment =~# '^\.'
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.ignore() {{{1
|
||||
"returns true if this path should be ignored
|
||||
function! s:Path.ignore()
|
||||
"filter out the user specified paths to ignore
|
||||
if b:NERDTreeIgnoreEnabled
|
||||
for i in g:NERDTreeIgnore
|
||||
if self._ignorePatternMatches(i)
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
"dont show hidden files unless instructed to
|
||||
if b:NERDTreeShowHidden ==# 0 && self.isUnixHiddenFile()
|
||||
return 1
|
||||
endif
|
||||
|
||||
if b:NERDTreeShowFiles ==# 0 && self.isDirectory ==# 0
|
||||
return 1
|
||||
endif
|
||||
|
||||
if exists("*NERDTreeCustomIgnoreFilter") && NERDTreeCustomIgnoreFilter(self)
|
||||
return 1
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._ignorePatternMatches(pattern) {{{1
|
||||
"returns true if this path matches the given ignore pattern
|
||||
function! s:Path._ignorePatternMatches(pattern)
|
||||
let pat = a:pattern
|
||||
if strpart(pat,len(pat)-7) == '[[dir]]'
|
||||
if !self.isDirectory
|
||||
return 0
|
||||
endif
|
||||
let pat = strpart(pat,0, len(pat)-7)
|
||||
elseif strpart(pat,len(pat)-8) == '[[file]]'
|
||||
if self.isDirectory
|
||||
return 0
|
||||
endif
|
||||
let pat = strpart(pat,0, len(pat)-8)
|
||||
endif
|
||||
|
||||
return self.getLastPathComponent(0) =~# pat
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.isUnder(path) {{{1
|
||||
"return 1 if this path is somewhere under the given path in the filesystem.
|
||||
"
|
||||
"a:path should be a dir
|
||||
function! s:Path.isUnder(path)
|
||||
if a:path.isDirectory == 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
let this = self.str()
|
||||
let that = a:path.str()
|
||||
return stridx(this, that . s:Path.Slash()) == 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.JoinPathStrings(...) {{{1
|
||||
function! s:Path.JoinPathStrings(...)
|
||||
let components = []
|
||||
for i in a:000
|
||||
let components = extend(components, split(i, '/'))
|
||||
endfor
|
||||
return '/' . join(components, '/')
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.equals() {{{1
|
||||
"
|
||||
"Determines whether 2 path objects are "equal".
|
||||
"They are equal if the paths they represent are the same
|
||||
"
|
||||
"Args:
|
||||
"path: the other path obj to compare this with
|
||||
function! s:Path.equals(path)
|
||||
return self.str() ==# a:path.str()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.New() {{{1
|
||||
"The Constructor for the Path object
|
||||
function! s:Path.New(path)
|
||||
let newPath = copy(self)
|
||||
|
||||
call newPath.readInfoFromDisk(s:Path.AbsolutePathFor(a:path))
|
||||
|
||||
let newPath.cachedDisplayString = ""
|
||||
|
||||
return newPath
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.Slash() {{{1
|
||||
"return the slash to use for the current OS
|
||||
function! s:Path.Slash()
|
||||
return nerdtree#runningWindows() ? '\' : '/'
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.Resolve() {{{1
|
||||
"Invoke the vim resolve() function and return the result
|
||||
"This is necessary because in some versions of vim resolve() removes trailing
|
||||
"slashes while in other versions it doesn't. This always removes the trailing
|
||||
"slash
|
||||
function! s:Path.Resolve(path)
|
||||
let tmp = resolve(a:path)
|
||||
return tmp =~# '.\+/$' ? substitute(tmp, '/$', '', '') : tmp
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.readInfoFromDisk(fullpath) {{{1
|
||||
"
|
||||
"
|
||||
"Throws NERDTree.Path.InvalidArguments exception.
|
||||
function! s:Path.readInfoFromDisk(fullpath)
|
||||
call self.extractDriveLetter(a:fullpath)
|
||||
|
||||
let fullpath = s:Path.WinToUnixPath(a:fullpath)
|
||||
|
||||
if getftype(fullpath) ==# "fifo"
|
||||
throw "NERDTree.InvalidFiletypeError: Cant handle FIFO files: " . a:fullpath
|
||||
endif
|
||||
|
||||
let self.pathSegments = split(fullpath, '/')
|
||||
|
||||
let self.isReadOnly = 0
|
||||
if isdirectory(a:fullpath)
|
||||
let self.isDirectory = 1
|
||||
elseif filereadable(a:fullpath)
|
||||
let self.isDirectory = 0
|
||||
let self.isReadOnly = filewritable(a:fullpath) ==# 0
|
||||
else
|
||||
throw "NERDTree.InvalidArgumentsError: Invalid path = " . a:fullpath
|
||||
endif
|
||||
|
||||
let self.isExecutable = 0
|
||||
if !self.isDirectory
|
||||
let self.isExecutable = getfperm(a:fullpath) =~# 'x'
|
||||
endif
|
||||
|
||||
"grab the last part of the path (minus the trailing slash)
|
||||
let lastPathComponent = self.getLastPathComponent(0)
|
||||
|
||||
"get the path to the new node with the parent dir fully resolved
|
||||
let hardPath = s:Path.Resolve(self.strTrunk()) . '/' . lastPathComponent
|
||||
|
||||
"if the last part of the path is a symlink then flag it as such
|
||||
let self.isSymLink = (s:Path.Resolve(hardPath) != hardPath)
|
||||
if self.isSymLink
|
||||
let self.symLinkDest = s:Path.Resolve(fullpath)
|
||||
|
||||
"if the link is a dir then slap a / on the end of its dest
|
||||
if isdirectory(self.symLinkDest)
|
||||
|
||||
"we always wanna treat MS windows shortcuts as files for
|
||||
"simplicity
|
||||
if hardPath !~# '\.lnk$'
|
||||
|
||||
let self.symLinkDest = self.symLinkDest . '/'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.refresh() {{{1
|
||||
function! s:Path.refresh()
|
||||
call self.readInfoFromDisk(self.str())
|
||||
call self.cacheDisplayString()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.rename() {{{1
|
||||
"
|
||||
"Renames this node on the filesystem
|
||||
function! s:Path.rename(newPath)
|
||||
if a:newPath ==# ''
|
||||
throw "NERDTree.InvalidArgumentsError: Invalid newPath for renaming = ". a:newPath
|
||||
endif
|
||||
|
||||
let success = rename(self.str(), a:newPath)
|
||||
if success != 0
|
||||
throw "NERDTree.PathRenameError: Could not rename: '" . self.str() . "'" . 'to:' . a:newPath
|
||||
endif
|
||||
call self.readInfoFromDisk(a:newPath)
|
||||
|
||||
for i in self.bookmarkNames()
|
||||
let b = g:NERDTreeBookmark.BookmarkFor(i)
|
||||
call b.setPath(copy(self))
|
||||
endfor
|
||||
call g:NERDTreeBookmark.Write()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.str() {{{1
|
||||
"
|
||||
"Returns a string representation of this Path
|
||||
"
|
||||
"Takes an optional dictionary param to specify how the output should be
|
||||
"formatted.
|
||||
"
|
||||
"The dict may have the following keys:
|
||||
" 'format'
|
||||
" 'escape'
|
||||
" 'truncateTo'
|
||||
"
|
||||
"The 'format' key may have a value of:
|
||||
" 'Cd' - a string to be used with the :cd command
|
||||
" 'Edit' - a string to be used with :e :sp :new :tabedit etc
|
||||
" 'UI' - a string used in the NERD tree UI
|
||||
"
|
||||
"The 'escape' key, if specified will cause the output to be escaped with
|
||||
"shellescape()
|
||||
"
|
||||
"The 'truncateTo' key causes the resulting string to be truncated to the value
|
||||
"'truncateTo' maps to. A '<' char will be prepended.
|
||||
function! s:Path.str(...)
|
||||
let options = a:0 ? a:1 : {}
|
||||
let toReturn = ""
|
||||
|
||||
if has_key(options, 'format')
|
||||
let format = options['format']
|
||||
if has_key(self, '_strFor' . format)
|
||||
exec 'let toReturn = self._strFor' . format . '()'
|
||||
else
|
||||
raise 'NERDTree.UnknownFormatError: unknown format "'. format .'"'
|
||||
endif
|
||||
else
|
||||
let toReturn = self._str()
|
||||
endif
|
||||
|
||||
if nerdtree#has_opt(options, 'escape')
|
||||
let toReturn = shellescape(toReturn)
|
||||
endif
|
||||
|
||||
if has_key(options, 'truncateTo')
|
||||
let limit = options['truncateTo']
|
||||
if len(toReturn) > limit
|
||||
let toReturn = "<" . strpart(toReturn, len(toReturn) - limit + 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForUI() {{{1
|
||||
function! s:Path._strForUI()
|
||||
let toReturn = '/' . join(self.pathSegments, '/')
|
||||
if self.isDirectory && toReturn != '/'
|
||||
let toReturn = toReturn . '/'
|
||||
endif
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForCd() {{{1
|
||||
"
|
||||
" returns a string that can be used with :cd
|
||||
function! s:Path._strForCd()
|
||||
return escape(self.str(), nerdtree#escChars())
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForEdit() {{{1
|
||||
"
|
||||
"Return: the string for this path that is suitable to be used with the :edit
|
||||
"command
|
||||
function! s:Path._strForEdit()
|
||||
let p = escape(self.str({'format': 'UI'}), nerdtree#escChars())
|
||||
let cwd = getcwd() . s:Path.Slash()
|
||||
|
||||
"return a relative path if we can
|
||||
let isRelative = 0
|
||||
if nerdtree#runningWindows()
|
||||
let isRelative = stridx(tolower(p), tolower(cwd)) == 0
|
||||
else
|
||||
let isRelative = stridx(p, cwd) == 0
|
||||
endif
|
||||
|
||||
if isRelative
|
||||
let p = strpart(p, strlen(cwd))
|
||||
|
||||
"handle the edge case where the file begins with a + (vim interprets
|
||||
"the +foo in `:e +foo` as an option to :edit)
|
||||
if p[0] == "+"
|
||||
let p = '\' . p
|
||||
endif
|
||||
endif
|
||||
|
||||
if p ==# ''
|
||||
let p = '.'
|
||||
endif
|
||||
|
||||
return p
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._strForGlob() {{{1
|
||||
function! s:Path._strForGlob()
|
||||
let lead = s:Path.Slash()
|
||||
|
||||
"if we are running windows then slap a drive letter on the front
|
||||
if nerdtree#runningWindows()
|
||||
let lead = self.drive . '\'
|
||||
endif
|
||||
|
||||
let toReturn = lead . join(self.pathSegments, s:Path.Slash())
|
||||
|
||||
if !nerdtree#runningWindows()
|
||||
let toReturn = escape(toReturn, nerdtree#escChars())
|
||||
endif
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path._str() {{{1
|
||||
"
|
||||
"Gets the string path for this path object that is appropriate for the OS.
|
||||
"EG, in windows c:\foo\bar
|
||||
" in *nix /foo/bar
|
||||
function! s:Path._str()
|
||||
let lead = s:Path.Slash()
|
||||
|
||||
"if we are running windows then slap a drive letter on the front
|
||||
if nerdtree#runningWindows()
|
||||
let lead = self.drive . '\'
|
||||
endif
|
||||
|
||||
return lead . join(self.pathSegments, s:Path.Slash())
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.strTrunk() {{{1
|
||||
"Gets the path without the last segment on the end.
|
||||
function! s:Path.strTrunk()
|
||||
return self.drive . '/' . join(self.pathSegments[0:-2], '/')
|
||||
endfunction
|
||||
|
||||
" FUNCTION: Path.tabnr() {{{1
|
||||
" return the number of the first tab that is displaying this file
|
||||
"
|
||||
" return 0 if no tab was found
|
||||
function! s:Path.tabnr()
|
||||
let str = self.str()
|
||||
for t in range(tabpagenr('$'))
|
||||
for b in tabpagebuflist(t+1)
|
||||
if str == expand('#' . b . ':p')
|
||||
return t+1
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: Path.WinToUnixPath(pathstr){{{1
|
||||
"Takes in a windows path and returns the unix equiv
|
||||
"
|
||||
"A class level method
|
||||
"
|
||||
"Args:
|
||||
"pathstr: the windows path to convert
|
||||
function! s:Path.WinToUnixPath(pathstr)
|
||||
if !nerdtree#runningWindows()
|
||||
return a:pathstr
|
||||
endif
|
||||
|
||||
let toReturn = a:pathstr
|
||||
|
||||
"remove the x:\ of the front
|
||||
let toReturn = substitute(toReturn, '^.*:\(\\\|/\)\?', '/', "")
|
||||
|
||||
"remove the \\ network share from the front
|
||||
let toReturn = substitute(toReturn, '^\(\\\\\|\/\/\)[^\\\/]*\(\\\|\/\)[^\\\/]*\(\\\|\/\)\?', '/', "")
|
||||
|
||||
"convert all \ chars to /
|
||||
let toReturn = substitute(toReturn, '\', '/', "g")
|
||||
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,528 +0,0 @@
|
|||
"CLASS: TreeDirNode
|
||||
"A subclass of NERDTreeFileNode.
|
||||
"
|
||||
"The 'composite' part of the file/dir composite.
|
||||
"============================================================
|
||||
let s:TreeDirNode = copy(g:NERDTreeFileNode)
|
||||
let g:NERDTreeDirNode = s:TreeDirNode
|
||||
|
||||
"FUNCTION: TreeDirNode.AbsoluteTreeRoot(){{{1
|
||||
"class method that returns the highest cached ancestor of the current root
|
||||
function! s:TreeDirNode.AbsoluteTreeRoot()
|
||||
let currentNode = b:NERDTreeRoot
|
||||
while currentNode.parent != {}
|
||||
let currentNode = currentNode.parent
|
||||
endwhile
|
||||
return currentNode
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.activate([options]) {{{1
|
||||
unlet s:TreeDirNode.activate
|
||||
function! s:TreeDirNode.activate(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
call self.toggleOpen(opts)
|
||||
call nerdtree#renderView()
|
||||
call self.putCursorHere(0, 0)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.addChild(treenode, inOrder) {{{1
|
||||
"Adds the given treenode to the list of children for this node
|
||||
"
|
||||
"Args:
|
||||
"-treenode: the node to add
|
||||
"-inOrder: 1 if the new node should be inserted in sorted order
|
||||
function! s:TreeDirNode.addChild(treenode, inOrder)
|
||||
call add(self.children, a:treenode)
|
||||
let a:treenode.parent = self
|
||||
|
||||
if a:inOrder
|
||||
call self.sortChildren()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.close() {{{1
|
||||
"Closes this directory
|
||||
function! s:TreeDirNode.close()
|
||||
let self.isOpen = 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.closeChildren() {{{1
|
||||
"Closes all the child dir nodes of this node
|
||||
function! s:TreeDirNode.closeChildren()
|
||||
for i in self.children
|
||||
if i.path.isDirectory
|
||||
call i.close()
|
||||
call i.closeChildren()
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.createChild(path, inOrder) {{{1
|
||||
"Instantiates a new child node for this node with the given path. The new
|
||||
"nodes parent is set to this node.
|
||||
"
|
||||
"Args:
|
||||
"path: a Path object that this node will represent/contain
|
||||
"inOrder: 1 if the new node should be inserted in sorted order
|
||||
"
|
||||
"Returns:
|
||||
"the newly created node
|
||||
function! s:TreeDirNode.createChild(path, inOrder)
|
||||
let newTreeNode = g:NERDTreeFileNode.New(a:path)
|
||||
call self.addChild(newTreeNode, a:inOrder)
|
||||
return newTreeNode
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.findNode(path) {{{1
|
||||
"Will find one of the children (recursively) that has the given path
|
||||
"
|
||||
"Args:
|
||||
"path: a path object
|
||||
unlet s:TreeDirNode.findNode
|
||||
function! s:TreeDirNode.findNode(path)
|
||||
if a:path.equals(self.path)
|
||||
return self
|
||||
endif
|
||||
if stridx(a:path.str(), self.path.str(), 0) ==# -1
|
||||
return {}
|
||||
endif
|
||||
|
||||
if self.path.isDirectory
|
||||
for i in self.children
|
||||
let retVal = i.findNode(a:path)
|
||||
if retVal != {}
|
||||
return retVal
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.getChildCount() {{{1
|
||||
"Returns the number of children this node has
|
||||
function! s:TreeDirNode.getChildCount()
|
||||
return len(self.children)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.getChild(path) {{{1
|
||||
"Returns child node of this node that has the given path or {} if no such node
|
||||
"exists.
|
||||
"
|
||||
"This function doesnt not recurse into child dir nodes
|
||||
"
|
||||
"Args:
|
||||
"path: a path object
|
||||
function! s:TreeDirNode.getChild(path)
|
||||
if stridx(a:path.str(), self.path.str(), 0) ==# -1
|
||||
return {}
|
||||
endif
|
||||
|
||||
let index = self.getChildIndex(a:path)
|
||||
if index ==# -1
|
||||
return {}
|
||||
else
|
||||
return self.children[index]
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.getChildByIndex(indx, visible) {{{1
|
||||
"returns the child at the given index
|
||||
"Args:
|
||||
"indx: the index to get the child from
|
||||
"visible: 1 if only the visible children array should be used, 0 if all the
|
||||
"children should be searched.
|
||||
function! s:TreeDirNode.getChildByIndex(indx, visible)
|
||||
let array_to_search = a:visible? self.getVisibleChildren() : self.children
|
||||
if a:indx > len(array_to_search)
|
||||
throw "NERDTree.InvalidArgumentsError: Index is out of bounds."
|
||||
endif
|
||||
return array_to_search[a:indx]
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.getChildIndex(path) {{{1
|
||||
"Returns the index of the child node of this node that has the given path or
|
||||
"-1 if no such node exists.
|
||||
"
|
||||
"This function doesnt not recurse into child dir nodes
|
||||
"
|
||||
"Args:
|
||||
"path: a path object
|
||||
function! s:TreeDirNode.getChildIndex(path)
|
||||
if stridx(a:path.str(), self.path.str(), 0) ==# -1
|
||||
return -1
|
||||
endif
|
||||
|
||||
"do a binary search for the child
|
||||
let a = 0
|
||||
let z = self.getChildCount()
|
||||
while a < z
|
||||
let mid = (a+z)/2
|
||||
let diff = a:path.compareTo(self.children[mid].path)
|
||||
|
||||
if diff ==# -1
|
||||
let z = mid
|
||||
elseif diff ==# 1
|
||||
let a = mid+1
|
||||
else
|
||||
return mid
|
||||
endif
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.GetSelected() {{{1
|
||||
"Returns the current node if it is a dir node, or else returns the current
|
||||
"nodes parent
|
||||
unlet s:TreeDirNode.GetSelected
|
||||
function! s:TreeDirNode.GetSelected()
|
||||
let currentDir = g:NERDTreeFileNode.GetSelected()
|
||||
if currentDir != {} && !currentDir.isRoot()
|
||||
if currentDir.path.isDirectory ==# 0
|
||||
let currentDir = currentDir.parent
|
||||
endif
|
||||
endif
|
||||
return currentDir
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.getVisibleChildCount() {{{1
|
||||
"Returns the number of visible children this node has
|
||||
function! s:TreeDirNode.getVisibleChildCount()
|
||||
return len(self.getVisibleChildren())
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.getVisibleChildren() {{{1
|
||||
"Returns a list of children to display for this node, in the correct order
|
||||
"
|
||||
"Return:
|
||||
"an array of treenodes
|
||||
function! s:TreeDirNode.getVisibleChildren()
|
||||
let toReturn = []
|
||||
for i in self.children
|
||||
if i.path.ignore() ==# 0
|
||||
call add(toReturn, i)
|
||||
endif
|
||||
endfor
|
||||
return toReturn
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.hasVisibleChildren() {{{1
|
||||
"returns 1 if this node has any childre, 0 otherwise..
|
||||
function! s:TreeDirNode.hasVisibleChildren()
|
||||
return self.getVisibleChildCount() != 0
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode._initChildren() {{{1
|
||||
"Removes all childen from this node and re-reads them
|
||||
"
|
||||
"Args:
|
||||
"silent: 1 if the function should not echo any "please wait" messages for
|
||||
"large directories
|
||||
"
|
||||
"Return: the number of child nodes read
|
||||
function! s:TreeDirNode._initChildren(silent)
|
||||
"remove all the current child nodes
|
||||
let self.children = []
|
||||
|
||||
"get an array of all the files in the nodes dir
|
||||
let dir = self.path
|
||||
let globDir = dir.str({'format': 'Glob'})
|
||||
|
||||
if version >= 703
|
||||
let filesStr = globpath(globDir, '*', 1) . "\n" . globpath(globDir, '.*', 1)
|
||||
else
|
||||
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
|
||||
endif
|
||||
|
||||
let files = split(filesStr, "\n")
|
||||
|
||||
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
|
||||
call nerdtree#echo("Please wait, caching a large dir ...")
|
||||
endif
|
||||
|
||||
let invalidFilesFound = 0
|
||||
for i in files
|
||||
|
||||
"filter out the .. and . directories
|
||||
"Note: we must match .. AND ../ cos sometimes the globpath returns
|
||||
"../ for path with strange chars (eg $)
|
||||
if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
|
||||
|
||||
"put the next file in a new node and attach it
|
||||
try
|
||||
let path = g:NERDTreePath.New(i)
|
||||
call self.createChild(path, 0)
|
||||
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
|
||||
let invalidFilesFound += 1
|
||||
endtry
|
||||
endif
|
||||
endfor
|
||||
|
||||
call self.sortChildren()
|
||||
|
||||
if !a:silent && len(files) > g:NERDTreeNotificationThreshold
|
||||
call nerdtree#echo("Please wait, caching a large dir ... DONE (". self.getChildCount() ." nodes cached).")
|
||||
endif
|
||||
|
||||
if invalidFilesFound
|
||||
call nerdtree#echoWarning(invalidFilesFound . " file(s) could not be loaded into the NERD tree")
|
||||
endif
|
||||
return self.getChildCount()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.New(path) {{{1
|
||||
"Returns a new TreeNode object with the given path and parent
|
||||
"
|
||||
"Args:
|
||||
"path: a path object representing the full filesystem path to the file/dir that the node represents
|
||||
unlet s:TreeDirNode.New
|
||||
function! s:TreeDirNode.New(path)
|
||||
if a:path.isDirectory != 1
|
||||
throw "NERDTree.InvalidArgumentsError: A TreeDirNode object must be instantiated with a directory Path object."
|
||||
endif
|
||||
|
||||
let newTreeNode = copy(self)
|
||||
let newTreeNode.path = a:path
|
||||
|
||||
let newTreeNode.isOpen = 0
|
||||
let newTreeNode.children = []
|
||||
|
||||
let newTreeNode.parent = {}
|
||||
|
||||
return newTreeNode
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.open([opts]) {{{1
|
||||
"Open the dir in the current tree or in a new tree elsewhere.
|
||||
"
|
||||
"If opening in the current tree, return the number of cached nodes.
|
||||
unlet s:TreeDirNode.open
|
||||
function! s:TreeDirNode.open(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
|
||||
if has_key(opts, 'where') && !empty(opts['where'])
|
||||
let opener = g:NERDTreeOpener.New(self.path, opts)
|
||||
call opener.open(self)
|
||||
else
|
||||
let self.isOpen = 1
|
||||
if self.children ==# []
|
||||
return self._initChildren(0)
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.openAlong([opts]) {{{1
|
||||
"recursive open the dir if it has only one directory child.
|
||||
"
|
||||
"return the level of opened directories.
|
||||
function! s:TreeDirNode.openAlong(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
let level = 0
|
||||
|
||||
let node = self
|
||||
while node.path.isDirectory
|
||||
call node.open(opts)
|
||||
let level += 1
|
||||
if node.getVisibleChildCount() == 1
|
||||
let node = node.getChildByIndex(0, 1)
|
||||
else
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
return level
|
||||
endfunction
|
||||
|
||||
" FUNCTION: TreeDirNode.openExplorer() {{{1
|
||||
" opens an explorer window for this node in the previous window (could be a
|
||||
" nerd tree or a netrw)
|
||||
function! s:TreeDirNode.openExplorer()
|
||||
call self.open({'where': 'p'})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.openInNewTab(options) {{{1
|
||||
unlet s:TreeDirNode.openInNewTab
|
||||
function! s:TreeDirNode.openInNewTab(options)
|
||||
call nerdtree#deprecated('TreeDirNode.openInNewTab', 'is deprecated, use open() instead')
|
||||
call self.open({'where': 't'})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode._openInNewTab() {{{1
|
||||
function! s:TreeDirNode._openInNewTab()
|
||||
tabnew
|
||||
call g:NERDTreeCreator.CreatePrimary(self.path.str())
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.openRecursively() {{{1
|
||||
"Opens this treenode and all of its children whose paths arent 'ignored'
|
||||
"because of the file filters.
|
||||
"
|
||||
"This method is actually a wrapper for the OpenRecursively2 method which does
|
||||
"the work.
|
||||
function! s:TreeDirNode.openRecursively()
|
||||
call self._openRecursively2(1)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode._openRecursively2() {{{1
|
||||
"Opens this all children of this treenode recursively if either:
|
||||
" *they arent filtered by file filters
|
||||
" *a:forceOpen is 1
|
||||
"
|
||||
"Args:
|
||||
"forceOpen: 1 if this node should be opened regardless of file filters
|
||||
function! s:TreeDirNode._openRecursively2(forceOpen)
|
||||
if self.path.ignore() ==# 0 || a:forceOpen
|
||||
let self.isOpen = 1
|
||||
if self.children ==# []
|
||||
call self._initChildren(1)
|
||||
endif
|
||||
|
||||
for i in self.children
|
||||
if i.path.isDirectory ==# 1
|
||||
call i._openRecursively2(0)
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.refresh() {{{1
|
||||
unlet s:TreeDirNode.refresh
|
||||
function! s:TreeDirNode.refresh()
|
||||
call self.path.refresh()
|
||||
|
||||
"if this node was ever opened, refresh its children
|
||||
if self.isOpen || !empty(self.children)
|
||||
"go thru all the files/dirs under this node
|
||||
let newChildNodes = []
|
||||
let invalidFilesFound = 0
|
||||
let dir = self.path
|
||||
let globDir = dir.str({'format': 'Glob'})
|
||||
let filesStr = globpath(globDir, '*') . "\n" . globpath(globDir, '.*')
|
||||
let files = split(filesStr, "\n")
|
||||
for i in files
|
||||
"filter out the .. and . directories
|
||||
"Note: we must match .. AND ../ cos sometimes the globpath returns
|
||||
"../ for path with strange chars (eg $)
|
||||
if i !~# '\/\.\.\/\?$' && i !~# '\/\.\/\?$'
|
||||
|
||||
try
|
||||
"create a new path and see if it exists in this nodes children
|
||||
let path = g:NERDTreePath.New(i)
|
||||
let newNode = self.getChild(path)
|
||||
if newNode != {}
|
||||
call newNode.refresh()
|
||||
call add(newChildNodes, newNode)
|
||||
|
||||
"the node doesnt exist so create it
|
||||
else
|
||||
let newNode = g:NERDTreeFileNode.New(path)
|
||||
let newNode.parent = self
|
||||
call add(newChildNodes, newNode)
|
||||
endif
|
||||
|
||||
|
||||
catch /^NERDTree.\(InvalidArguments\|InvalidFiletype\)Error/
|
||||
let invalidFilesFound = 1
|
||||
endtry
|
||||
endif
|
||||
endfor
|
||||
|
||||
"swap this nodes children out for the children we just read/refreshed
|
||||
let self.children = newChildNodes
|
||||
call self.sortChildren()
|
||||
|
||||
if invalidFilesFound
|
||||
call nerdtree#echoWarning("some files could not be loaded into the NERD tree")
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.reveal(path) {{{1
|
||||
"reveal the given path, i.e. cache and open all treenodes needed to display it
|
||||
"in the UI
|
||||
function! s:TreeDirNode.reveal(path)
|
||||
if !a:path.isUnder(self.path)
|
||||
throw "NERDTree.InvalidArgumentsError: " . a:path.str() . " should be under " . self.path.str()
|
||||
endif
|
||||
|
||||
call self.open()
|
||||
|
||||
if self.path.equals(a:path.getParent())
|
||||
let n = self.findNode(a:path)
|
||||
call nerdtree#renderView()
|
||||
call n.putCursorHere(1,0)
|
||||
return
|
||||
endif
|
||||
|
||||
let p = a:path
|
||||
while !p.getParent().equals(self.path)
|
||||
let p = p.getParent()
|
||||
endwhile
|
||||
|
||||
let n = self.findNode(p)
|
||||
call n.reveal(a:path)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.removeChild(treenode) {{{1
|
||||
"
|
||||
"Removes the given treenode from this nodes set of children
|
||||
"
|
||||
"Args:
|
||||
"treenode: the node to remove
|
||||
"
|
||||
"Throws a NERDTree.ChildNotFoundError if the given treenode is not found
|
||||
function! s:TreeDirNode.removeChild(treenode)
|
||||
for i in range(0, self.getChildCount()-1)
|
||||
if self.children[i].equals(a:treenode)
|
||||
call remove(self.children, i)
|
||||
return
|
||||
endif
|
||||
endfor
|
||||
|
||||
throw "NERDTree.ChildNotFoundError: child node was not found"
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.sortChildren() {{{1
|
||||
"
|
||||
"Sorts the children of this node according to alphabetical order and the
|
||||
"directory priority.
|
||||
"
|
||||
function! s:TreeDirNode.sortChildren()
|
||||
let CompareFunc = function("nerdtree#compareNodes")
|
||||
call sort(self.children, CompareFunc)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.toggleOpen([options]) {{{1
|
||||
"Opens this directory if it is closed and vice versa
|
||||
function! s:TreeDirNode.toggleOpen(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
if self.isOpen ==# 1
|
||||
call self.close()
|
||||
else
|
||||
if g:NERDTreeCasadeOpenSingleChildDir == 0
|
||||
call self.open(opts)
|
||||
else
|
||||
call self.openAlong(opts)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeDirNode.transplantChild(newNode) {{{1
|
||||
"Replaces the child of this with the given node (where the child node's full
|
||||
"path matches a:newNode's fullpath). The search for the matching node is
|
||||
"non-recursive
|
||||
"
|
||||
"Arg:
|
||||
"newNode: the node to graft into the tree
|
||||
function! s:TreeDirNode.transplantChild(newNode)
|
||||
for i in range(0, self.getChildCount()-1)
|
||||
if self.children[i].equals(a:newNode)
|
||||
let self.children[i] = a:newNode
|
||||
let a:newNode.parent = self
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,485 +0,0 @@
|
|||
"CLASS: TreeFileNode
|
||||
"This class is the parent of the TreeDirNode class and is the
|
||||
"'Component' part of the composite design pattern between the treenode
|
||||
"classes.
|
||||
"============================================================
|
||||
let s:TreeFileNode = {}
|
||||
let g:NERDTreeFileNode = s:TreeFileNode
|
||||
|
||||
"FUNCTION: TreeFileNode.activate(...) {{{1
|
||||
function! s:TreeFileNode.activate(...)
|
||||
call self.open(a:0 ? a:1 : {})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.bookmark(name) {{{1
|
||||
"bookmark this node with a:name
|
||||
function! s:TreeFileNode.bookmark(name)
|
||||
|
||||
"if a bookmark exists with the same name and the node is cached then save
|
||||
"it so we can update its display string
|
||||
let oldMarkedNode = {}
|
||||
try
|
||||
let oldMarkedNode = g:NERDTreeBookmark.GetNodeForName(a:name, 1)
|
||||
catch /^NERDTree.BookmarkNotFoundError/
|
||||
catch /^NERDTree.BookmarkedNodeNotFoundError/
|
||||
endtry
|
||||
|
||||
call g:NERDTreeBookmark.AddBookmark(a:name, self.path)
|
||||
call self.path.cacheDisplayString()
|
||||
call g:NERDTreeBookmark.Write()
|
||||
|
||||
if !empty(oldMarkedNode)
|
||||
call oldMarkedNode.path.cacheDisplayString()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.cacheParent() {{{1
|
||||
"initializes self.parent if it isnt already
|
||||
function! s:TreeFileNode.cacheParent()
|
||||
if empty(self.parent)
|
||||
let parentPath = self.path.getParent()
|
||||
if parentPath.equals(self.path)
|
||||
throw "NERDTree.CannotCacheParentError: already at root"
|
||||
endif
|
||||
let self.parent = s:TreeFileNode.New(parentPath)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.clearBookmarks() {{{1
|
||||
function! s:TreeFileNode.clearBookmarks()
|
||||
for i in g:NERDTreeBookmark.Bookmarks()
|
||||
if i.path.equals(self.path)
|
||||
call i.delete()
|
||||
end
|
||||
endfor
|
||||
call self.path.cacheDisplayString()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.copy(dest) {{{1
|
||||
function! s:TreeFileNode.copy(dest)
|
||||
call self.path.copy(a:dest)
|
||||
let newPath = g:NERDTreePath.New(a:dest)
|
||||
let parent = b:NERDTreeRoot.findNode(newPath.getParent())
|
||||
if !empty(parent)
|
||||
call parent.refresh()
|
||||
return parent.findNode(newPath)
|
||||
else
|
||||
return {}
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.delete {{{1
|
||||
"Removes this node from the tree and calls the Delete method for its path obj
|
||||
function! s:TreeFileNode.delete()
|
||||
call self.path.delete()
|
||||
call self.parent.removeChild(self)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.displayString() {{{1
|
||||
"
|
||||
"Returns a string that specifies how the node should be represented as a
|
||||
"string
|
||||
"
|
||||
"Return:
|
||||
"a string that can be used in the view to represent this node
|
||||
function! s:TreeFileNode.displayString()
|
||||
return self.path.displayString()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.equals(treenode) {{{1
|
||||
"
|
||||
"Compares this treenode to the input treenode and returns 1 if they are the
|
||||
"same node.
|
||||
"
|
||||
"Use this method instead of == because sometimes when the treenodes contain
|
||||
"many children, vim seg faults when doing ==
|
||||
"
|
||||
"Args:
|
||||
"treenode: the other treenode to compare to
|
||||
function! s:TreeFileNode.equals(treenode)
|
||||
return self.path.str() ==# a:treenode.path.str()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.findNode(path) {{{1
|
||||
"Returns self if this node.path.Equals the given path.
|
||||
"Returns {} if not equal.
|
||||
"
|
||||
"Args:
|
||||
"path: the path object to compare against
|
||||
function! s:TreeFileNode.findNode(path)
|
||||
if a:path.equals(self.path)
|
||||
return self
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction) {{{1
|
||||
"
|
||||
"Finds the next sibling for this node in the indicated direction. This sibling
|
||||
"must be a directory and may/may not have children as specified.
|
||||
"
|
||||
"Args:
|
||||
"direction: 0 if you want to find the previous sibling, 1 for the next sibling
|
||||
"
|
||||
"Return:
|
||||
"a treenode object or {} if no appropriate sibling could be found
|
||||
function! s:TreeFileNode.findOpenDirSiblingWithVisibleChildren(direction)
|
||||
"if we have no parent then we can have no siblings
|
||||
if self.parent != {}
|
||||
let nextSibling = self.findSibling(a:direction)
|
||||
|
||||
while nextSibling != {}
|
||||
if nextSibling.path.isDirectory && nextSibling.hasVisibleChildren() && nextSibling.isOpen
|
||||
return nextSibling
|
||||
endif
|
||||
let nextSibling = nextSibling.findSibling(a:direction)
|
||||
endwhile
|
||||
endif
|
||||
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.findSibling(direction) {{{1
|
||||
"
|
||||
"Finds the next sibling for this node in the indicated direction
|
||||
"
|
||||
"Args:
|
||||
"direction: 0 if you want to find the previous sibling, 1 for the next sibling
|
||||
"
|
||||
"Return:
|
||||
"a treenode object or {} if no sibling could be found
|
||||
function! s:TreeFileNode.findSibling(direction)
|
||||
"if we have no parent then we can have no siblings
|
||||
if self.parent != {}
|
||||
|
||||
"get the index of this node in its parents children
|
||||
let siblingIndx = self.parent.getChildIndex(self.path)
|
||||
|
||||
if siblingIndx != -1
|
||||
"move a long to the next potential sibling node
|
||||
let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
|
||||
|
||||
"keep moving along to the next sibling till we find one that is valid
|
||||
let numSiblings = self.parent.getChildCount()
|
||||
while siblingIndx >= 0 && siblingIndx < numSiblings
|
||||
|
||||
"if the next node is not an ignored node (i.e. wont show up in the
|
||||
"view) then return it
|
||||
if self.parent.children[siblingIndx].path.ignore() ==# 0
|
||||
return self.parent.children[siblingIndx]
|
||||
endif
|
||||
|
||||
"go to next node
|
||||
let siblingIndx = a:direction ==# 1 ? siblingIndx+1 : siblingIndx-1
|
||||
endwhile
|
||||
endif
|
||||
endif
|
||||
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.getLineNum(){{{1
|
||||
"returns the line number this node is rendered on, or -1 if it isnt rendered
|
||||
function! s:TreeFileNode.getLineNum()
|
||||
"if the node is the root then return the root line no.
|
||||
if self.isRoot()
|
||||
return s:TreeFileNode.GetRootLineNum()
|
||||
endif
|
||||
|
||||
let totalLines = line("$")
|
||||
|
||||
"the path components we have matched so far
|
||||
let pathcomponents = [substitute(b:NERDTreeRoot.path.str({'format': 'UI'}), '/ *$', '', '')]
|
||||
"the index of the component we are searching for
|
||||
let curPathComponent = 1
|
||||
|
||||
let fullpath = self.path.str({'format': 'UI'})
|
||||
|
||||
|
||||
let lnum = s:TreeFileNode.GetRootLineNum()
|
||||
while lnum > 0
|
||||
let lnum = lnum + 1
|
||||
"have we reached the bottom of the tree?
|
||||
if lnum ==# totalLines+1
|
||||
return -1
|
||||
endif
|
||||
|
||||
let curLine = getline(lnum)
|
||||
|
||||
let indent = nerdtree#indentLevelFor(curLine)
|
||||
if indent ==# curPathComponent
|
||||
let curLine = nerdtree#stripMarkupFromLine(curLine, 1)
|
||||
|
||||
let curPath = join(pathcomponents, '/') . '/' . curLine
|
||||
if stridx(fullpath, curPath, 0) ==# 0
|
||||
if fullpath ==# curPath || strpart(fullpath, len(curPath)-1,1) ==# '/'
|
||||
let curLine = substitute(curLine, '/ *$', '', '')
|
||||
call add(pathcomponents, curLine)
|
||||
let curPathComponent = curPathComponent + 1
|
||||
|
||||
if fullpath ==# curPath
|
||||
return lnum
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endwhile
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.GetRootForTab(){{{1
|
||||
"get the root node for this tab
|
||||
function! s:TreeFileNode.GetRootForTab()
|
||||
if nerdtree#treeExistsForTab()
|
||||
return getbufvar(t:NERDTreeBufName, 'NERDTreeRoot')
|
||||
end
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.GetRootLineNum(){{{1
|
||||
"gets the line number of the root node
|
||||
function! s:TreeFileNode.GetRootLineNum()
|
||||
let rootLine = 1
|
||||
while getline(rootLine) !~# '^\(/\|<\)'
|
||||
let rootLine = rootLine + 1
|
||||
endwhile
|
||||
return rootLine
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.GetSelected() {{{1
|
||||
"gets the treenode that the cursor is currently over
|
||||
function! s:TreeFileNode.GetSelected()
|
||||
try
|
||||
let path = nerdtree#getPath(line("."))
|
||||
if path ==# {}
|
||||
return {}
|
||||
endif
|
||||
return b:NERDTreeRoot.findNode(path)
|
||||
catch /^NERDTree/
|
||||
return {}
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.isVisible() {{{1
|
||||
"returns 1 if this node should be visible according to the tree filters and
|
||||
"hidden file filters (and their on/off status)
|
||||
function! s:TreeFileNode.isVisible()
|
||||
return !self.path.ignore()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.isRoot() {{{1
|
||||
"returns 1 if this node is b:NERDTreeRoot
|
||||
function! s:TreeFileNode.isRoot()
|
||||
if !nerdtree#treeExistsForBuf()
|
||||
throw "NERDTree.NoTreeError: No tree exists for the current buffer"
|
||||
endif
|
||||
|
||||
return self.equals(b:NERDTreeRoot)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.makeRoot() {{{1
|
||||
"Make this node the root of the tree
|
||||
function! s:TreeFileNode.makeRoot()
|
||||
if self.path.isDirectory
|
||||
let b:NERDTreeRoot = self
|
||||
else
|
||||
call self.cacheParent()
|
||||
let b:NERDTreeRoot = self.parent
|
||||
endif
|
||||
|
||||
call b:NERDTreeRoot.open()
|
||||
|
||||
"change dir to the dir of the new root if instructed to
|
||||
if g:NERDTreeChDirMode ==# 2
|
||||
exec "cd " . b:NERDTreeRoot.path.str({'format': 'Edit'})
|
||||
endif
|
||||
|
||||
silent doautocmd User NERDTreeNewRoot
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.New(path) {{{1
|
||||
"Returns a new TreeNode object with the given path and parent
|
||||
"
|
||||
"Args:
|
||||
"path: a path object representing the full filesystem path to the file/dir that the node represents
|
||||
function! s:TreeFileNode.New(path)
|
||||
if a:path.isDirectory
|
||||
return g:NERDTreeDirNode.New(a:path)
|
||||
else
|
||||
let newTreeNode = copy(self)
|
||||
let newTreeNode.path = a:path
|
||||
let newTreeNode.parent = {}
|
||||
return newTreeNode
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.open() {{{1
|
||||
function! s:TreeFileNode.open(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
let opener = g:NERDTreeOpener.New(self.path, opts)
|
||||
call opener.open(self)
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.openSplit() {{{1
|
||||
"Open this node in a new window
|
||||
function! s:TreeFileNode.openSplit()
|
||||
call nerdtree#deprecated('TreeFileNode.openSplit', 'is deprecated, use .open() instead.')
|
||||
call self.open({'where': 'h'})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.openVSplit() {{{1
|
||||
"Open this node in a new vertical window
|
||||
function! s:TreeFileNode.openVSplit()
|
||||
call nerdtree#deprecated('TreeFileNode.openVSplit', 'is deprecated, use .open() instead.')
|
||||
call self.open({'where': 'v'})
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.openInNewTab(options) {{{1
|
||||
function! s:TreeFileNode.openInNewTab(options)
|
||||
echomsg 'TreeFileNode.openInNewTab is deprecated'
|
||||
call self.open(extend({'where': 't'}, a:options))
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.putCursorHere(isJump, recurseUpward){{{1
|
||||
"Places the cursor on the line number this node is rendered on
|
||||
"
|
||||
"Args:
|
||||
"isJump: 1 if this cursor movement should be counted as a jump by vim
|
||||
"recurseUpward: try to put the cursor on the parent if the this node isnt
|
||||
"visible
|
||||
function! s:TreeFileNode.putCursorHere(isJump, recurseUpward)
|
||||
let ln = self.getLineNum()
|
||||
if ln != -1
|
||||
if a:isJump
|
||||
mark '
|
||||
endif
|
||||
call cursor(ln, col("."))
|
||||
else
|
||||
if a:recurseUpward
|
||||
let node = self
|
||||
while node != {} && node.getLineNum() ==# -1
|
||||
let node = node.parent
|
||||
call node.open()
|
||||
endwhile
|
||||
call nerdtree#renderView()
|
||||
call node.putCursorHere(a:isJump, 0)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.refresh() {{{1
|
||||
function! s:TreeFileNode.refresh()
|
||||
call self.path.refresh()
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.rename() {{{1
|
||||
"Calls the rename method for this nodes path obj
|
||||
function! s:TreeFileNode.rename(newName)
|
||||
let newName = substitute(a:newName, '\(\\\|\/\)$', '', '')
|
||||
call self.path.rename(newName)
|
||||
call self.parent.removeChild(self)
|
||||
|
||||
let parentPath = self.path.getParent()
|
||||
let newParent = b:NERDTreeRoot.findNode(parentPath)
|
||||
|
||||
if newParent != {}
|
||||
call newParent.createChild(self.path, 1)
|
||||
call newParent.refresh()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: TreeFileNode.renderToString {{{1
|
||||
"returns a string representation for this tree to be rendered in the view
|
||||
function! s:TreeFileNode.renderToString()
|
||||
return self._renderToString(0, 0, [], self.getChildCount() ==# 1)
|
||||
endfunction
|
||||
|
||||
"Args:
|
||||
"depth: the current depth in the tree for this call
|
||||
"drawText: 1 if we should actually draw the line for this node (if 0 then the
|
||||
"child nodes are rendered only)
|
||||
"vertMap: a binary array that indicates whether a vertical bar should be draw
|
||||
"for each depth in the tree
|
||||
"isLastChild:true if this curNode is the last child of its parent
|
||||
function! s:TreeFileNode._renderToString(depth, drawText, vertMap, isLastChild)
|
||||
let output = ""
|
||||
if a:drawText ==# 1
|
||||
|
||||
let treeParts = ''
|
||||
|
||||
"get all the leading spaces and vertical tree parts for this line
|
||||
if a:depth > 1
|
||||
for j in a:vertMap[0:-2]
|
||||
if g:NERDTreeDirArrows
|
||||
let treeParts = treeParts . ' '
|
||||
else
|
||||
if j ==# 1
|
||||
let treeParts = treeParts . '| '
|
||||
else
|
||||
let treeParts = treeParts . ' '
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
"get the last vertical tree part for this line which will be different
|
||||
"if this node is the last child of its parent
|
||||
if !g:NERDTreeDirArrows
|
||||
if a:isLastChild
|
||||
let treeParts = treeParts . '`'
|
||||
else
|
||||
let treeParts = treeParts . '|'
|
||||
endif
|
||||
endif
|
||||
|
||||
"smack the appropriate dir/file symbol on the line before the file/dir
|
||||
"name itself
|
||||
if self.path.isDirectory
|
||||
if self.isOpen
|
||||
if g:NERDTreeDirArrows
|
||||
let treeParts = treeParts . '▾ '
|
||||
else
|
||||
let treeParts = treeParts . '~'
|
||||
endif
|
||||
else
|
||||
if g:NERDTreeDirArrows
|
||||
let treeParts = treeParts . '▸ '
|
||||
else
|
||||
let treeParts = treeParts . '+'
|
||||
endif
|
||||
endif
|
||||
else
|
||||
if g:NERDTreeDirArrows
|
||||
let treeParts = treeParts . ' '
|
||||
else
|
||||
let treeParts = treeParts . '-'
|
||||
endif
|
||||
endif
|
||||
let line = treeParts . self.displayString()
|
||||
|
||||
let output = output . line . "\n"
|
||||
endif
|
||||
|
||||
"if the node is an open dir, draw its children
|
||||
if self.path.isDirectory ==# 1 && self.isOpen ==# 1
|
||||
|
||||
let childNodesToDraw = self.getVisibleChildren()
|
||||
if len(childNodesToDraw) > 0
|
||||
|
||||
"draw all the nodes children except the last
|
||||
let lastIndx = len(childNodesToDraw)-1
|
||||
if lastIndx > 0
|
||||
for i in childNodesToDraw[0:lastIndx-1]
|
||||
let output = output . i._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 1), 0)
|
||||
endfor
|
||||
endif
|
||||
|
||||
"draw the last child, indicating that it IS the last
|
||||
let output = output . childNodesToDraw[lastIndx]._renderToString(a:depth + 1, 1, add(copy(a:vertMap), 0), 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
return output
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,41 +0,0 @@
|
|||
" ============================================================================
|
||||
" File: exec_menuitem.vim
|
||||
" Description: plugin for NERD Tree that provides an execute file menu item
|
||||
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
|
||||
" Last Change: 22 July, 2009
|
||||
" License: This program is free software. It comes without any warranty,
|
||||
" to the extent permitted by applicable law. You can redistribute
|
||||
" it and/or modify it under the terms of the Do What The Fuck You
|
||||
" Want To Public License, Version 2, as published by Sam Hocevar.
|
||||
" See http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
"
|
||||
" ============================================================================
|
||||
if exists("g:loaded_nerdtree_exec_menuitem")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_nerdtree_exec_menuitem = 1
|
||||
|
||||
call NERDTreeAddMenuItem({
|
||||
\ 'text': '(!)Execute file',
|
||||
\ 'shortcut': '!',
|
||||
\ 'callback': 'NERDTreeExecFile',
|
||||
\ 'isActiveCallback': 'NERDTreeExecFileActive' })
|
||||
|
||||
function! NERDTreeExecFileActive()
|
||||
let node = g:NERDTreeFileNode.GetSelected()
|
||||
return !node.path.isDirectory && node.path.isExecutable
|
||||
endfunction
|
||||
|
||||
function! NERDTreeExecFile()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
echo "==========================================================\n"
|
||||
echo "Complete the command to execute (add arguments etc):\n"
|
||||
let cmd = treenode.path.str({'escape': 1})
|
||||
let cmd = input(':!', cmd . ' ')
|
||||
|
||||
if cmd != ''
|
||||
exec ':!' . cmd
|
||||
else
|
||||
echo "Aborted"
|
||||
endif
|
||||
endfunction
|
|
@ -1,262 +0,0 @@
|
|||
" ============================================================================
|
||||
" File: fs_menu.vim
|
||||
" Description: plugin for the NERD Tree that provides a file system menu
|
||||
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
|
||||
" Last Change: 17 July, 2009
|
||||
" License: This program is free software. It comes without any warranty,
|
||||
" to the extent permitted by applicable law. You can redistribute
|
||||
" it and/or modify it under the terms of the Do What The Fuck You
|
||||
" Want To Public License, Version 2, as published by Sam Hocevar.
|
||||
" See http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
"
|
||||
" ============================================================================
|
||||
if exists("g:loaded_nerdtree_fs_menu")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_nerdtree_fs_menu = 1
|
||||
|
||||
"Automatically delete the buffer after deleting or renaming a file
|
||||
if !exists("g:NERDTreeAutoDeleteBuffer")
|
||||
let g:NERDTreeAutoDeleteBuffer = 0
|
||||
endif
|
||||
|
||||
call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'})
|
||||
call NERDTreeAddMenuItem({'text': '(m)ove the current node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'})
|
||||
call NERDTreeAddMenuItem({'text': '(d)elete the current node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'})
|
||||
|
||||
if has("gui_mac") || has("gui_macvim")
|
||||
call NERDTreeAddMenuItem({'text': '(r)eveal in Finder the current node', 'shortcut': 'r', 'callback': 'NERDTreeRevealInFinder'})
|
||||
call NERDTreeAddMenuItem({'text': '(o)pen the current node with system editor', 'shortcut': 'o', 'callback': 'NERDTreeExecuteFile'})
|
||||
call NERDTreeAddMenuItem({'text': '(q)uicklook the current node', 'shortcut': 'q', 'callback': 'NERDTreeQuickLook'})
|
||||
endif
|
||||
|
||||
if g:NERDTreePath.CopyingSupported()
|
||||
call NERDTreeAddMenuItem({'text': '(c)opy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'})
|
||||
endif
|
||||
|
||||
"FUNCTION: s:echo(msg){{{1
|
||||
function! s:echo(msg)
|
||||
redraw
|
||||
echomsg "NERDTree: " . a:msg
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:echoWarning(msg){{{1
|
||||
function! s:echoWarning(msg)
|
||||
echohl warningmsg
|
||||
call s:echo(a:msg)
|
||||
echohl normal
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1
|
||||
"prints out the given msg and, if the user responds by pushing 'y' then the
|
||||
"buffer with the given bufnum is deleted
|
||||
"
|
||||
"Args:
|
||||
"bufnum: the buffer that may be deleted
|
||||
"msg: a message that will be echoed to the user asking them if they wish to
|
||||
" del the buffer
|
||||
function! s:promptToDelBuffer(bufnum, msg)
|
||||
echo a:msg
|
||||
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
|
||||
" 1. ensure that all windows which display the just deleted filename
|
||||
" now display an empty buffer (so a layout is preserved).
|
||||
" Is not it better to close single tabs with this file only ?
|
||||
let s:originalTabNumber = tabpagenr()
|
||||
let s:originalWindowNumber = winnr()
|
||||
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':enew! ' | endif"
|
||||
exec "tabnext " . s:originalTabNumber
|
||||
exec s:originalWindowNumber . "wincmd w"
|
||||
" 3. We don't need a previous buffer anymore
|
||||
exec "bwipeout! " . a:bufnum
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"FUNCTION: s:promptToRenameBuffer(bufnum, msg){{{1
|
||||
"prints out the given msg and, if the user responds by pushing 'y' then the
|
||||
"buffer with the given bufnum is replaced with a new one
|
||||
"
|
||||
"Args:
|
||||
"bufnum: the buffer that may be deleted
|
||||
"msg: a message that will be echoed to the user asking them if they wish to
|
||||
" del the buffer
|
||||
function! s:promptToRenameBuffer(bufnum, msg, newFileName)
|
||||
echo a:msg
|
||||
if g:NERDTreeAutoDeleteBuffer || nr2char(getchar()) ==# 'y'
|
||||
" 1. ensure that a new buffer is loaded
|
||||
exec "badd " . a:newFileName
|
||||
" 2. ensure that all windows which display the just deleted filename
|
||||
" display a buffer for a new filename.
|
||||
let s:originalTabNumber = tabpagenr()
|
||||
let s:originalWindowNumber = winnr()
|
||||
exec "tabdo windo if winbufnr(0) == " . a:bufnum . " | exec ':e! " . a:newFileName . "' | endif"
|
||||
exec "tabnext " . s:originalTabNumber
|
||||
exec s:originalWindowNumber . "wincmd w"
|
||||
" 3. We don't need a previous buffer anymore
|
||||
exec "bwipeout! " . a:bufnum
|
||||
endif
|
||||
endfunction
|
||||
"FUNCTION: NERDTreeAddNode(){{{1
|
||||
function! NERDTreeAddNode()
|
||||
let curDirNode = g:NERDTreeDirNode.GetSelected()
|
||||
|
||||
let newNodeName = input("Add a childnode\n".
|
||||
\ "==========================================================\n".
|
||||
\ "Enter the dir/file name to be created. Dirs end with a '/'\n" .
|
||||
\ "", curDirNode.path.str() . g:NERDTreePath.Slash(), "file")
|
||||
|
||||
if newNodeName ==# ''
|
||||
call s:echo("Node Creation Aborted.")
|
||||
return
|
||||
endif
|
||||
|
||||
try
|
||||
let newPath = g:NERDTreePath.Create(newNodeName)
|
||||
let parentNode = b:NERDTreeRoot.findNode(newPath.getParent())
|
||||
|
||||
let newTreeNode = g:NERDTreeFileNode.New(newPath)
|
||||
if parentNode.isOpen || !empty(parentNode.children)
|
||||
call parentNode.addChild(newTreeNode, 1)
|
||||
call NERDTreeRender()
|
||||
call newTreeNode.putCursorHere(1, 0)
|
||||
endif
|
||||
catch /^NERDTree/
|
||||
call s:echoWarning("Node Not Created.")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"FUNCTION: NERDTreeMoveNode(){{{1
|
||||
function! NERDTreeMoveNode()
|
||||
let curNode = g:NERDTreeFileNode.GetSelected()
|
||||
let newNodePath = input("Rename the current node\n" .
|
||||
\ "==========================================================\n" .
|
||||
\ "Enter the new path for the node: \n" .
|
||||
\ "", curNode.path.str(), "file")
|
||||
|
||||
if newNodePath ==# ''
|
||||
call s:echo("Node Renaming Aborted.")
|
||||
return
|
||||
endif
|
||||
|
||||
try
|
||||
let bufnum = bufnr(curNode.path.str())
|
||||
|
||||
call curNode.rename(newNodePath)
|
||||
call NERDTreeRender()
|
||||
|
||||
"if the node is open in a buffer, ask the user if they want to
|
||||
"close that buffer
|
||||
if bufnum != -1
|
||||
let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Replace this buffer with a new file? (yN)"
|
||||
call s:promptToRenameBuffer(bufnum, prompt, newNodePath)
|
||||
endif
|
||||
|
||||
call curNode.putCursorHere(1, 0)
|
||||
|
||||
redraw
|
||||
catch /^NERDTree/
|
||||
call s:echoWarning("Node Not Renamed.")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeDeleteNode() {{{1
|
||||
function! NERDTreeDeleteNode()
|
||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
||||
let confirmed = 0
|
||||
|
||||
if currentNode.path.isDirectory
|
||||
let choice =input("Delete the current node\n" .
|
||||
\ "==========================================================\n" .
|
||||
\ "STOP! To delete this entire directory, type 'yes'\n" .
|
||||
\ "" . currentNode.path.str() . ": ")
|
||||
let confirmed = choice ==# 'yes'
|
||||
else
|
||||
echo "Delete the current node\n" .
|
||||
\ "==========================================================\n".
|
||||
\ "Are you sure you wish to delete the node:\n" .
|
||||
\ "" . currentNode.path.str() . " (yN):"
|
||||
let choice = nr2char(getchar())
|
||||
let confirmed = choice ==# 'y'
|
||||
endif
|
||||
|
||||
|
||||
if confirmed
|
||||
try
|
||||
call currentNode.delete()
|
||||
call NERDTreeRender()
|
||||
|
||||
"if the node is open in a buffer, ask the user if they want to
|
||||
"close that buffer
|
||||
let bufnum = bufnr(currentNode.path.str())
|
||||
if buflisted(bufnum)
|
||||
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
|
||||
call s:promptToDelBuffer(bufnum, prompt)
|
||||
endif
|
||||
|
||||
redraw
|
||||
catch /^NERDTree/
|
||||
call s:echoWarning("Could not remove node")
|
||||
endtry
|
||||
else
|
||||
call s:echo("delete aborted")
|
||||
endif
|
||||
|
||||
endfunction
|
||||
|
||||
" FUNCTION: NERDTreeCopyNode() {{{1
|
||||
function! NERDTreeCopyNode()
|
||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
||||
let newNodePath = input("Copy the current node\n" .
|
||||
\ "==========================================================\n" .
|
||||
\ "Enter the new path to copy the node to: \n" .
|
||||
\ "", currentNode.path.str(), "file")
|
||||
|
||||
if newNodePath != ""
|
||||
"strip trailing slash
|
||||
let newNodePath = substitute(newNodePath, '\/$', '', '')
|
||||
|
||||
let confirmed = 1
|
||||
if currentNode.path.copyingWillOverwrite(newNodePath)
|
||||
call s:echo("Warning: copying may overwrite files! Continue? (yN)")
|
||||
let choice = nr2char(getchar())
|
||||
let confirmed = choice ==# 'y'
|
||||
endif
|
||||
|
||||
if confirmed
|
||||
try
|
||||
let newNode = currentNode.copy(newNodePath)
|
||||
if !empty(newNode)
|
||||
call NERDTreeRender()
|
||||
call newNode.putCursorHere(0, 0)
|
||||
endif
|
||||
catch /^NERDTree/
|
||||
call s:echoWarning("Could not copy node")
|
||||
endtry
|
||||
endif
|
||||
else
|
||||
call s:echo("Copy aborted.")
|
||||
endif
|
||||
redraw
|
||||
endfunction
|
||||
|
||||
function! NERDTreeQuickLook()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
if treenode != {}
|
||||
call system("qlmanage -p 2>/dev/null '" . treenode.path.str() . "'")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! NERDTreeRevealInFinder()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
if treenode != {}
|
||||
let x = system("open -R '" . treenode.path.str() . "'")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! NERDTreeExecuteFile()
|
||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
||||
if treenode != {}
|
||||
let x = system("open '" . treenode.path.str() . "'")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,210 +0,0 @@
|
|||
" ============================================================================
|
||||
" File: NERD_tree.vim
|
||||
" Description: vim global plugin that provides a nice tree explorer
|
||||
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
|
||||
" Last Change: 28 December, 2011
|
||||
" License: This program is free software. It comes without any warranty,
|
||||
" to the extent permitted by applicable law. You can redistribute
|
||||
" it and/or modify it under the terms of the Do What The Fuck You
|
||||
" Want To Public License, Version 2, as published by Sam Hocevar.
|
||||
" See http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
"
|
||||
" ============================================================================
|
||||
"
|
||||
" SECTION: Script init stuff {{{1
|
||||
"============================================================
|
||||
if exists("loaded_nerd_tree")
|
||||
finish
|
||||
endif
|
||||
if v:version < 700
|
||||
echoerr "NERDTree: this plugin requires vim >= 7. DOWNLOAD IT! You'll thank me later!"
|
||||
finish
|
||||
endif
|
||||
let loaded_nerd_tree = 1
|
||||
|
||||
"for line continuation - i.e dont want C in &cpo
|
||||
let s:old_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
"Function: s:initVariable() function {{{2
|
||||
"This function is used to initialise a given variable to a given value. The
|
||||
"variable is only initialised if it does not exist prior
|
||||
"
|
||||
"Args:
|
||||
"var: the name of the var to be initialised
|
||||
"value: the value to initialise var to
|
||||
"
|
||||
"Returns:
|
||||
"1 if the var is set, 0 otherwise
|
||||
function! s:initVariable(var, value)
|
||||
if !exists(a:var)
|
||||
exec 'let ' . a:var . ' = ' . "'" . substitute(a:value, "'", "''", "g") . "'"
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"SECTION: Init variable calls and other random constants {{{2
|
||||
call s:initVariable("g:NERDChristmasTree", 1)
|
||||
call s:initVariable("g:NERDTreeAutoCenter", 1)
|
||||
call s:initVariable("g:NERDTreeAutoCenterThreshold", 3)
|
||||
call s:initVariable("g:NERDTreeCaseSensitiveSort", 0)
|
||||
call s:initVariable("g:NERDTreeChDirMode", 0)
|
||||
call s:initVariable("g:NERDTreeMinimalUI", 0)
|
||||
if !exists("g:NERDTreeIgnore")
|
||||
let g:NERDTreeIgnore = ['\~$']
|
||||
endif
|
||||
call s:initVariable("g:NERDTreeBookmarksFile", expand('$HOME') . '/.NERDTreeBookmarks')
|
||||
call s:initVariable("g:NERDTreeHighlightCursorline", 1)
|
||||
call s:initVariable("g:NERDTreeHijackNetrw", 1)
|
||||
call s:initVariable("g:NERDTreeMouseMode", 1)
|
||||
call s:initVariable("g:NERDTreeNotificationThreshold", 100)
|
||||
call s:initVariable("g:NERDTreeQuitOnOpen", 0)
|
||||
call s:initVariable("g:NERDTreeShowBookmarks", 0)
|
||||
call s:initVariable("g:NERDTreeShowFiles", 1)
|
||||
call s:initVariable("g:NERDTreeShowHidden", 0)
|
||||
call s:initVariable("g:NERDTreeShowLineNumbers", 0)
|
||||
call s:initVariable("g:NERDTreeSortDirs", 1)
|
||||
call s:initVariable("g:NERDTreeDirArrows", !nerdtree#runningWindows())
|
||||
call s:initVariable("g:NERDTreeCasadeOpenSingleChildDir", 1)
|
||||
|
||||
if !exists("g:NERDTreeSortOrder")
|
||||
let g:NERDTreeSortOrder = ['\/$', '*', '\.swp$', '\.bak$', '\~$']
|
||||
else
|
||||
"if there isnt a * in the sort sequence then add one
|
||||
if count(g:NERDTreeSortOrder, '*') < 1
|
||||
call add(g:NERDTreeSortOrder, '*')
|
||||
endif
|
||||
endif
|
||||
|
||||
if !exists('g:NERDTreeStatusline')
|
||||
|
||||
"the exists() crap here is a hack to stop vim spazzing out when
|
||||
"loading a session that was created with an open nerd tree. It spazzes
|
||||
"because it doesnt store b:NERDTreeRoot (its a b: var, and its a hash)
|
||||
let g:NERDTreeStatusline = "%{exists('b:NERDTreeRoot')?b:NERDTreeRoot.path.str():''}"
|
||||
|
||||
endif
|
||||
call s:initVariable("g:NERDTreeWinPos", "left")
|
||||
call s:initVariable("g:NERDTreeWinSize", 31)
|
||||
|
||||
"init the shell commands that will be used to copy nodes, and remove dir trees
|
||||
"
|
||||
"Note: the space after the command is important
|
||||
if nerdtree#runningWindows()
|
||||
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rmdir /s /q ')
|
||||
else
|
||||
call s:initVariable("g:NERDTreeRemoveDirCmd", 'rm -rf ')
|
||||
call s:initVariable("g:NERDTreeCopyCmd", 'cp -r ')
|
||||
endif
|
||||
|
||||
|
||||
"SECTION: Init variable calls for key mappings {{{2
|
||||
call s:initVariable("g:NERDTreeMapActivateNode", "o")
|
||||
call s:initVariable("g:NERDTreeMapChangeRoot", "C")
|
||||
call s:initVariable("g:NERDTreeMapChdir", "cd")
|
||||
call s:initVariable("g:NERDTreeMapCloseChildren", "X")
|
||||
call s:initVariable("g:NERDTreeMapCloseDir", "x")
|
||||
call s:initVariable("g:NERDTreeMapDeleteBookmark", "D")
|
||||
call s:initVariable("g:NERDTreeMapMenu", "m")
|
||||
call s:initVariable("g:NERDTreeMapHelp", "?")
|
||||
call s:initVariable("g:NERDTreeMapJumpFirstChild", "K")
|
||||
call s:initVariable("g:NERDTreeMapJumpLastChild", "J")
|
||||
call s:initVariable("g:NERDTreeMapJumpNextSibling", "<C-j>")
|
||||
call s:initVariable("g:NERDTreeMapJumpParent", "p")
|
||||
call s:initVariable("g:NERDTreeMapJumpPrevSibling", "<C-k>")
|
||||
call s:initVariable("g:NERDTreeMapJumpRoot", "P")
|
||||
call s:initVariable("g:NERDTreeMapOpenExpl", "e")
|
||||
call s:initVariable("g:NERDTreeMapOpenInTab", "t")
|
||||
call s:initVariable("g:NERDTreeMapOpenInTabSilent", "T")
|
||||
call s:initVariable("g:NERDTreeMapOpenRecursively", "O")
|
||||
call s:initVariable("g:NERDTreeMapOpenSplit", "i")
|
||||
call s:initVariable("g:NERDTreeMapOpenVSplit", "s")
|
||||
call s:initVariable("g:NERDTreeMapPreview", "g" . NERDTreeMapActivateNode)
|
||||
call s:initVariable("g:NERDTreeMapPreviewSplit", "g" . NERDTreeMapOpenSplit)
|
||||
call s:initVariable("g:NERDTreeMapPreviewVSplit", "g" . NERDTreeMapOpenVSplit)
|
||||
call s:initVariable("g:NERDTreeMapQuit", "q")
|
||||
call s:initVariable("g:NERDTreeMapRefresh", "r")
|
||||
call s:initVariable("g:NERDTreeMapRefreshRoot", "R")
|
||||
call s:initVariable("g:NERDTreeMapToggleBookmarks", "B")
|
||||
call s:initVariable("g:NERDTreeMapToggleFiles", "F")
|
||||
call s:initVariable("g:NERDTreeMapToggleFilters", "f")
|
||||
call s:initVariable("g:NERDTreeMapToggleHidden", "I")
|
||||
call s:initVariable("g:NERDTreeMapToggleZoom", "A")
|
||||
call s:initVariable("g:NERDTreeMapUpdir", "u")
|
||||
call s:initVariable("g:NERDTreeMapUpdirKeepOpen", "U")
|
||||
call s:initVariable("g:NERDTreeMapCWD", "CD")
|
||||
|
||||
"SECTION: Load class files{{{2
|
||||
call nerdtree#loadClassFiles()
|
||||
|
||||
" SECTION: Commands {{{1
|
||||
"============================================================
|
||||
"init the command that users start the nerd tree with
|
||||
command! -n=? -complete=dir -bar NERDTree :call g:NERDTreeCreator.CreatePrimary('<args>')
|
||||
command! -n=? -complete=dir -bar NERDTreeToggle :call g:NERDTreeCreator.TogglePrimary('<args>')
|
||||
command! -n=0 -bar NERDTreeClose :call nerdtree#closeTreeIfOpen()
|
||||
command! -n=1 -complete=customlist,nerdtree#completeBookmarks -bar NERDTreeFromBookmark call g:NERDTreeCreator.CreatePrimary('<args>')
|
||||
command! -n=0 -bar NERDTreeMirror call g:NERDTreeCreator.CreateMirror()
|
||||
command! -n=0 -bar NERDTreeFind call nerdtree#findAndRevealPath()
|
||||
command! -n=0 -bar NERDTreeFocus call NERDTreeFocus()
|
||||
command! -n=0 -bar NERDTreeCWD call NERDTreeCWD()
|
||||
" SECTION: Auto commands {{{1
|
||||
"============================================================
|
||||
augroup NERDTree
|
||||
"Save the cursor position whenever we close the nerd tree
|
||||
exec "autocmd BufWinLeave ". g:NERDTreeCreator.BufNamePrefix() ."* call nerdtree#saveScreenState()"
|
||||
|
||||
"disallow insert mode in the NERDTree
|
||||
exec "autocmd BufEnter ". g:NERDTreeCreator.BufNamePrefix() ."* stopinsert"
|
||||
augroup END
|
||||
|
||||
if g:NERDTreeHijackNetrw
|
||||
augroup NERDTreeHijackNetrw
|
||||
autocmd VimEnter * silent! autocmd! FileExplorer
|
||||
au BufEnter,VimEnter * call nerdtree#checkForBrowse(expand("<amatch>"))
|
||||
augroup END
|
||||
endif
|
||||
|
||||
" SECTION: Public API {{{1
|
||||
"============================================================
|
||||
function! NERDTreeAddMenuItem(options)
|
||||
call g:NERDTreeMenuItem.Create(a:options)
|
||||
endfunction
|
||||
|
||||
function! NERDTreeAddMenuSeparator(...)
|
||||
let opts = a:0 ? a:1 : {}
|
||||
call g:NERDTreeMenuItem.CreateSeparator(opts)
|
||||
endfunction
|
||||
|
||||
function! NERDTreeAddSubmenu(options)
|
||||
return g:NERDTreeMenuItem.Create(a:options)
|
||||
endfunction
|
||||
|
||||
function! NERDTreeAddKeyMap(options)
|
||||
call g:NERDTreeKeyMap.Create(a:options)
|
||||
endfunction
|
||||
|
||||
function! NERDTreeRender()
|
||||
call nerdtree#renderView()
|
||||
endfunction
|
||||
|
||||
function! NERDTreeFocus()
|
||||
if nerdtree#isTreeOpen()
|
||||
call nerdtree#putCursorInTreeWin()
|
||||
else
|
||||
call g:NERDTreeCreator.TogglePrimary("")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! NERDTreeCWD()
|
||||
call NERDTreeFocus()
|
||||
call nerdtree#chRootCwd()
|
||||
endfunction
|
||||
" SECTION: Post Source Actions {{{1
|
||||
call nerdtree#postSourceActions()
|
||||
|
||||
"reset &cpo back to users setting
|
||||
let &cpo = s:old_cpo
|
||||
|
||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
@ -1,88 +0,0 @@
|
|||
let s:tree_up_dir_line = '.. (up a dir)'
|
||||
"NERDTreeFlags are syntax items that should be invisible, but give clues as to
|
||||
"how things should be highlighted
|
||||
syn match NERDTreeFlag #\~#
|
||||
syn match NERDTreeFlag #\[RO\]#
|
||||
|
||||
"highlighting for the .. (up dir) line at the top of the tree
|
||||
execute "syn match NERDTreeUp #\\V". s:tree_up_dir_line ."#"
|
||||
|
||||
"highlighting for the ~/+ symbols for the directory nodes
|
||||
syn match NERDTreeClosable #\~\<#
|
||||
syn match NERDTreeClosable #\~\.#
|
||||
syn match NERDTreeOpenable #+\<#
|
||||
syn match NERDTreeOpenable #+\.#he=e-1
|
||||
|
||||
"highlighting for the tree structural parts
|
||||
syn match NERDTreePart #|#
|
||||
syn match NERDTreePart #`#
|
||||
syn match NERDTreePartFile #[|`]-#hs=s+1 contains=NERDTreePart
|
||||
|
||||
"quickhelp syntax elements
|
||||
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*:#hs=s+2,he=e-1
|
||||
syn match NERDTreeHelpKey #" \{1,2\}[^ ]*,#hs=s+2,he=e-1
|
||||
syn match NERDTreeHelpTitle #" .*\~#hs=s+2,he=e-1 contains=NERDTreeFlag
|
||||
syn match NERDTreeToggleOn #".*(on)#hs=e-2,he=e-1 contains=NERDTreeHelpKey
|
||||
syn match NERDTreeToggleOff #".*(off)#hs=e-3,he=e-1 contains=NERDTreeHelpKey
|
||||
syn match NERDTreeHelpCommand #" :.\{-}\>#hs=s+3
|
||||
syn match NERDTreeHelp #^".*# contains=NERDTreeHelpKey,NERDTreeHelpTitle,NERDTreeFlag,NERDTreeToggleOff,NERDTreeToggleOn,NERDTreeHelpCommand
|
||||
|
||||
"highlighting for readonly files
|
||||
syn match NERDTreeRO #.*\[RO\]#hs=s+2 contains=NERDTreeFlag,NERDTreeBookmark,NERDTreePart,NERDTreePartFile
|
||||
|
||||
"highlighting for sym links
|
||||
syn match NERDTreeLink #[^-| `].* -> # contains=NERDTreeBookmark,NERDTreeOpenable,NERDTreeClosable,NERDTreeDirSlash
|
||||
|
||||
"highlighing for directory nodes and file nodes
|
||||
syn match NERDTreeDirSlash #/#
|
||||
syn match NERDTreeDir #[^-| `].*/# contains=NERDTreeLink,NERDTreeDirSlash,NERDTreeOpenable,NERDTreeClosable
|
||||
syn match NERDTreeExecFile #[|` ].*\*\($\| \)# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark
|
||||
syn match NERDTreeFile #|-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
|
||||
syn match NERDTreeFile #`-.*# contains=NERDTreeLink,NERDTreePart,NERDTreeRO,NERDTreePartFile,NERDTreeBookmark,NERDTreeExecFile
|
||||
syn match NERDTreeCWD #^[</].*$#
|
||||
|
||||
"highlighting for bookmarks
|
||||
syn match NERDTreeBookmark # {.*}#hs=s+1
|
||||
|
||||
"highlighting for the bookmarks table
|
||||
syn match NERDTreeBookmarksLeader #^>#
|
||||
syn match NERDTreeBookmarksHeader #^>-\+Bookmarks-\+$# contains=NERDTreeBookmarksLeader
|
||||
syn match NERDTreeBookmarkName #^>.\{-} #he=e-1 contains=NERDTreeBookmarksLeader
|
||||
syn match NERDTreeBookmark #^>.*$# contains=NERDTreeBookmarksLeader,NERDTreeBookmarkName,NERDTreeBookmarksHeader
|
||||
|
||||
if exists("g:NERDChristmasTree") && g:NERDChristmasTree
|
||||
hi def link NERDTreePart Special
|
||||
hi def link NERDTreePartFile Type
|
||||
hi def link NERDTreeFile Normal
|
||||
hi def link NERDTreeExecFile Title
|
||||
hi def link NERDTreeDirSlash Identifier
|
||||
hi def link NERDTreeClosable Type
|
||||
else
|
||||
hi def link NERDTreePart Normal
|
||||
hi def link NERDTreePartFile Normal
|
||||
hi def link NERDTreeFile Normal
|
||||
hi def link NERDTreeClosable Title
|
||||
endif
|
||||
|
||||
hi def link NERDTreeBookmarksHeader statement
|
||||
hi def link NERDTreeBookmarksLeader ignore
|
||||
hi def link NERDTreeBookmarkName Identifier
|
||||
hi def link NERDTreeBookmark normal
|
||||
|
||||
hi def link NERDTreeHelp String
|
||||
hi def link NERDTreeHelpKey Identifier
|
||||
hi def link NERDTreeHelpCommand Identifier
|
||||
hi def link NERDTreeHelpTitle Macro
|
||||
hi def link NERDTreeToggleOn Question
|
||||
hi def link NERDTreeToggleOff WarningMsg
|
||||
|
||||
hi def link NERDTreeDir Directory
|
||||
hi def link NERDTreeUp Directory
|
||||
hi def link NERDTreeCWD Statement
|
||||
hi def link NERDTreeLink Macro
|
||||
hi def link NERDTreeOpenable Title
|
||||
hi def link NERDTreeFlag ignore
|
||||
hi def link NERDTreeRO WarningMsg
|
||||
hi def link NERDTreeBookmark Statement
|
||||
|
||||
hi def link NERDTreeCurrentNode Search
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 53f319728a57caed6c7db0304b218d662a67981f
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 616daceb735771ed27535abe8a6e4907320f1e82
|
1
vim/bundle/vim-bundler/.gitignore
vendored
1
vim/bundle/vim-bundler/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/doc/tags
|
|
@ -1,2 +0,0 @@
|
|||
See the contribution guidelines for
|
||||
[rails.vim](https://github.com/tpope/vim-rails/blob/HEAD/CONTRIBUTING.markdown).
|
|
@ -1,55 +0,0 @@
|
|||
# bundler.vim
|
||||
|
||||
This is a lightweight bag of Vim goodies for
|
||||
[Bundler](http://gembundler.com), best accompanied by
|
||||
[rake.vim](https://github.com/tpope/vim-rake) and/or
|
||||
[rails.vim](https://github.com/tpope/vim-rails). Features:
|
||||
|
||||
* `:Bundle`, which wraps `bundle`.
|
||||
* An internalized version of `bundle open`: `:Bopen` (and `:Bsplit`,
|
||||
`:Btabedit`, etc.).
|
||||
* `'path'` and `'tags'` are automatically altered to include all gems
|
||||
from your bundle. (Generate those tags with
|
||||
[gem-ctags](https://github.com/tpope/gem-ctags)!)
|
||||
* Highlight Bundler keywords in `Gemfile`.
|
||||
* Support for `gf` in `Gemfile.lock`, plus syntax highlighting that
|
||||
distinguishes between installed and missing gems.
|
||||
|
||||
## Installation
|
||||
|
||||
If you don't have a preferred installation method, I recommend
|
||||
installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and
|
||||
then simply copy and paste:
|
||||
|
||||
cd ~/.vim/bundle
|
||||
git clone git://github.com/tpope/vim-bundler.git
|
||||
|
||||
Once help tags have been generated, you can view the manual with
|
||||
`:help bundler`.
|
||||
|
||||
## FAQ
|
||||
|
||||
> I installed the plugin and started Vim. Why don't any of the commands
|
||||
> exist?
|
||||
|
||||
This plugin cares about the current file, not the current working
|
||||
directory. Edit a file that's covered by a `Gemfile`.
|
||||
|
||||
> I opened a new tab. Why don't any of the commands exist?
|
||||
|
||||
This plugin cares about the current file, not the current working
|
||||
directory. Edit a file that's covered by a `Gemfile`.
|
||||
|
||||
## Self-Promotion
|
||||
|
||||
Like bundler.vim? Follow the repository on
|
||||
[GitHub](https://github.com/tpope/vim-bundler) and vote for it on
|
||||
[vim.org](http://www.vim.org/scripts/script.php?script_id=4280). And if
|
||||
you're feeling especially charitable, follow [tpope](http://tpo.pe/) on
|
||||
[Twitter](http://twitter.com/tpope) and
|
||||
[GitHub](https://github.com/tpope).
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
|
||||
See `:help license`.
|
|
@ -1,26 +0,0 @@
|
|||
" Vim compiler file
|
||||
|
||||
if exists("current_compiler")
|
||||
finish
|
||||
endif
|
||||
let current_compiler = "bundler"
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo-=C
|
||||
|
||||
CompilerSet makeprg=bundle
|
||||
|
||||
CompilerSet errorformat=
|
||||
\%+E%f:%l:\ parse\ error,
|
||||
\%W%f:%l:\ warning:\ %m,
|
||||
\%E%f:%l:in\ %*[^:]:\ %m,
|
||||
\%E%f:%l:\ %m,
|
||||
\%-C%\tfrom\ %f:%l:in\ %.%#,
|
||||
\%-Z%\tfrom\ %f:%l,
|
||||
\%-Z%p^,
|
||||
\%-G%.%#
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: sw=2:
|
|
@ -1,68 +0,0 @@
|
|||
*bundler.txt* Support for Ruby's Bundler
|
||||
|
||||
Author: Tim Pope <http://tpo.pe/>
|
||||
License: Same terms as Vim itself (see |license|)
|
||||
|
||||
This plugin is only available if 'compatible' is not set.
|
||||
|
||||
INTRODUCTION *bundler*
|
||||
|
||||
This lightweight companion to rails.vim and rake.vim provides support for
|
||||
Bundler. In addition to the below commands, it also syntax highlights
|
||||
Gemfile and Gemfile.lock, and alters 'path' and 'tags' to include bundled
|
||||
gems. I recommend gem-ctags for generating tags for your gems.
|
||||
|
||||
COMMANDS *bundler-commands*
|
||||
|
||||
*bundler-:Bundle*
|
||||
:Bundle[!] [args] Invoke `bundle` via |:make|.
|
||||
|
||||
|
||||
*bundler-:Bopen*
|
||||
:Bopen[!] [gem] With no argument, edits the Gemfile. Otherwise,
|
||||
effectively does a `bundle open` of a gem inside of
|
||||
Vim, including an |:lcd| to the gem's root directory.
|
||||
Add ! to discard the current buffer's changes.
|
||||
|
||||
*bundler-:Bedit*
|
||||
:Bedit[!] [gem] Like |:Bopen|, but don't |:lcd| afterwards.
|
||||
|
||||
*bundler-:Bsplit*
|
||||
:Bsplit[!] [gem] Like |:Bopen|, but horizontally split. Add ! to
|
||||
suppress the |:lcd|.
|
||||
|
||||
*bundler-:Bvsplit*
|
||||
:Bvsplit[!] [gem] Like |:Bopen|, but vertically split. Add ! to
|
||||
suppress the |:lcd|.
|
||||
|
||||
*bundler-:Btabedit*
|
||||
:Btabedit[!] [gem] Like |:Bopen|, but use a new tab. Add ! to
|
||||
suppress the |:lcd|.
|
||||
|
||||
*bundler-:Bpedit*
|
||||
:Bpedit[!] [gem] Like |:Bopen|, but use a preview window. Add ! to
|
||||
suppress the |:lcd|.
|
||||
|
||||
API *bundler-api*
|
||||
|
||||
Use bundler#project(root) to retrieve an object for the project at the given
|
||||
root path. If no path is given, the current buffer's project root is used.
|
||||
An empty object is returned if no project is found. Use |empty()| to check
|
||||
for that.
|
||||
|
||||
On the bundler#project() object, versions() returns a dictionary mapping
|
||||
between gem names and their locked versions, paths() returns a dictionary
|
||||
mapping between gem names and their installation path (omitting gems which
|
||||
aren't installed), and has(gem) returns true if the given gem name is in the
|
||||
bundle (regardless of whether or not it is installed).
|
||||
|
||||
The original data structures are returned for performance reasons. Do not
|
||||
mutate.
|
||||
|
||||
ABOUT *bundler-about*
|
||||
|
||||
Grab the latest version or report a bug on GitHub:
|
||||
|
||||
http://github.com/tpope/vim-bundler
|
||||
|
||||
vim:tw=78:et:ft=help:norl:
|
|
@ -1,581 +0,0 @@
|
|||
" bundler.vim - Support for Ruby's Bundler
|
||||
" Maintainer: Tim Pope <http://tpo.pe/>
|
||||
" Version: 2.0
|
||||
|
||||
if exists('g:loaded_bundler') || &cp || v:version < 700
|
||||
finish
|
||||
endif
|
||||
let g:loaded_bundler = 1
|
||||
|
||||
" Utility {{{1
|
||||
|
||||
function! s:function(name) abort
|
||||
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
|
||||
endfunction
|
||||
|
||||
function! s:sub(str,pat,rep) abort
|
||||
return substitute(a:str,'\v\C'.a:pat,a:rep,'')
|
||||
endfunction
|
||||
|
||||
function! s:gsub(str,pat,rep) abort
|
||||
return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
|
||||
endfunction
|
||||
|
||||
function! s:shellesc(arg) abort
|
||||
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
|
||||
return a:arg
|
||||
else
|
||||
return shellescape(a:arg)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:fnameescape(file) abort
|
||||
if exists('*fnameescape')
|
||||
return fnameescape(a:file)
|
||||
else
|
||||
return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:shellslash(path)
|
||||
if exists('+shellslash') && !&shellslash
|
||||
return s:gsub(a:path,'\\','/')
|
||||
else
|
||||
return a:path
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:completion_filter(results,A)
|
||||
let results = sort(copy(a:results))
|
||||
call filter(results,'v:val !~# "\\~$"')
|
||||
let filtered = filter(copy(results),'v:val[0:strlen(a:A)-1] ==# a:A')
|
||||
if !empty(filtered) | return filtered | endif
|
||||
let regex = s:gsub(a:A,'[^/:]','[&].*')
|
||||
let filtered = filter(copy(results),'v:val =~# "^".regex')
|
||||
if !empty(filtered) | return filtered | endif
|
||||
let filtered = filter(copy(results),'"/".v:val =~# "[/:]".regex')
|
||||
if !empty(filtered) | return filtered | endif
|
||||
let regex = s:gsub(a:A,'.','[&].*')
|
||||
let filtered = filter(copy(results),'"/".v:val =~# regex')
|
||||
return filtered
|
||||
endfunction
|
||||
|
||||
function! s:throw(string) abort
|
||||
let v:errmsg = 'bundler: '.a:string
|
||||
throw v:errmsg
|
||||
endfunction
|
||||
|
||||
function! s:warn(str)
|
||||
echohl WarningMsg
|
||||
echomsg a:str
|
||||
echohl None
|
||||
let v:warningmsg = a:str
|
||||
endfunction
|
||||
|
||||
function! s:add_methods(namespace, method_names) abort
|
||||
for name in a:method_names
|
||||
let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
let s:commands = []
|
||||
function! s:command(definition) abort
|
||||
let s:commands += [a:definition]
|
||||
endfunction
|
||||
|
||||
function! s:define_commands()
|
||||
for command in s:commands
|
||||
exe 'command! -buffer '.command
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
augroup bundler_utility
|
||||
autocmd!
|
||||
autocmd User Bundler call s:define_commands()
|
||||
augroup END
|
||||
|
||||
let s:abstract_prototype = {}
|
||||
|
||||
" }}}1
|
||||
" Syntax highlighting {{{1
|
||||
|
||||
function! s:syntaxfile()
|
||||
syntax keyword rubyGemfileMethod gemspec gem source path git group platforms env ruby
|
||||
hi def link rubyGemfileMethod Function
|
||||
endfunction
|
||||
|
||||
function! s:syntaxlock()
|
||||
setlocal iskeyword+=-,.
|
||||
syn match gemfilelockHeading '^[[:upper:]]\+$'
|
||||
syn match gemfilelockKey '^\s\+\zs\S\+:'he=e-1 skipwhite nextgroup=gemfilelockRevision
|
||||
syn match gemfilelockKey 'remote:'he=e-1 skipwhite nextgroup=gemfilelockRemote
|
||||
syn match gemfilelockRemote '\S\+' contained
|
||||
syn match gemfilelockRevision '[[:alnum:]._-]\+$' contained
|
||||
syn match gemfilelockGem '^\s\+\zs[[:alnum:]._-]\+\%([ !]\|$\)\@=' contains=gemfilelockFound,gemfilelockMissing skipwhite nextgroup=gemfilelockVersions,gemfilelockBang
|
||||
syn match gemfilelockVersions '([^()]*)' contained contains=gemfilelockVersion
|
||||
syn match gemfilelockVersion '[^,()]*' contained
|
||||
syn match gemfilelockBang '!' contained
|
||||
if !empty(bundler#project())
|
||||
exe 'syn match gemfilelockFound "\<\%(bundler\|' . join(keys(s:project().paths()), '\|') . '\)\>" contained'
|
||||
exe 'syn match gemfilelockMissing "\<\%(' . join(keys(filter(s:project().versions(), '!has_key(s:project().paths(), v:key)')), '\|') . '\)\>" contained'
|
||||
else
|
||||
exe 'syn match gemfilelockFound "\<\%(\S*\)\>" contained'
|
||||
endif
|
||||
syn match gemfilelockHeading '^PLATFORMS$' nextgroup=gemfilelockPlatform skipnl skipwhite
|
||||
syn match gemfilelockPlatform '^ \zs[[:alnum:]._-]\+$' contained nextgroup=gemfilelockPlatform skipnl skipwhite
|
||||
|
||||
hi def link gemfilelockHeading PreProc
|
||||
hi def link gemfilelockPlatform Typedef
|
||||
hi def link gemfilelockKey Identifier
|
||||
hi def link gemfilelockRemote String
|
||||
hi def link gemfilelockRevision Number
|
||||
hi def link gemfilelockFound Statement
|
||||
hi def link gemfilelockMissing Error
|
||||
hi def link gemfilelockVersion Type
|
||||
hi def link gemfilelockBang Special
|
||||
endfunction
|
||||
|
||||
function! s:setuplock()
|
||||
nnoremap <silent><buffer> gf :Bopen <C-R><C-F><CR>
|
||||
nnoremap <silent><buffer> <C-W>f :Bsplit <C-R><C-F><CR>
|
||||
nnoremap <silent><buffer> <C-W><C-F> :Bsplit <C-R><C-F><CR>
|
||||
nnoremap <silent><buffer> <C-W>gf :Btabedit <C-R><C-F><CR>
|
||||
endfunction
|
||||
|
||||
augroup bundler_syntax
|
||||
autocmd!
|
||||
autocmd BufNewFile,BufRead */.bundle/config set filetype=yaml
|
||||
autocmd BufNewFile,BufRead Gemfile set filetype=ruby
|
||||
autocmd Syntax ruby if expand('<afile>:t') ==? 'gemfile' | call s:syntaxfile() | endif
|
||||
autocmd BufNewFile,BufRead [Gg]emfile.lock setf gemfilelock
|
||||
autocmd FileType gemfilelock set suffixesadd=.rb
|
||||
autocmd Syntax gemfilelock call s:syntaxlock()
|
||||
autocmd FileType gemfilelock call s:setuplock()
|
||||
autocmd User Rails/Gemfile.lock call s:setuplock()
|
||||
augroup END
|
||||
|
||||
" }}}1
|
||||
" Initialization {{{1
|
||||
|
||||
function! s:FindBundlerRoot(path) abort
|
||||
let path = s:shellslash(a:path)
|
||||
let fn = fnamemodify(path,':s?[\/]$??')
|
||||
let ofn = ""
|
||||
let nfn = fn
|
||||
while fn != ofn
|
||||
if filereadable(fn.'/Gemfile')
|
||||
return s:sub(simplify(fnamemodify(fn,':p')),'[\\/]$','')
|
||||
endif
|
||||
let ofn = fn
|
||||
let fn = fnamemodify(ofn,':h')
|
||||
endwhile
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:Detect(path)
|
||||
if !exists('b:bundler_root')
|
||||
let dir = s:FindBundlerRoot(a:path)
|
||||
if dir != ''
|
||||
let b:bundler_root = dir
|
||||
endif
|
||||
endif
|
||||
if exists('b:bundler_root')
|
||||
silent doautocmd User Bundler
|
||||
endif
|
||||
endfunction
|
||||
|
||||
augroup bundler
|
||||
autocmd!
|
||||
autocmd FileType * call s:Detect(expand('<afile>:p'))
|
||||
autocmd BufNewFile,BufReadPost *
|
||||
\ if empty(&filetype) |
|
||||
\ call s:Detect(expand('<afile>:p')) |
|
||||
\ endif
|
||||
autocmd VimEnter * if expand('<amatch>')==''|call s:Detect(getcwd())|endif
|
||||
augroup END
|
||||
|
||||
" }}}1
|
||||
" Project {{{1
|
||||
|
||||
let s:project_prototype = {}
|
||||
let s:projects = {}
|
||||
|
||||
function! bundler#project(...) abort
|
||||
let dir = a:0 ? a:1 : (exists('b:bundler_root') && b:bundler_root !=# '' ? b:bundler_root : s:FindBundlerRoot(expand('%:p')))
|
||||
if dir !=# ''
|
||||
if has_key(s:projects,dir)
|
||||
let project = get(s:projects,dir)
|
||||
else
|
||||
let project = {'root': dir}
|
||||
let s:projects[dir] = project
|
||||
endif
|
||||
return extend(extend(project,s:project_prototype,'keep'),s:abstract_prototype,'keep')
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! s:project(...) abort
|
||||
let project = a:0 ? bundler#project(a:1) : bundler#project()
|
||||
if empty(project)
|
||||
call s:throw('not a Bundler project: '.(a:0 ? a:1 : expand('%')))
|
||||
else
|
||||
return project
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:project_path(...) dict abort
|
||||
return join([self.root]+a:000,'/')
|
||||
endfunction
|
||||
|
||||
call s:add_methods('project',['path'])
|
||||
|
||||
function! s:project_locked() dict abort
|
||||
let lock_file = self.path('Gemfile.lock')
|
||||
let time = getftime(lock_file)
|
||||
if time != -1 && time != get(self,'_lock_time',-1)
|
||||
let self._locked = {'git': [], 'gem': [], 'path': []}
|
||||
let self._versions = {}
|
||||
|
||||
for line in readfile(lock_file)
|
||||
if line =~# '^\S'
|
||||
let properties = {'versions': {}}
|
||||
if has_key(self._locked, tolower(line))
|
||||
call extend(self._locked[tolower(line)], [properties])
|
||||
endif
|
||||
elseif line =~# '^ \w\+: '
|
||||
let properties[matchstr(line, '\w\+')] = matchstr(line, ': \zs.*')
|
||||
elseif line =~# '^ [a-zA-Z0-9._-]\+\s\+(\d\+'
|
||||
let name = split(line, ' ')[0]
|
||||
let ver = substitute(line, '.*(\|).*', '', 'g')
|
||||
let properties.versions[name] = ver
|
||||
let self._versions[name] = ver
|
||||
endif
|
||||
endfor
|
||||
let self._lock_time = time
|
||||
endif
|
||||
return get(self, '_locked', {})
|
||||
endfunction
|
||||
|
||||
function! s:project_paths(...) dict abort
|
||||
call self.locked()
|
||||
let time = get(self, '_lock_time', -1)
|
||||
if a:0 && a:1 ==# 'refresh' || time != -1 && time != get(self, '_path_time', -1)
|
||||
let paths = {}
|
||||
|
||||
let chdir = exists("*haslocaldir") && haslocaldir() ? "lchdir" : "chdir"
|
||||
let cwd = getcwd()
|
||||
|
||||
" Explicitly setting $PATH means /etc/zshenv on OS X can't touch it.
|
||||
if executable('env')
|
||||
let prefix = 'env PATH='.s:shellesc($PATH).' '
|
||||
else
|
||||
let prefix = ''
|
||||
endif
|
||||
|
||||
let gem_paths = []
|
||||
if exists('$GEM_PATH')
|
||||
let gem_paths = split($GEM_PATH, has('win32') ? ';' : ':')
|
||||
else
|
||||
try
|
||||
exe chdir s:fnameescape(self.path())
|
||||
let gem_paths = split(system(prefix.'ruby -rubygems -e "print Gem.path.join(%(;))"'), ';')
|
||||
finally
|
||||
exe chdir s:fnameescape(cwd)
|
||||
endtry
|
||||
endif
|
||||
|
||||
let abi_version = matchstr(get(gem_paths, 0, '1.9.1'), '[0-9.]\+$')
|
||||
for config in [expand('~/.bundle/config'), self.path('.bundle/config')]
|
||||
if filereadable(config)
|
||||
let body = join(readfile(config), "\n")
|
||||
let bundle_path = matchstr(body, "\\C\\<BUNDLE_PATH: \\zs[^\n]*")
|
||||
if !empty(bundle_path)
|
||||
if body =~# '\C\<BUNDLE_DISABLE_SHARED_GEMS:'
|
||||
let gem_paths = [self.path(bundle_path, 'ruby', abi_version)]
|
||||
else
|
||||
let gem_paths = [self.path(bundle_path)]
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
|
||||
for source in self._locked.git
|
||||
for [name, ver] in items(source.versions)
|
||||
for path in gem_paths
|
||||
let dir = path . '/bundler/gems/' . matchstr(source.remote, '.*/\zs.\{-\}\ze\%(\.git\)\=$') . '-' . source.revision[0:11]
|
||||
if isdirectory(dir)
|
||||
let files = split(glob(dir . '/*/' . name . '.gemspec'), "\n")
|
||||
if empty(files)
|
||||
let paths[name] = dir
|
||||
else
|
||||
let paths[name] = files[0][0 : -10-strlen(name)]
|
||||
endif
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
|
||||
for source in self._locked.path
|
||||
for [name, ver] in items(source.versions)
|
||||
if source.remote !~# '^/'
|
||||
let local = simplify(self.path(source.remote))
|
||||
else
|
||||
let local = source.remote
|
||||
endif
|
||||
let files = split(glob(local . '/*/' . name . '.gemspec'), "\n")
|
||||
if empty(files)
|
||||
let paths[name] = local
|
||||
else
|
||||
let paths[name] = files[0][0 : -10-strlen(name)]
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
|
||||
for source in self._locked.gem
|
||||
for [name, ver] in items(source.versions)
|
||||
for path in gem_paths
|
||||
let dir = path . '/gems/' . name . '-' . ver
|
||||
if isdirectory(dir)
|
||||
let paths[name] = dir
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
if !has_key(paths, name)
|
||||
for path in gem_paths
|
||||
let dir = glob(path . '/gems/' . name . '-' . ver . '-*')
|
||||
if isdirectory(dir)
|
||||
let paths[name] = dir
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
|
||||
let self._path_time = time
|
||||
let self._paths = paths
|
||||
let self._sorted = sort(values(paths))
|
||||
let index = index(self._sorted, self.path())
|
||||
if index > 0
|
||||
call insert(self._sorted, remove(self._sorted,index))
|
||||
endif
|
||||
call self.alter_buffer_paths()
|
||||
return paths
|
||||
endif
|
||||
return get(self,'_paths',{})
|
||||
endfunction
|
||||
|
||||
function! s:project_sorted() dict abort
|
||||
call self.paths()
|
||||
return get(self, '_sorted', [])
|
||||
endfunction
|
||||
|
||||
function! s:project_gems() dict abort
|
||||
return self.paths()
|
||||
endfunction
|
||||
|
||||
function! s:project_versions() dict abort
|
||||
call self.locked()
|
||||
return get(self, '_versions', {})
|
||||
endfunction
|
||||
|
||||
function! s:project_has(gem) dict abort
|
||||
call self.locked()
|
||||
return has_key(self.versions(), a:gem)
|
||||
endfunction
|
||||
|
||||
call s:add_methods('project', ['locked', 'gems', 'paths', 'sorted', 'versions', 'has'])
|
||||
|
||||
" }}}1
|
||||
" Buffer {{{1
|
||||
|
||||
let s:buffer_prototype = {}
|
||||
|
||||
function! s:buffer(...) abort
|
||||
let buffer = {'#': bufnr(a:0 ? a:1 : '%')}
|
||||
let g:buffer = buffer
|
||||
call extend(extend(buffer,s:buffer_prototype,'keep'),s:abstract_prototype,'keep')
|
||||
if buffer.getvar('bundler_root') !=# ''
|
||||
return buffer
|
||||
endif
|
||||
call s:throw('not a Bundler project: '.(a:0 ? a:1 : expand('%')))
|
||||
endfunction
|
||||
|
||||
function! bundler#buffer(...) abort
|
||||
return s:buffer(a:0 ? a:1 : '%')
|
||||
endfunction
|
||||
|
||||
function! s:buffer_getvar(var) dict abort
|
||||
return getbufvar(self['#'],a:var)
|
||||
endfunction
|
||||
|
||||
function! s:buffer_setvar(var,value) dict abort
|
||||
return setbufvar(self['#'],a:var,a:value)
|
||||
endfunction
|
||||
|
||||
function! s:buffer_project() dict abort
|
||||
return s:project(self.getvar('bundler_root'))
|
||||
endfunction
|
||||
|
||||
call s:add_methods('buffer',['getvar','setvar','project'])
|
||||
|
||||
" }}}1
|
||||
" Bundle {{{1
|
||||
|
||||
function! s:push_chdir()
|
||||
if !exists("s:command_stack") | let s:command_stack = [] | endif
|
||||
let chdir = exists("*haslocaldir") && haslocaldir() ? "lchdir " : "chdir "
|
||||
call add(s:command_stack,chdir.s:fnameescape(getcwd()))
|
||||
exe chdir.'`=s:project().path()`'
|
||||
endfunction
|
||||
|
||||
function! s:pop_command()
|
||||
if exists("s:command_stack") && len(s:command_stack) > 0
|
||||
exe remove(s:command_stack,-1)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Bundle(bang,arg)
|
||||
let old_makeprg = &l:makeprg
|
||||
let old_errorformat = &l:errorformat
|
||||
let old_compiler = get(b:, 'current_compiler', '')
|
||||
try
|
||||
compiler bundler
|
||||
execute 'make! '.a:arg
|
||||
if a:bang ==# ''
|
||||
return 'if !empty(getqflist()) | cfirst | endif'
|
||||
else
|
||||
return ''
|
||||
endif
|
||||
finally
|
||||
let &l:errorformat = old_errorformat
|
||||
let &l:makeprg = old_makeprg
|
||||
let b:current_compiler = old_compiler
|
||||
if empty(b:current_compiler)
|
||||
unlet b:current_compiler
|
||||
endif
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:BundleComplete(A,L,P)
|
||||
if a:L =~# '^\S\+\s\+\%(show\|update\) '
|
||||
return s:completion_filter(keys(s:project().paths()),a:A)
|
||||
endif
|
||||
return s:completion_filter(['install','update','exec','package','config','check','list','show','outdated','console','viz','benchmark'],a:A)
|
||||
endfunction
|
||||
|
||||
function! s:SetupMake() abort
|
||||
compiler bundler
|
||||
endfunction
|
||||
|
||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:BundleComplete Bundle :execute s:Bundle('<bang>',<q-args>)")
|
||||
|
||||
augroup bundler_make
|
||||
autocmd FileType gemfilelock call s:SetupMake()
|
||||
autocmd FileType ruby
|
||||
\ if expand('<afile>:t') ==? 'gemfile' |
|
||||
\ call s:SetupMake() |
|
||||
\ endif
|
||||
autocmd QuickFixCmdPre make,lmake
|
||||
\ if &makeprg =~# '^bundle' && exists('b:bundler_root') |
|
||||
\ call s:push_chdir() |
|
||||
\ endif
|
||||
autocmd QuickFixCmdPost make,lmake
|
||||
\ if &makeprg =~# '^bundle' && exists('b:bundler_root') |
|
||||
\ call s:pop_command() |
|
||||
\ call s:project().paths("refresh") |
|
||||
\ endif
|
||||
augroup END
|
||||
|
||||
" }}}1
|
||||
" Bopen {{{1
|
||||
|
||||
function! s:Open(cmd,gem,lcd)
|
||||
if a:gem ==# '' && a:lcd
|
||||
return a:cmd.' `=bundler#buffer().project().path("Gemfile")`'
|
||||
elseif a:gem ==# ''
|
||||
return a:cmd.' `=bundler#buffer().project().path("Gemfile.lock")`'
|
||||
else
|
||||
if !has_key(s:project().paths(), a:gem)
|
||||
call s:project().paths('refresh')
|
||||
endif
|
||||
if !has_key(s:project().paths(), a:gem)
|
||||
if has_key(s:project().versions(), a:gem)
|
||||
let v:errmsg = "Gem \"".a:gem."\" is in bundle but not installed"
|
||||
else
|
||||
let v:errmsg = "Gem \"".a:gem."\" is not in bundle"
|
||||
endif
|
||||
return 'echoerr v:errmsg'
|
||||
endif
|
||||
let path = fnameescape(bundler#buffer().project().paths()[a:gem])
|
||||
let exec = a:cmd.' '.path
|
||||
if a:cmd =~# '^pedit' && a:lcd
|
||||
let exec .= '|wincmd P|lcd '.path.'|wincmd p'
|
||||
elseif a:lcd
|
||||
let exec .= '|lcd '.path
|
||||
endif
|
||||
return exec
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:OpenComplete(A,L,P)
|
||||
return s:completion_filter(keys(s:project().paths()),a:A)
|
||||
endfunction
|
||||
|
||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bopen :execute s:Open('edit<bang>',<q-args>,1)")
|
||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bedit :execute s:Open('edit<bang>',<q-args>,0)")
|
||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bsplit :execute s:Open('split',<q-args>,<bang>1)")
|
||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bvsplit :execute s:Open('vsplit',<q-args>,<bang>1)")
|
||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Btabedit :execute s:Open('tabedit',<q-args>,<bang>1)")
|
||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:OpenComplete Bpedit :execute s:Open('pedit',<q-args>,<bang>1)")
|
||||
|
||||
" }}}1
|
||||
" Paths {{{1
|
||||
|
||||
function! s:build_path_option(paths,suffix) abort
|
||||
return join(map(copy(a:paths),'",".escape(s:shellslash(v:val."/".a:suffix),", ")'),'')
|
||||
endfunction
|
||||
|
||||
function! s:buffer_alter_paths() dict abort
|
||||
if self.getvar('&suffixesadd') =~# '\.rb\>'
|
||||
let new = self.project().sorted()
|
||||
let old = type(self.getvar('bundler_paths')) == type([]) ? self.getvar('bundler_paths') : []
|
||||
for [option, suffix] in [['path', 'lib'], ['tags', 'tags']]
|
||||
let value = self.getvar('&'.option)
|
||||
if !empty(old)
|
||||
let drop = s:build_path_option(old,suffix)
|
||||
let index = stridx(value,drop)
|
||||
if index > 0
|
||||
let value = value[0:index-1] . value[index+strlen(drop):-1]
|
||||
endif
|
||||
endif
|
||||
call self.setvar('&'.option,value.s:build_path_option(new,suffix))
|
||||
endfor
|
||||
call self.setvar('bundler_paths',new)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
call s:add_methods('buffer',['alter_paths'])
|
||||
|
||||
function! s:project_alter_buffer_paths() dict abort
|
||||
for bufnr in range(1,bufnr('$'))
|
||||
if getbufvar(bufnr,'bundler_root') ==# self.path()
|
||||
let vim_parsing_quirk = s:buffer(bufnr).alter_paths()
|
||||
endif
|
||||
if getbufvar(bufnr, '&syntax') ==# 'gemfilelock'
|
||||
call setbufvar(bufnr, '&syntax', 'gemfilelock')
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
call s:add_methods('project',['alter_buffer_paths'])
|
||||
|
||||
augroup bundler_path
|
||||
autocmd!
|
||||
autocmd User Bundler call s:buffer().alter_paths()
|
||||
augroup END
|
||||
|
||||
" }}}1
|
||||
|
||||
" vim:set sw=2 sts=2:
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 1ef18a10512fe0f84bb2c412b38e613c331a7b55
|
|
@ -1 +0,0 @@
|
|||
Subproject commit aac76b431b1ed726a7f3e2608bdfc02cce76ec8e
|
|
@ -1 +0,0 @@
|
|||
Subproject commit bdf57577b8c1f3677da788f93490209688870e58
|
|
@ -1 +0,0 @@
|
|||
Subproject commit fd09aea1c0944eddd9dd6e5a22db4d52b7894490
|
|
@ -1 +0,0 @@
|
|||
Subproject commit b79c5177caac6810af07cb15e4f6db9324f1f42f
|
|
@ -1,267 +0,0 @@
|
|||
---
|
||||
Title: Solarized Colorscheme for Vim
|
||||
Description: Precision colors for machines and people
|
||||
Author: Ethan Schoonover
|
||||
Colors: light yellow
|
||||
Created: 2011 Mar 15
|
||||
Modified: 2011 Apr 16
|
||||
|
||||
---
|
||||
|
||||
Solarized Colorscheme for Vim
|
||||
=============================
|
||||
|
||||
Developed by Ethan Schoonover <es@ethanschoonover.com>
|
||||
|
||||
Visit the [Solarized homepage]
|
||||
------------------------------
|
||||
|
||||
See the [Solarized homepage] for screenshots,
|
||||
details and colorscheme versions for Vim, Mutt, popular terminal emulators and
|
||||
other applications.
|
||||
|
||||
Screenshots
|
||||
-----------
|
||||
|
||||

|
||||
|
||||
Downloads
|
||||
---------
|
||||
|
||||
If you have come across this colorscheme via the [Vim-only repository] on
|
||||
github, or the [vim.org script] page see the link above to the Solarized
|
||||
homepage or visit the main [Solarized repository].
|
||||
|
||||
The [Vim-only repository] is kept in sync with the main [Solarized repository]
|
||||
and is for installation convenience only (with [Pathogen] or [Vundle], for
|
||||
instance). Issues, bug reports, changelogs are centralized at the main
|
||||
[Solarized repository].
|
||||
|
||||
[Solarized homepage]: http://ethanschoonover.com/solarized
|
||||
[Solarized repository]: https://github.com/altercation/solarized
|
||||
[Vim-only repository]: https://github.com/altercation/vim-colors-solarized
|
||||
[vimorg-script]: http://vim.org/script
|
||||
[Pathogen]: https://github.com/tpope/vim-pathogen
|
||||
[Vundle]: https://github.com/gmarik/vundle
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
### Option 1: Manual installation
|
||||
|
||||
1. Move `solarized.vim` to your `.vim/colors` directory. After downloading the
|
||||
vim script or package:
|
||||
|
||||
$ cd vim-colors-solarized/colors
|
||||
$ mv solarized.vim ~/.vim/colors/
|
||||
|
||||
### Option 2: Pathogen installation ***(recommended)***
|
||||
|
||||
1. Download and install Tim Pope's [Pathogen].
|
||||
|
||||
2. Next, move or clone the `vim-colors-solarized` directory so that it is
|
||||
a subdirectory of the `.vim/bundle` directory.
|
||||
|
||||
a. **Clone:**
|
||||
|
||||
$ cd ~/.vim/bundle
|
||||
$ git clone git://github.com/altercation/vim-colors-solarized.git
|
||||
|
||||
b. **Move:**
|
||||
|
||||
In the parent directory of vim-colors-solarized:
|
||||
|
||||
$ mv vim-colors-solarized ~/.vim/bundle/
|
||||
|
||||
### Modify .vimrc
|
||||
|
||||
After either Option 1 or Option 2 above, put the following two lines in your
|
||||
.vimrc:
|
||||
|
||||
syntax enable
|
||||
set background=dark
|
||||
colorscheme solarized
|
||||
|
||||
or, for the light background mode of Solarized:
|
||||
|
||||
syntax enable
|
||||
set background=light
|
||||
colorscheme solarized
|
||||
|
||||
I like to have a different background in GUI and terminal modes, so I can use
|
||||
the following if-then. However, I find vim's background autodetection to be
|
||||
pretty good and, at least with MacVim, I can leave this background value
|
||||
assignment out entirely and get the same results.
|
||||
|
||||
if has('gui_running')
|
||||
set background=light
|
||||
else
|
||||
set background=dark
|
||||
endif
|
||||
|
||||
See the [Solarized homepage] for screenshots which will help you
|
||||
select either the light or dark background.
|
||||
|
||||
### IMPORTANT NOTE FOR TERMINAL USERS:
|
||||
|
||||
If you are going to use Solarized in Terminal mode (i.e. not in a GUI version
|
||||
like gvim or macvim), **please please please** consider setting your terminal
|
||||
emulator's colorscheme to used the Solarized palette. I've included palettes
|
||||
for some popular terminal emulator as well as Xdefaults in the official
|
||||
Solarized download available from [Solarized homepage]. If you use
|
||||
Solarized *without* these colors, Solarized will need to be told to degrade its
|
||||
colorscheme to a set compatible with the limited 256 terminal palette (whereas
|
||||
by using the terminal's 16 ansi color values, you can set the correct, specific
|
||||
values for the Solarized palette).
|
||||
|
||||
If you do use the custom terminal colors, solarized.vim should work out of the
|
||||
box for you. If you are using a terminal emulator that supports 256 colors and
|
||||
don't want to use the custom Solarized terminal colors, you will need to use
|
||||
the degraded 256 colorscheme. To do so, simply add the following line *before*
|
||||
the `colorschem solarized` line:
|
||||
|
||||
let g:solarized_termcolors=256
|
||||
|
||||
Again, I recommend just changing your terminal colors to Solarized values
|
||||
either manually or via one of the many terminal schemes available for import.
|
||||
|
||||
Advanced Configuration
|
||||
----------------------
|
||||
|
||||
Solarized will work out of the box with just the two lines specified above but
|
||||
does include several other options that can be set in your .vimrc file.
|
||||
|
||||
Set these in your vimrc file prior to calling the colorscheme.
|
||||
"
|
||||
option name default optional
|
||||
------------------------------------------------
|
||||
g:solarized_termcolors= 16 | 256
|
||||
g:solarized_termtrans = 0 | 1
|
||||
g:solarized_degrade = 0 | 1
|
||||
g:solarized_bold = 1 | 0
|
||||
g:solarized_underline = 1 | 0
|
||||
g:solarized_italic = 1 | 0
|
||||
g:solarized_contrast = "normal"| "high" or "low"
|
||||
g:solarized_visibility= "normal"| "high" or "low"
|
||||
------------------------------------------------
|
||||
|
||||
### Option Details
|
||||
|
||||
* g:solarized_termcolors
|
||||
|
||||
This is set to *16* by default, meaning that Solarized will attempt to use
|
||||
the standard 16 colors of your terminal emulator. You will need to set
|
||||
those colors to the correct Solarized values either manually or by
|
||||
importing one of the many colorscheme available for popular terminal
|
||||
emulators and Xdefaults.
|
||||
|
||||
* g:solarized_termtrans
|
||||
|
||||
If you use a terminal emulator with a transparent background and Solarized
|
||||
isn't displaying the background color transparently, set this to 1 and
|
||||
Solarized will use the default (transparent) background of the terminal
|
||||
emulator. *urxvt* required this in my testing; iTerm2 did not.
|
||||
|
||||
Note that on Mac OS X Terminal.app, solarized_termtrans is set to 1 by
|
||||
default as this is almost always the best option. The only exception to
|
||||
this is if the working terminfo file supports 256 colors (xterm-256color).
|
||||
|
||||
* g:solarized_degrade
|
||||
|
||||
For test purposes only; forces Solarized to use the 256 degraded color mode
|
||||
to test the approximate color values for accuracy.
|
||||
|
||||
* g:solarized_bold | g:solarized_underline | g:solarized_italic
|
||||
|
||||
If you wish to stop Solarized from displaying bold, underlined or
|
||||
italicized typefaces, simply assign a zero value to the appropriate
|
||||
variable, for example: `let g:solarized_italic=0`
|
||||
|
||||
* g:solarized_contrast
|
||||
|
||||
Stick with normal! It's been carefully tested. Setting this option to high
|
||||
or low does use the same Solarized palette but simply shifts some values up
|
||||
or down in order to expand or compress the tonal range displayed.
|
||||
|
||||
* g:solarized_visibility
|
||||
|
||||
Special characters such as trailing whitespace, tabs, newlines, when
|
||||
displayed using `:set list` can be set to one of three levels depending on
|
||||
your needs. Default value is `normal` with `high` and `low` options.
|
||||
|
||||
Toggle Background Function
|
||||
--------------------------
|
||||
|
||||
Solarized comes with a Toggle Background plugin that by default will map to
|
||||
<F5> if that mapping is available. If it is not available you will need to
|
||||
either map the function manually or change your current <F5> mapping to
|
||||
something else.
|
||||
|
||||
To set your own mapping in your .vimrc file, simply add the following line to
|
||||
support normal, insert and visual mode usage, changing the "<F5>" value to the
|
||||
key or key combination you wish to use:
|
||||
|
||||
call togglebg#map("<F5>")
|
||||
|
||||
Note that you'll want to use a single function key or equivalent if you want
|
||||
the plugin to work in all modes (normal, insert, visual).
|
||||
|
||||
Code Notes
|
||||
----------
|
||||
|
||||
Use folding to view the `solarized.vim` script with `foldmethod=marker` turned
|
||||
on.
|
||||
|
||||
I have attempted to modularize the creation of Vim colorschemes in this script
|
||||
and, while it could be refactored further, it should be a good foundation for
|
||||
the creation of any color scheme. By simply changing the sixteen values in the
|
||||
GUI section and testing in gvim (or mvim) you can rapidly prototype new
|
||||
colorschemes without diving into the weeds of line-item editing each syntax
|
||||
highlight declaration.
|
||||
|
||||
The Values
|
||||
----------
|
||||
|
||||
L\*a\*b values are canonical (White D65, Reference D50), other values are
|
||||
matched in sRGB space.
|
||||
|
||||
SOLARIZED HEX 16/8 TERMCOL XTERM/HEX L*A*B sRGB HSB
|
||||
--------- ------- ---- ------- ----------- ---------- ----------- -----------
|
||||
base03 #002b36 8/4 brblack 234 #1c1c1c 15 -12 -12 0 43 54 193 100 21
|
||||
base02 #073642 0/4 black 235 #262626 20 -12 -12 7 54 66 192 90 26
|
||||
base01 #586e75 10/7 brgreen 240 #4e4e4e 45 -07 -07 88 110 117 194 25 46
|
||||
base00 #657b83 11/7 bryellow 241 #585858 50 -07 -07 101 123 131 195 23 51
|
||||
base0 #839496 12/6 brblue 244 #808080 60 -06 -03 131 148 150 186 13 59
|
||||
base1 #93a1a1 14/4 brcyan 245 #8a8a8a 65 -05 -02 147 161 161 180 9 63
|
||||
base2 #eee8d5 7/7 white 254 #d7d7af 92 -00 10 238 232 213 44 11 93
|
||||
base3 #fdf6e3 15/7 brwhite 230 #ffffd7 97 00 10 253 246 227 44 10 99
|
||||
yellow #b58900 3/3 yellow 136 #af8700 60 10 65 181 137 0 45 100 71
|
||||
orange #cb4b16 9/3 brred 166 #d75f00 50 50 55 203 75 22 18 89 80
|
||||
red #dc322f 1/1 red 160 #d70000 50 65 45 220 50 47 1 79 86
|
||||
magenta #d33682 5/5 magenta 125 #af005f 50 65 -05 211 54 130 331 74 83
|
||||
violet #6c71c4 13/5 brmagenta 61 #5f5faf 50 15 -45 108 113 196 237 45 77
|
||||
blue #268bd2 4/4 blue 33 #0087ff 55 -10 -45 38 139 210 205 82 82
|
||||
cyan #2aa198 6/6 cyan 37 #00afaf 60 -35 -05 42 161 152 175 74 63
|
||||
green #859900 2/2 green 64 #5f8700 60 -20 65 133 153 0 68 100 60
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright (c) 2011 Ethan Schoonover
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -1,55 +0,0 @@
|
|||
" Toggle Background
|
||||
" Modified: 2011 Apr 29
|
||||
" Maintainer: Ethan Schoonover
|
||||
" License: OSI approved MIT license
|
||||
|
||||
if exists("g:loaded_togglebg")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_togglebg = 1
|
||||
|
||||
" noremap is a bit misleading here if you are unused to vim mapping.
|
||||
" in fact, there is remapping, but only of script locally defined remaps, in
|
||||
" this case <SID>TogBG. The <script> argument modifies the noremap scope in
|
||||
" this regard (and the noremenu below).
|
||||
nnoremap <unique> <script> <Plug>ToggleBackground <SID>TogBG
|
||||
inoremap <unique> <script> <Plug>ToggleBackground <ESC><SID>TogBG<ESC>a
|
||||
vnoremap <unique> <script> <Plug>ToggleBackground <ESC><SID>TogBG<ESC>gv
|
||||
nnoremenu <script> Window.Toggle\ Background <SID>TogBG
|
||||
inoremenu <script> Window.Toggle\ Background <ESC><SID>TogBG<ESC>a
|
||||
vnoremenu <script> Window.Toggle\ Background <ESC><SID>TogBG<ESC>gv
|
||||
tmenu Window.Toggle\ Background Toggle light and dark background modes
|
||||
nnoremenu <script> ToolBar.togglebg <SID>TogBG
|
||||
inoremenu <script> ToolBar.togglebg <ESC><SID>TogBG<ESC>a
|
||||
vnoremenu <script> ToolBar.togglebg <ESC><SID>TogBG<ESC>gv
|
||||
tmenu ToolBar.togglebg Toggle light and dark background modes
|
||||
noremap <SID>TogBG :call <SID>TogBG()<CR>
|
||||
|
||||
function! s:TogBG()
|
||||
let &background = ( &background == "dark"? "light" : "dark" )
|
||||
if exists("g:colors_name")
|
||||
exe "colorscheme " . g:colors_name
|
||||
endif
|
||||
endfunction
|
||||
|
||||
if !exists(":ToggleBG")
|
||||
command ToggleBG :call s:TogBG()
|
||||
endif
|
||||
|
||||
function! ToggleBackground()
|
||||
echo "Please update your ToggleBackground mapping. ':help togglebg' for information."
|
||||
endfunction
|
||||
|
||||
function! togglebg#map(mapActivation)
|
||||
try
|
||||
exe "silent! nmap <unique> ".a:mapActivation." <Plug>ToggleBackground"
|
||||
exe "silent! imap <unique> ".a:mapActivation." <Plug>ToggleBackground"
|
||||
exe "silent! vmap <unique> ".a:mapActivation." <Plug>ToggleBackground"
|
||||
finally
|
||||
return 0
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
if !exists("no_plugin_maps") && !hasmapto('<Plug>ToggleBackground')
|
||||
call togglebg#map("<F5>")
|
||||
endif
|
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -1,254 +0,0 @@
|
|||
*solarized.vim* for Vim version 7.3 or newer. Modified: 2011 May 05
|
||||
|
||||
|
||||
Solarized Vim Colorscheme by Ethan Schoonover ~
|
||||
|
||||
Solarized Colorscheme *solarized*
|
||||
*solarized-help*
|
||||
*solarized-colors*
|
||||
*solarized-colorscheme*
|
||||
*vim-colors-solarized*
|
||||
|
||||
Solarized is a carefully designed selective contrast colorscheme with dual
|
||||
light and dark modes that runs in both GUI, 256 and 16 color modes.
|
||||
|
||||
See the homepage at http://ethanschoonover.com/solarized for screenshots and
|
||||
details.
|
||||
|
||||
0. Install |solarized-install|
|
||||
1. Solarized Menu |solarized-menu|
|
||||
2. Options |solarized-options|
|
||||
3. Toggle Background |solarized-togglebg|
|
||||
4. Terminal Issues |solarized-term|
|
||||
|
||||
==============================================================================
|
||||
0. Install *solarized-install*
|
||||
|
||||
Note: I recommend using Tim Pope's pathogen plugin to install this
|
||||
colorscheme. See https://github.com/tpope/vim-pathogen . If you've installed
|
||||
pathogen properly you can install Solarized with the following commands,
|
||||
followed by the .vimrc configuration below.
|
||||
|
||||
$ cd ~/.vim/bundle
|
||||
$ git clone https://github.com/altercation/vim-colors-solarized.git
|
||||
|
||||
If you aren't using pathogen, you can use the following three steps to install
|
||||
Solarized:
|
||||
|
||||
1. Download the solarized distribution (available on the homepage above)
|
||||
and unarchive the file.
|
||||
|
||||
2. Move `solarized.vim` to your `.vim/colors` directory.
|
||||
|
||||
3. Move each of the files in each subdirectories to the corresponding .vim
|
||||
subdirectory (e.g. autoload/togglebg.vim goes into your .vim/autoload
|
||||
directory as .vim/autoload/togglebg.vim).
|
||||
|
||||
|
||||
After installation, place the following lines in your .vimrc:
|
||||
|
||||
syntax enable
|
||||
set background=dark
|
||||
colorscheme solarized
|
||||
|
||||
or, for the light background mode of Solarized:
|
||||
|
||||
syntax enable
|
||||
set background=light
|
||||
colorscheme solarized
|
||||
|
||||
==============================================================================
|
||||
1. Solarized Menu *solarized-menu*
|
||||
|
||||
Solarized makes available a menu when used in Vim GUI mode (gvim, macvim).
|
||||
This menu includes many of the options detailed below so that you can test out
|
||||
different values quickly without modifying your .vimrc file. If you wish to
|
||||
turn off this menu permanently, simply place the following line in your .vimrc
|
||||
above the "colorscheme solarized" line.
|
||||
|
||||
let g:solarized_menu=0
|
||||
|
||||
==============================================================================
|
||||
2. Toggle Background *solarized-togglebg*
|
||||
*toggle-bg* *togglebg*
|
||||
*toggle-background*
|
||||
|
||||
Solarized comes with Toggle Background, a simple plugin to switch between
|
||||
light and dark background modes and reset the colorscheme. This is most useful
|
||||
for colorschemes that support both light and dark modes and in terminals or
|
||||
gui vim windows where the background will be properly set.
|
||||
|
||||
Toggle Background can be accessed by:
|
||||
|
||||
* the Solarized menu (in Vim gui mode)
|
||||
* the Window menu (in Vim gui mode, even if the Solarized menu is off)
|
||||
* the "yin/yang" toolbar button (in Vim gui mode)
|
||||
* the default mapping of <F5>
|
||||
* custom key mapping you set in your .vimrc (see below)
|
||||
* command line via ":ToggleBG" (no quotes)
|
||||
|
||||
Toggle Background starts with a default mapping to function key <F5>. If you
|
||||
are already using this in a mapping, Toggle Background will not map itself to
|
||||
a default and you will have to map it manually in your .vimrc file, or
|
||||
remove/change your existing <F5> mapping to another value. To customize the
|
||||
keyboard mapping in your .vimrc file, use the following line, changing the
|
||||
"<F5>" value to the key or key combination you wish to use:
|
||||
|
||||
call togglebg#map("<F5>")
|
||||
|
||||
Note that you'll want to use a single function key or equivalent if you want
|
||||
the plugin to work in all modes (normal, insert, visual).
|
||||
|
||||
When using the plugin during normal, visual, or insert mode, there should be
|
||||
no interruption in workflow. However, if you activate the plugin during
|
||||
REPLACE mode, you will switch to standard insert mode (you will leave the
|
||||
overwrite replace mode).
|
||||
|
||||
==============================================================================
|
||||
3. Solarized Terminal Issues *solarized-term*
|
||||
|
||||
If you are going to use Solarized in Terminal mode (i.e. not in a GUI version
|
||||
like gvim or macvim), **please please please** consider setting your terminal
|
||||
emulator's colorscheme to used the Solarized palette. I've included palettes
|
||||
for some popular terminal emulator as well as Xdefaults in the official
|
||||
Solarized download available from the Solarized homepage listed at the top of
|
||||
this help document. If you use Solarized *without* these colors, Solarized
|
||||
will need to be told to degrade its colorscheme to a set compatible with the
|
||||
limited 256 terminal palette (whereas by using the terminal's 16 ansi color
|
||||
values, you can set the correct, specific values for the Solarized palette).
|
||||
|
||||
If you do use the custom terminal colors, solarized.vim should work out of
|
||||
the box for you. If you are using a terminal emulator that supports 256
|
||||
colors and don't want to use the custom Solarized terminal colors, you will
|
||||
need to use the degraded 256 colorscheme. To do so, simply add the following
|
||||
line *before* the `colorschem solarized` line:
|
||||
|
||||
let g:solarized_termcolors=256
|
||||
|
||||
Again, I recommend just changing your terminal colors to Solarized values
|
||||
either manually or via one of the many terminal schemes available for import.
|
||||
|
||||
==============================================================================
|
||||
4. Solarized Options *solarized-options*
|
||||
|
||||
|
||||
AUTOGENERATE OPTIONS
|
||||
|
||||
You can easily modify and experiment with Solarized display options using the
|
||||
Solarized menu when using Vim in gui mode. Once you have things set to your
|
||||
liking, you can autogenerate the current option list in a format ready for
|
||||
insertion into your .vimrc file using the Solarized menu "Autogenerate
|
||||
Options" command or at the command line with:
|
||||
|
||||
:SolarizedOptions
|
||||
|
||||
|
||||
OPTION LIST
|
||||
|
||||
Set these in your vimrc file prior to calling the colorscheme.
|
||||
|
||||
option name default optional
|
||||
------------------------------------------------
|
||||
g:solarized_termcolors= 16 | 256
|
||||
g:solarized_termtrans = 0 | 1
|
||||
g:solarized_degrade = 0 | 1
|
||||
g:solarized_bold = 1 | 0
|
||||
g:solarized_underline = 1 | 0
|
||||
g:solarized_italic = 1 | 0
|
||||
g:solarized_contrast = "normal"| "high" or "low"
|
||||
g:solarized_visibility= "normal"| "high" or "low"
|
||||
g:solarized_hitrail = 0 | 1
|
||||
g:solarized_menu = 1 | 0
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
OPTION DETAILS
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_termcolors= 256 | 16 *'solarized_termcolors'*
|
||||
------------------------------------------------
|
||||
The most important option if you are using vim in terminal (non gui) mode!
|
||||
This tells Solarized to use the 256 degraded color mode if running in a 256
|
||||
color capable terminal. Otherwise, if set to `16` it will use the terminal
|
||||
emulators colorscheme (best option as long as you've set the emulators colors
|
||||
to the Solarized palette).
|
||||
|
||||
If you are going to use Solarized in Terminal mode (i.e. not in a GUI
|
||||
version like gvim or macvim), **please please please** consider setting your
|
||||
terminal emulator's colorscheme to used the Solarized palette. I've included
|
||||
palettes for some popular terminal emulator as well as Xdefaults in the
|
||||
official Solarized download available from:
|
||||
http://ethanschoonover.com/solarized . If you use Solarized without these
|
||||
colors, Solarized will by default use an approximate set of 256 colors. It
|
||||
isn't bad looking and has been extensively tweaked, but it's still not quite
|
||||
the real thing.
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_termtrans = 0 | 1 *'solarized_termtrans'*
|
||||
------------------------------------------------
|
||||
If you use a terminal emulator with a transparent background and Solarized
|
||||
isn't displaying the background color transparently, set this to 1 and
|
||||
Solarized will use the default (transparent) background of the terminal
|
||||
emulator. *urxvt* required this in my testing; iTerm2 did not.
|
||||
|
||||
Note that on Mac OS X Terminal.app, solarized_termtrans is set to 1 by
|
||||
default as this is almost always the best option. The only exception to this
|
||||
is if the working terminfo file supports 256 colors (xterm-256color).
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_degrade = 0 | 1 *'solarized_degrade'*
|
||||
------------------------------------------------
|
||||
For test purposes only; forces Solarized to use the 256 degraded color mode
|
||||
to test the approximate color values for accuracy.
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_bold = 1 | 0 *'solarized_bold'*
|
||||
------------------------------------------------
|
||||
------------------------------------------------
|
||||
g:solarized_underline = 1 | 0 *'solarized_underline'*
|
||||
------------------------------------------------
|
||||
------------------------------------------------
|
||||
g:solarized_italic = 1 | 0 *'solarized_italic'*
|
||||
------------------------------------------------
|
||||
If you wish to stop Solarized from displaying bold, underlined or
|
||||
italicized typefaces, simply assign a zero value to the appropriate
|
||||
variable, for example: `let g:solarized_italic=0`
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_contrast = "normal"| "high" or "low" *'solarized_contrast'*
|
||||
------------------------------------------------
|
||||
Stick with normal! It's been carefully tested. Setting this option to high
|
||||
or low does use the same Solarized palette but simply shifts some values up
|
||||
or down in order to expand or compress the tonal range displayed.
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_visibility = "normal"| "high" or "low" *'solarized_visibility'*
|
||||
------------------------------------------------
|
||||
Special characters such as trailing whitespace, tabs, newlines, when
|
||||
displayed using ":set list" can be set to one of three levels depending on
|
||||
your needs.
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_hitrail = 0 | 1 *'solarized_hitrail'*
|
||||
------------------------------------------------
|
||||
Visibility can make listchar entities more visible, but if one has set
|
||||
cursorline on, these same listchar values standout somewhat less due to the
|
||||
background color of the cursorline. g:solarized_hitrail enables highlighting
|
||||
of trailing spaces (only one of the listchar types, but a particularly
|
||||
important one) while in the cursoline in a different manner in order to make
|
||||
them more visible. This may not work consistently as Solarized is using
|
||||
a pattern match than can be overridden by a more encompassing syntax-native
|
||||
match such as a comment line.
|
||||
|
||||
|
||||
------------------------------------------------
|
||||
g:solarized_menu = 1 | 0 *'solarized_menu'*
|
||||
------------------------------------------------
|
||||
Solarized includes a menu providing access to several of the above
|
||||
display related options, including contrast and visibility. This allows
|
||||
for an easy method of testing different values quickly before settling
|
||||
on a final assignment for your .vimrc. If you wish to turn off this menu,
|
||||
assign g:solarized_menu a value of 0.
|
||||
|
||||
|
||||
vim:tw=78:noet:ts=8:ft=help:norl:
|
|
@ -1,27 +0,0 @@
|
|||
'solarized_bold' solarized.txt /*'solarized_bold'*
|
||||
'solarized_contrast' solarized.txt /*'solarized_contrast'*
|
||||
'solarized_degrade' solarized.txt /*'solarized_degrade'*
|
||||
'solarized_hitrail' solarized.txt /*'solarized_hitrail'*
|
||||
'solarized_italic' solarized.txt /*'solarized_italic'*
|
||||
'solarized_menu' solarized.txt /*'solarized_menu'*
|
||||
'solarized_termcolors' solarized.txt /*'solarized_termcolors'*
|
||||
'solarized_termtrans' solarized.txt /*'solarized_termtrans'*
|
||||
'solarized_underline' solarized.txt /*'solarized_underline'*
|
||||
'solarized_visibility' solarized.txt /*'solarized_visibility'*
|
||||
before solarized.txt /*before*
|
||||
solarized solarized.txt /*solarized*
|
||||
solarized-colors solarized.txt /*solarized-colors*
|
||||
solarized-colorscheme solarized.txt /*solarized-colorscheme*
|
||||
solarized-help solarized.txt /*solarized-help*
|
||||
solarized-install solarized.txt /*solarized-install*
|
||||
solarized-menu solarized.txt /*solarized-menu*
|
||||
solarized-options solarized.txt /*solarized-options*
|
||||
solarized-term solarized.txt /*solarized-term*
|
||||
solarized-togglebg solarized.txt /*solarized-togglebg*
|
||||
solarized.vim solarized.txt /*solarized.vim*
|
||||
toggle-background solarized.txt /*toggle-background*
|
||||
toggle-bg solarized.txt /*toggle-bg*
|
||||
togglebg solarized.txt /*togglebg*
|
||||
urxvt solarized.txt /*urxvt*
|
||||
vim-colors-solarized solarized.txt /*vim-colors-solarized*
|
||||
without solarized.txt /*without*
|
|
@ -1,15 +0,0 @@
|
|||
## Vim Colorscheme 'Elrodeo'
|
||||
|
||||
This is a dark low contrast vim color scheme influenced by colors used by Chris Granger (@ibdknox) for Clojure code, e.g., on the Noir web page (webnoir.org).
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
The color scheme can be installed as a pathogen plugin, i.e., just check it out to `~/.vim/bundle`, or copy the content of `colors`to `~/.vim/colors`.
|
||||
|
||||
## Usage
|
||||
|
||||
In Vim: `:colorscheme elrodeo`.
|
|
@ -1,63 +0,0 @@
|
|||
" Vim color file
|
||||
" Name: elrodeo
|
||||
" Maintainer: Christian Müller (@chmllr)
|
||||
" Version: 1.0
|
||||
"
|
||||
" Inspired by the color scheme used by ibdknox.
|
||||
|
||||
set background=dark
|
||||
|
||||
hi clear
|
||||
if exists("syntax_on")
|
||||
syntax reset
|
||||
endif
|
||||
|
||||
let g:colors_name="elrodeo"
|
||||
|
||||
" the nexz block is copied from the wombat theme:
|
||||
" Vim >= 7.0 specific colors
|
||||
if version >= 700
|
||||
hi CursorLine guibg=#2d2d2d
|
||||
hi CursorColumn guibg=#2d2d2d
|
||||
hi MatchParen guifg=#f6f3e8 guibg=#857b6f gui=bold
|
||||
hi Pmenu guifg=#f6f3e8 guibg=#444444
|
||||
hi PmenuSel guifg=#000000 guibg=#cae682
|
||||
endif
|
||||
" General colors
|
||||
hi Normal guibg=#404040 guifg=#d0d0d0
|
||||
hi Cursor guifg=#656565 guibg=#d0d0d0
|
||||
hi NonText guifg=#808080 guibg=#404040
|
||||
hi LineNr guifg=#666666 guibg=#383838
|
||||
hi StatusLine guifg=#f6f3e8 guibg=#444444
|
||||
hi StatusLineNC guifg=#857b6f guibg=#444444
|
||||
hi VertSplit guifg=#444444 guibg=#444444
|
||||
hi Folded guibg=#384048 guifg=#a0a8b0
|
||||
hi Title guifg=#f6f3e8 guibg=NONE gui=bold
|
||||
hi Visual guifg=#f6f3e8 guibg=#444444
|
||||
hi SpecialKey guifg=#808080 guibg=#343434
|
||||
|
||||
|
||||
" Syntax highlighting
|
||||
hi Comment guifg=#677c99
|
||||
hi Operator guifg=#a080f0
|
||||
hi Todo guifg=#333333 guibg=#cccccc
|
||||
hi Constant guifg=white
|
||||
hi String guifg=#bbddff
|
||||
hi Identifier guifg=#30c080
|
||||
hi Define guifg=#30c080
|
||||
hi Function guifg=#30c080
|
||||
hi Macro guifg=#30c080
|
||||
hi Number guifg=#319899
|
||||
hi Special guifg=#30c080
|
||||
hi Conditional guifg=#30c080
|
||||
hi Boolean guifg=#99dd99
|
||||
hi Delimiter guifg=#999999
|
||||
hi Character guifg=#55d2ee
|
||||
hi Search guifg=black guibg=#30c080
|
||||
hi Visual guibg=#303030
|
||||
|
||||
" not used in Clojure (left as in wombat)
|
||||
hi Type guifg=#cae682
|
||||
hi Statement guifg=#8ac6f2
|
||||
hi Keyword guifg=#8ac6f2
|
||||
hi PreProc guifg=#e5786d
|
Binary file not shown.
Before Width: | Height: | Size: 75 KiB |
|
@ -1 +0,0 @@
|
|||
Subproject commit b27b35e401b5fa3a13f23c52a902533436c50368
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 874505e9f292767e85503573365f613d0ead3895
|
1
vim/bundle/vim-fugitive/.gitignore
vendored
1
vim/bundle/vim-fugitive/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/doc/tags
|
|
@ -1,150 +0,0 @@
|
|||
fugitive.vim
|
||||
============
|
||||
|
||||
I'm not going to lie to you; fugitive.vim may very well be the best
|
||||
Git wrapper of all time. Check out these features:
|
||||
|
||||
View any blob, tree, commit, or tag in the repository with `:Gedit` (and
|
||||
`:Gsplit`, `:Gvsplit`, `:Gtabedit`, ...). Edit a file in the index and
|
||||
write to it to stage the changes. Use `:Gdiff` to bring up the staged
|
||||
version of the file side by side with the working tree version and use
|
||||
Vim's diff handling capabilities to stage a subset of the file's
|
||||
changes.
|
||||
|
||||
Bring up the output of `git status` with `:Gstatus`. Press `-` to
|
||||
`add`/`reset` a file's changes, or `p` to `add`/`reset` `--patch` that
|
||||
mofo. And guess what `:Gcommit` does!
|
||||
|
||||
`:Gblame` brings up an interactive vertical split with `git blame`
|
||||
output. Press enter on a line to reblame the file as it stood in that
|
||||
commit, or `o` to open that commit in a split. When you're done, use
|
||||
`:Gedit` in the historic buffer to go back to the work tree version.
|
||||
|
||||
`:Gmove` does a `git mv` on a file and simultaneously renames the
|
||||
buffer. `:Gremove` does a `git rm` on a file and simultaneously deletes
|
||||
the buffer.
|
||||
|
||||
Use `:Ggrep` to search the work tree (or any arbitrary commit) with
|
||||
`git grep`, skipping over that which is not tracked in the repository.
|
||||
`:Glog` loads all previous revisions of a file into the quickfix list so
|
||||
you can iterate over them and watch the file evolve!
|
||||
|
||||
`:Gread` is a variant of `git checkout -- filename` that operates on the
|
||||
buffer rather than the filename. This means you can use `u` to undo it
|
||||
and you never get any warnings about the file changing outside Vim.
|
||||
`:Gwrite` writes to both the work tree and index versions of a file,
|
||||
making it like `git add` when called from a work tree file and like
|
||||
`git checkout` when called from the index or a blob in history.
|
||||
|
||||
Use `:Gbrowse` to open the current file on GitHub, with optional line
|
||||
range (try it in visual mode!). If your current repository isn't on
|
||||
GitHub, `git instaweb` will be spun up instead.
|
||||
|
||||
Add `%{fugitive#statusline()}` to `'statusline'` to get an indicator
|
||||
with the current branch in (surprise!) your statusline.
|
||||
|
||||
Last but not least, there's `:Git` for running any arbitrary command,
|
||||
and `Git!` to open the output of a command in a temp file.
|
||||
|
||||
Screencasts
|
||||
-----------
|
||||
|
||||
* [A complement to command line git](http://vimcasts.org/e/31)
|
||||
* [Working with the git index](http://vimcasts.org/e/32)
|
||||
* [Resolving merge conflicts with vimdiff](http://vimcasts.org/e/33)
|
||||
* [Browsing the git object database](http://vimcasts.org/e/34)
|
||||
* [Exploring the history of a git repository](http://vimcasts.org/e/35)
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
If you don't have a preferred installation method, I recommend
|
||||
installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and
|
||||
then simply copy and paste:
|
||||
|
||||
cd ~/.vim/bundle
|
||||
git clone git://github.com/tpope/vim-fugitive.git
|
||||
|
||||
Once help tags have been generated, you can view the manual with
|
||||
`:help fugitive`.
|
||||
|
||||
If your Vim version is below 7.2, I recommend also installing
|
||||
[vim-git](https://github.com/tpope/vim-git) for syntax highlighting and
|
||||
other Git niceties.
|
||||
|
||||
FAQ
|
||||
---
|
||||
|
||||
> I installed the plugin and started Vim. Why don't any of the commands
|
||||
> exist?
|
||||
|
||||
Fugitive cares about the current file, not the current working
|
||||
directory. Edit a file from the repository.
|
||||
|
||||
> I opened a new tab. Why don't any of the commands exist?
|
||||
|
||||
Fugitive cares about the current file, not the current working
|
||||
directory. Edit a file from the repository.
|
||||
|
||||
> Why is `:Gbrowse` not using the right browser?
|
||||
|
||||
`:Gbrowse` delegates to `git web--browse`, which is less than perfect
|
||||
when it comes to finding the right browser. You can tell it the correct
|
||||
browser to use with `git config --global web.browser ...`. On OS X, for
|
||||
example, you might want to set this to `open`. See `git web--browse --help`
|
||||
for details.
|
||||
|
||||
> Here's a patch that automatically opens the quickfix window after
|
||||
> `:Ggrep`.
|
||||
|
||||
This is a great example of why I recommend asking before patching.
|
||||
There are valid arguments to be made both for and against automatically
|
||||
opening the quickfix window. Whenever I have to make an arbitrary
|
||||
decision like this, I ask what Vim would do. And Vim does not open a
|
||||
quickfix window after `:grep`.
|
||||
|
||||
Luckily, it's easy to implement the desired behavior without changing
|
||||
fugitive.vim. The following autocommand will cause the quickfix window
|
||||
to open after any grep invocation:
|
||||
|
||||
autocmd QuickFixCmdPost *grep* cwindow
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Before reporting a bug, you should try stripping down your Vim
|
||||
configuration and removing other plugins. The sad nature of VimScript
|
||||
is that it is fraught with incompatibilities waiting to happen. I'm
|
||||
happy to work around them where I can, but it's up to you to isolate
|
||||
the conflict.
|
||||
|
||||
If your [commit message sucks](http://stopwritingramblingcommitmessages.com/),
|
||||
I'm not going to accept your pull request. I've explained very politely
|
||||
dozens of times that
|
||||
[my general guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
|
||||
are absolute rules on my own repositories, so I may lack the energy to
|
||||
explain it to you yet another time. And please, if I ask you to change
|
||||
something, `git commit --amend`.
|
||||
|
||||
Beyond that, don't be shy about asking before patching. What takes you
|
||||
hours might take me minutes simply because I have both domain knowledge
|
||||
and a perverse knowledge of VimScript so vast that many would consider
|
||||
it a symptom of mental illness. On the flip side, some ideas I'll
|
||||
reject no matter how good the implementation is. "Send a patch" is an
|
||||
edge case answer in my book.
|
||||
|
||||
Self-Promotion
|
||||
--------------
|
||||
|
||||
Like fugitive.vim? Follow the repository on
|
||||
[GitHub](https://github.com/tpope/vim-fugitive) and vote for it on
|
||||
[vim.org](http://www.vim.org/scripts/script.php?script_id=2975). And if
|
||||
you're feeling especially charitable, follow [tpope](http://tpo.pe/) on
|
||||
[Twitter](http://twitter.com/tpope) and
|
||||
[GitHub](https://github.com/tpope).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
|
||||
See `:help license`.
|
|
@ -1,313 +0,0 @@
|
|||
*fugitive.txt* A Git wrapper so awesome, it should be illegal
|
||||
|
||||
Author: Tim Pope <http://tpo.pe/>
|
||||
License: Same terms as Vim itself (see |license|)
|
||||
|
||||
This plugin is only available if 'compatible' is not set.
|
||||
|
||||
INTRODUCTION *fugitive*
|
||||
|
||||
Whenever you edit a file from a Git repository, a set of commands is defined
|
||||
that serve as a gateway to Git.
|
||||
|
||||
COMMANDS *fugitive-commands*
|
||||
|
||||
These commands are local to the buffers in which they work (generally, buffers
|
||||
that are part of Git repositories).
|
||||
|
||||
*fugitive-:Git*
|
||||
:Git [args] Run an arbitrary git command. Similar to :!git [args]
|
||||
but chdir to the repository tree first.
|
||||
|
||||
*fugitive-:Git!*
|
||||
:Git! [args] Like |:Git|, but capture the output into a temp file,
|
||||
and edit that temp file.
|
||||
|
||||
*fugitive-:Gcd*
|
||||
:Gcd [directory] |:cd| relative to the repository.
|
||||
|
||||
*fugitive-:Glcd*
|
||||
:Glcd [directory] |:lcd| relative to the repository.
|
||||
|
||||
*fugitive-:Gstatus*
|
||||
:Gstatus Bring up the output of git-status in the preview
|
||||
window. The following maps, which work on the cursor
|
||||
line file where sensible, are provided:
|
||||
|
||||
<C-N> next file
|
||||
<C-P> previous file
|
||||
<CR> |:Gedit|
|
||||
- |:Git| add
|
||||
- |:Git| reset (staged files)
|
||||
cA |:Gcommit| --amend --reuse-message=HEAD
|
||||
ca |:Gcommit| --amend
|
||||
cc |:Gcommit|
|
||||
cva |:Gcommit| --amend --verbose
|
||||
cvc |:Gcommit| --verbose
|
||||
D |:Gdiff|
|
||||
ds |:Gsdiff|
|
||||
dp |:Git!| diff (p for patch; use :Gw to apply)
|
||||
dp |:Git| add --intent-to-add (untracked files)
|
||||
dv |:Gvdiff|
|
||||
O |:Gtabedit|
|
||||
o |:Gsplit|
|
||||
p |:Git| add --patch
|
||||
p |:Git| reset --patch (staged files)
|
||||
q close status
|
||||
R reload status
|
||||
S |:Gvsplit|
|
||||
|
||||
*fugitive-:Gcommit*
|
||||
:Gcommit [args] A wrapper around git-commit. If there is nothing
|
||||
to commit, |:Gstatus| is called instead. Unless the
|
||||
arguments given would skip the invocation of an editor
|
||||
(e.g., -m), a split window will be used to obtain a
|
||||
commit message. Write and close that window (:wq or
|
||||
|:Gwrite|) to finish the commit. Unlike when running
|
||||
the actual git-commit command, it is possible (but
|
||||
unadvisable) to muck with the index with commands like
|
||||
git-add and git-reset while a commit message is
|
||||
pending.
|
||||
|
||||
*fugitive-:Ggrep*
|
||||
:Ggrep [args] |:grep| with git-grep as 'grepprg'.
|
||||
|
||||
*fugitive-:Glgrep*
|
||||
:Glgrep [args] |:lgrep| with git-grep as 'grepprg'.
|
||||
|
||||
*fugitive-:Glog*
|
||||
:Glog [args] Load all previous revisions of the current file into
|
||||
the quickfix list. Additional git-log arguments can
|
||||
be given (for example, --reverse). If "--" appears as
|
||||
an argument, no file specific filtering is done, and
|
||||
previous commits rather than previous file revisions
|
||||
are loaded.
|
||||
|
||||
*fugitive-:Gllog*
|
||||
:Gllog [args] Like |:Glog|, but use the location list instead of the
|
||||
quickfix list.
|
||||
|
||||
*fugitive-:Gedit* *fugitive-:Ge*
|
||||
:Gedit [revision] |:edit| a |fugitive-revision|.
|
||||
|
||||
*fugitive-:Gsplit*
|
||||
:Gsplit [revision] |:split| a |fugitive-revision|.
|
||||
|
||||
*fugitive-:Gvsplit*
|
||||
:Gvsplit [revision] |:vsplit| a |fugitive-revision|.
|
||||
|
||||
*fugitive-:Gtabedit*
|
||||
:Gtabedit [revision] |:tabedit| a |fugitive-revision|.
|
||||
|
||||
*fugitive-:Gpedit*
|
||||
:Gpedit [revision] |:pedit| a |fugitive-revision|.
|
||||
|
||||
:Gsplit! [args] *fugitive-:Gsplit!* *fugitive-:Gvsplit!*
|
||||
:Gvsplit! [args] *fugitive-:Gtabedit!* *fugitive-:Gpedit!*
|
||||
:Gtabedit! [args] Like |:Git!|, but open the resulting temp file in a
|
||||
:Gpedit! [args] split, tab, or preview window.
|
||||
|
||||
*fugitive-:Gread*
|
||||
:Gread [revision] Empty the buffer and |:read| a |fugitive-revision|.
|
||||
When the argument is omitted, this is similar to
|
||||
git-checkout on a work tree file or git-add on a stage
|
||||
file, but without writing anything to disk.
|
||||
|
||||
:{range}Gread [revision]
|
||||
|:read| in a |fugitive-revision| after {range}.
|
||||
|
||||
*fugitive-:Gread!*
|
||||
:Gread! [args] Empty the buffer and |:read| the output of a Git
|
||||
command. For example, :Gread! show HEAD:%.
|
||||
|
||||
:{range}Gread! [args] |:read| the output of a Git command after {range}.
|
||||
|
||||
*fugitive-:Gwrite*
|
||||
:Gwrite Write to the current file's path and stage the results.
|
||||
When run in a work tree file, it is effectively git
|
||||
add. Elsewhere, it is effectively git-checkout. A
|
||||
great deal of effort is expended to behave sensibly
|
||||
when the work tree or index version of the file is
|
||||
open in another buffer.
|
||||
|
||||
:Gwrite {path} You can give |:Gwrite| an explicit path of where in
|
||||
the work tree to write. You can also give a path like
|
||||
:0:foo.txt or even :0 to write to just that stage in
|
||||
the index.
|
||||
|
||||
*fugitive-:Gwq*
|
||||
:Gwq [path] Like |:Gwrite| followed by |:quit| if the write
|
||||
succeeded.
|
||||
|
||||
:Gwq! [path] Like |:Gwrite|! followed by |:quit|! if the write
|
||||
succeeded.
|
||||
|
||||
*fugitive-:Gdiff*
|
||||
:Gdiff [revision] Perform a |vimdiff| against the current file in the
|
||||
given revision. With no argument, the version in the
|
||||
index is used (which means a three-way diff during a
|
||||
merge conflict, making it a git-mergetool
|
||||
alternative). The newer of the two files is placed
|
||||
to the right. Use |do| and |dp| and write to the
|
||||
index file to simulate "git add --patch".
|
||||
|
||||
*fugitive-:Gsdiff*
|
||||
:Gsdiff [revision] Like |:Gdiff|, but split horizontally.
|
||||
|
||||
*fugitive-:Gvdiff*
|
||||
:Gvdiff [revision] Identical to |:Gdiff|. For symmetry with |:Gsdiff|.
|
||||
|
||||
*fugitive-:Gmove*
|
||||
:Gmove {destination} Wrapper around git-mv that renames the buffer
|
||||
afterward. The destination is relative to the current
|
||||
directory except when started with a /, in which case
|
||||
it is relative to the work tree. Add a ! to pass -f.
|
||||
|
||||
*fugitive-:Gremove*
|
||||
:Gremove Wrapper around git-rm that deletes the buffer
|
||||
afterward. When invoked in an index file, --cached is
|
||||
passed. Add a ! to pass -f and forcefully discard the
|
||||
buffer.
|
||||
|
||||
*fugitive-:Gblame*
|
||||
:Gblame [flags] Run git-blame on the file and open the results in a
|
||||
scroll bound vertical split. Press enter on a line to
|
||||
reblame the file as it was in that commit. You can
|
||||
give any of ltfnsewMC as flags and they will be passed
|
||||
along to git-blame. The following maps, which work on
|
||||
the cursor line commit where sensible, are provided:
|
||||
|
||||
A resize to end of author column
|
||||
C resize to end of commit column
|
||||
D resize to end of date/time column
|
||||
q close blame and return to blamed window
|
||||
gq q, then |:Gedit| to return to work tree version
|
||||
i q, then open commit
|
||||
o open commit in horizontal split
|
||||
O open commit in new tab
|
||||
- reblame at commit
|
||||
~ reblame at [count]th first grandparent
|
||||
P reblame at [count]th parent (like HEAD^[count])
|
||||
|
||||
:[range]Gblame [flags] Run git-blame on the given range.
|
||||
|
||||
*fugitive-:Gbrowse*
|
||||
:[range]Gbrowse If the remote for the current branch is on GitHub,
|
||||
open the current file, blob, tree, commit, or tag
|
||||
(with git-web--browse) on GitHub. Otherwise, open the
|
||||
current file, blob, tree, commit, or tag in
|
||||
git-instaweb (if you have issues, verify you can run
|
||||
"git instaweb" from a terminal). If a range is given,
|
||||
it is appropriately appended to the URL as an anchor.
|
||||
|
||||
To use with GitHub FI, point g:fugitive_github_domains
|
||||
at a list of domains:
|
||||
>
|
||||
let g:fugitive_github_domains = ['git.example.com']
|
||||
~
|
||||
:[range]Gbrowse! Like :Gbrowse, but put the URL on the clipboard rather
|
||||
than opening it.
|
||||
|
||||
:[range]Gbrowse {revision}
|
||||
Like :Gbrowse, but for a given |fugitive-revision|. A
|
||||
useful value here is -, which ties the URL to the
|
||||
latest commit rather than a volatile branch.
|
||||
|
||||
:[range]Gbrowse [...]@{remote}
|
||||
Force using the given remote rather than the remote
|
||||
for the current branch. The remote is used to
|
||||
determine which GitHub repository to link to.
|
||||
|
||||
MAPPINGS *fugitive-mappings*
|
||||
|
||||
These maps are available everywhere.
|
||||
|
||||
*fugitive-c_CTRL-R_CTRL-G*
|
||||
<C-R><C-G> On the command line, recall the path to the current
|
||||
object (that is, a representation of the object
|
||||
recognized by |:Gedit|).
|
||||
|
||||
*fugitive-y_CTRL-G*
|
||||
["x]y<C-G> Yank the commit SHA and path to the current object.
|
||||
|
||||
These maps are available in Git objects.
|
||||
|
||||
*fugitive-<CR>*
|
||||
<CR> Jump to the revision under the cursor.
|
||||
|
||||
*fugitive-o*
|
||||
o Jump to the revision under the cursor in a new split.
|
||||
|
||||
*fugitive-S*
|
||||
S Jump to the revision under the cursor in a new
|
||||
vertical split.
|
||||
|
||||
*fugitive-O*
|
||||
O Jump to the revision under the cursor in a new tab.
|
||||
|
||||
*fugitive--*
|
||||
- Go to the tree containing the current tree or blob.
|
||||
|
||||
*fugitive-~*
|
||||
~ Go to the current file in the [count]th first
|
||||
ancestor.
|
||||
|
||||
*fugitive-P*
|
||||
P Go to the current file in the [count]th parent.
|
||||
|
||||
*fugitive-C*
|
||||
C Go to the commit containing the current file.
|
||||
|
||||
*fugitive-a*
|
||||
a Show the current tag, commit, or tree in an alternate
|
||||
format.
|
||||
|
||||
SPECIFYING REVISIONS *fugitive-revision*
|
||||
|
||||
Fugitive revisions are similar to Git revisions as defined in the "SPECIFYING
|
||||
REVISIONS" section in the git-rev-parse man page. For commands that accept an
|
||||
optional revision, the default is the file in the index for work tree files
|
||||
and the work tree file for everything else. Example revisions follow.
|
||||
|
||||
Revision Meaning ~
|
||||
HEAD .git/HEAD
|
||||
master .git/refs/heads/master
|
||||
HEAD^{} The commit referenced by HEAD
|
||||
HEAD^ The parent of the commit referenced by HEAD
|
||||
HEAD: The tree referenced by HEAD
|
||||
/HEAD The file named HEAD in the work tree
|
||||
Makefile The file named Makefile in the work tree
|
||||
HEAD^:Makefile The file named Makefile in the parent of HEAD
|
||||
:Makefile The file named Makefile in the index (writable)
|
||||
- The current file in HEAD
|
||||
^ The current file in the previous commit
|
||||
~3 The current file 3 commits ago
|
||||
: .git/index (Same as |:Gstatus|)
|
||||
:0 The current file in the index
|
||||
:1 The current file's common ancestor during a conflict
|
||||
:2 The current file in the target branch during a conflict
|
||||
:3 The current file in the merged branch during a conflict
|
||||
:/foo The most recent commit with "foo" in the message
|
||||
|
||||
STATUSLINE *fugitive-statusline*
|
||||
|
||||
*fugitive#statusline()*
|
||||
Add %{fugitive#statusline()} to your statusline to get an indicator including
|
||||
the current branch and the currently edited file's commit. If you don't have
|
||||
a statusline, this one matches the default when 'ruler' is set:
|
||||
>
|
||||
set statusline=%<%f\ %h%m%r%{fugitive#statusline()}%=%-14.(%l,%c%V%)\ %P
|
||||
<
|
||||
*fugitive#head(...)*
|
||||
Use fugitive#head() to return the name of the current branch. If the current
|
||||
HEAD is detached, fugitive#head() will return the empty string, unless the
|
||||
optional argument is given, in which case the hash of the current commit will
|
||||
be truncated to the given number of characters.
|
||||
|
||||
ABOUT *fugitive-about*
|
||||
|
||||
Grab the latest version or report a bug on GitHub:
|
||||
|
||||
http://github.com/tpope/vim-fugitive
|
||||
|
||||
vim:tw=78:et:ft=help:norl:
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +0,0 @@
|
|||
# vim-monokai
|
||||
|
||||
Monokai color scheme for Vim converted with [coloration](http://coloration.sickill.net) from Textmate theme with the same name.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
|
@ -1,107 +0,0 @@
|
|||
" Vim color file
|
||||
" Converted from Textmate theme Monokai using Coloration v0.3.2 (http://github.com/sickill/coloration)
|
||||
|
||||
set background=dark
|
||||
highlight clear
|
||||
|
||||
if exists("syntax_on")
|
||||
syntax reset
|
||||
endif
|
||||
|
||||
let g:colors_name = "Monokai"
|
||||
|
||||
hi Cursor ctermfg=235 ctermbg=231 cterm=NONE guifg=#272822 guibg=#f8f8f0 gui=NONE
|
||||
hi Visual ctermfg=NONE ctermbg=59 cterm=NONE guifg=NONE guibg=#49483e gui=NONE
|
||||
hi CursorLine ctermfg=NONE ctermbg=237 cterm=NONE guifg=NONE guibg=#3c3d37 gui=NONE
|
||||
hi CursorColumn ctermfg=NONE ctermbg=237 cterm=NONE guifg=NONE guibg=#3c3d37 gui=NONE
|
||||
hi ColorColumn ctermfg=NONE ctermbg=237 cterm=NONE guifg=NONE guibg=#3c3d37 gui=NONE
|
||||
hi LineNr ctermfg=102 ctermbg=237 cterm=NONE guifg=#90908a guibg=#3c3d37 gui=NONE
|
||||
hi VertSplit ctermfg=241 ctermbg=241 cterm=NONE guifg=#64645e guibg=#64645e gui=NONE
|
||||
hi MatchParen ctermfg=197 ctermbg=NONE cterm=underline guifg=#f92672 guibg=NONE gui=underline
|
||||
hi StatusLine ctermfg=231 ctermbg=241 cterm=bold guifg=#f8f8f2 guibg=#64645e gui=bold
|
||||
hi StatusLineNC ctermfg=231 ctermbg=241 cterm=NONE guifg=#f8f8f2 guibg=#64645e gui=NONE
|
||||
hi Pmenu ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi PmenuSel ctermfg=NONE ctermbg=59 cterm=NONE guifg=NONE guibg=#49483e gui=NONE
|
||||
hi IncSearch ctermfg=235 ctermbg=186 cterm=NONE guifg=#272822 guibg=#e6db74 gui=NONE
|
||||
hi Search ctermfg=NONE ctermbg=NONE cterm=underline guifg=NONE guibg=NONE gui=underline
|
||||
hi Directory ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi Folded ctermfg=242 ctermbg=235 cterm=NONE guifg=#75715e guibg=#272822 gui=NONE
|
||||
|
||||
hi Normal ctermfg=231 ctermbg=235 cterm=NONE guifg=#f8f8f2 guibg=#272822 gui=NONE
|
||||
hi Boolean ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi Character ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi Comment ctermfg=242 ctermbg=NONE cterm=NONE guifg=#75715e guibg=NONE gui=NONE
|
||||
hi Conditional ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi Constant ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi Define ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi DiffAdd ctermfg=231 ctermbg=64 cterm=bold guifg=#f8f8f2 guibg=#46830c gui=bold
|
||||
hi DiffDelete ctermfg=88 ctermbg=NONE cterm=NONE guifg=#8b0807 guibg=NONE gui=NONE
|
||||
hi DiffChange ctermfg=231 ctermbg=23 cterm=NONE guifg=#f8f8f2 guibg=#243955 gui=NONE
|
||||
hi DiffText ctermfg=231 ctermbg=24 cterm=bold guifg=#f8f8f2 guibg=#204a87 gui=bold
|
||||
hi ErrorMsg ctermfg=231 ctermbg=197 cterm=NONE guifg=#f8f8f0 guibg=#f92672 gui=NONE
|
||||
hi WarningMsg ctermfg=231 ctermbg=197 cterm=NONE guifg=#f8f8f0 guibg=#f92672 gui=NONE
|
||||
hi Float ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi Function ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE
|
||||
hi Identifier ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic
|
||||
hi Keyword ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi Label ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE
|
||||
hi NonText ctermfg=59 ctermbg=236 cterm=NONE guifg=#49483e guibg=#31322c gui=NONE
|
||||
hi Number ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi Operator ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi PreProc ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi Special ctermfg=231 ctermbg=NONE cterm=NONE guifg=#f8f8f2 guibg=NONE gui=NONE
|
||||
hi SpecialKey ctermfg=59 ctermbg=237 cterm=NONE guifg=#49483e guibg=#3c3d37 gui=NONE
|
||||
hi Statement ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi StorageClass ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic
|
||||
hi String ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE
|
||||
hi Tag ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi Title ctermfg=231 ctermbg=NONE cterm=bold guifg=#f8f8f2 guibg=NONE gui=bold
|
||||
hi Todo ctermfg=95 ctermbg=NONE cterm=inverse,bold guifg=#75715e guibg=NONE gui=inverse,bold
|
||||
hi Type ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline guifg=NONE guibg=NONE gui=underline
|
||||
hi rubyClass ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi rubyFunction ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE
|
||||
hi rubyInterpolationDelimiter ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi rubySymbol ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi rubyConstant ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic
|
||||
hi rubyStringDelimiter ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE
|
||||
hi rubyBlockParameter ctermfg=208 ctermbg=NONE cterm=NONE guifg=#fd971f guibg=NONE gui=italic
|
||||
hi rubyInstanceVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi rubyInclude ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi rubyGlobalVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi rubyRegexp ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE
|
||||
hi rubyRegexpDelimiter ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE
|
||||
hi rubyEscape ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi rubyControl ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi rubyClassVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi rubyOperator ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi rubyException ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi rubyPseudoVariable ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi rubyRailsUserClass ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic
|
||||
hi rubyRailsARAssociationMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi rubyRailsARMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi rubyRailsRenderMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi rubyRailsMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi erubyDelimiter ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi erubyComment ctermfg=95 ctermbg=NONE cterm=NONE guifg=#75715e guibg=NONE gui=NONE
|
||||
hi erubyRailsMethod ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi htmlTag ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi htmlEndTag ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi htmlTagName ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi htmlArg ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi htmlSpecialChar ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi javaScriptFunction ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=italic
|
||||
hi javaScriptRailsFunction ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi javaScriptBraces ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi yamlKey ctermfg=197 ctermbg=NONE cterm=NONE guifg=#f92672 guibg=NONE gui=NONE
|
||||
hi yamlAnchor ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi yamlAlias ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
||||
hi yamlDocumentHeader ctermfg=186 ctermbg=NONE cterm=NONE guifg=#e6db74 guibg=NONE gui=NONE
|
||||
hi cssURL ctermfg=208 ctermbg=NONE cterm=NONE guifg=#fd971f guibg=NONE gui=italic
|
||||
hi cssFunctionName ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi cssColor ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi cssPseudoClassId ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE
|
||||
hi cssClassName ctermfg=148 ctermbg=NONE cterm=NONE guifg=#a6e22e guibg=NONE gui=NONE
|
||||
hi cssValueLength ctermfg=141 ctermbg=NONE cterm=NONE guifg=#ae81ff guibg=NONE gui=NONE
|
||||
hi cssCommonAttr ctermfg=81 ctermbg=NONE cterm=NONE guifg=#66d9ef guibg=NONE gui=NONE
|
||||
hi cssBraces ctermfg=NONE ctermbg=NONE cterm=NONE guifg=NONE guibg=NONE gui=NONE
|
1
vim/bundle/vim-obsession/.gitignore
vendored
1
vim/bundle/vim-obsession/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/doc/tags
|
|
@ -1 +0,0 @@
|
|||
See the [contribution guidelines for pathogen.vim](https://github.com/tpope/vim-pathogen/blob/master/CONTRIBUTING.markdown).
|
|
@ -1,47 +0,0 @@
|
|||
# obsession.vim
|
||||
|
||||
Vim features a `:mksession` command to write a file containing the current
|
||||
state of Vim: window positions, open folds, stuff like that. For most of my
|
||||
existence, I found the interface way too awkward and manual to be useful, but
|
||||
I've recently discovered that the only thing standing between me and simple,
|
||||
no-hassle Vim sessions is a few tweaks:
|
||||
|
||||
* Instead of making me remember to capture the session immediately before
|
||||
exiting Vim, allow me to do it at any time, and automatically re-invoke
|
||||
`:mksession` immediately before exit.
|
||||
* Also invoke `:mksession` whenever the layout changes (in particular, on
|
||||
`BufEnter`), so that even if Vim exits abnormally, I'm good to go.
|
||||
* If I load an existing session, automatically keep it updated as above.
|
||||
* If I try to create a new session on top of an existing session, don't refuse
|
||||
to overwrite it. Just do what I mean.
|
||||
* If I pass in a directory rather than a file name, just create a
|
||||
`Session.vim` inside of it.
|
||||
* Don't capture options and maps. Options are sometimes mutilated and maps
|
||||
just interfere with updating plugins.
|
||||
|
||||
Use `:Obsess` (with optional file/directory name) to start recording to a
|
||||
session file and `:Obsess!` to stop and throw it away. That's it. Load a
|
||||
session in the usual manner: `vim -S`, or `:source` it.
|
||||
|
||||
## Installation
|
||||
|
||||
If you don't have a preferred installation method, I recommend
|
||||
installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and
|
||||
then simply copy and paste:
|
||||
|
||||
cd ~/.vim/bundle
|
||||
git clone git://github.com/tpope/vim-obsession.git
|
||||
|
||||
## Self-Promotion
|
||||
|
||||
Like obsession.vim? Follow the repository on
|
||||
[GitHub](https://github.com/tpope/vim-obsession) and vote for it on
|
||||
[vim.org](http://www.vim.org/scripts/script.php?script_id=4472). And if
|
||||
you're feeling especially charitable, follow [tpope](http://tpo.pe/) on
|
||||
[Twitter](http://twitter.com/tpope) and
|
||||
[GitHub](https://github.com/tpope).
|
||||
|
||||
## License
|
||||
|
||||
Copyright © Tim Pope. Distributed under the same terms as Vim itself.
|
||||
See `:help license`.
|
|
@ -1,27 +0,0 @@
|
|||
*obsession.txt* Continuously updated session files
|
||||
|
||||
Author: Tim Pope <http://tpo.pe/>
|
||||
Repo: https://github.com/tpope/vim-obsession
|
||||
License: Same terms as Vim itself (see |license|)
|
||||
|
||||
USAGE *obsession* *:Obsession*
|
||||
|
||||
:Obsession {file} Invoke |:mksession| on {file} and continue to keep it
|
||||
updated until Vim exits, triggering on the |BufEnter|
|
||||
and |VimLeavePre| autocommands. If the file exists,
|
||||
it will be overwritten if and only if it looks like a
|
||||
session file.
|
||||
|
||||
:Obsession {dir} Invoke |:Obsession| on {dir}/Session.vim. Use "." to
|
||||
write to a session file in the current directory.
|
||||
|
||||
:Obsession If session tracking is already in progress, pause it.
|
||||
Otherwise, resume tracking or create a new session in
|
||||
the current directory.
|
||||
|
||||
:Obsession! Stop obsession and delete the underlying session file.
|
||||
|
||||
Loading a session created with |:Obsession| automatically resumes updates to
|
||||
that file.
|
||||
|
||||
vim:tw=78:et:ft=help:norl:
|
|
@ -1,71 +0,0 @@
|
|||
" obsession.vim - Continuously updated session files
|
||||
" Maintainer: Tim Pope <http://tpo.pe/>
|
||||
" Version: 1.0
|
||||
|
||||
if exists("g:loaded_obsession") || v:version < 700 || &cp
|
||||
finish
|
||||
endif
|
||||
let g:loaded_obsession = 1
|
||||
|
||||
command! -bar -bang -complete=file -nargs=? Obsession execute s:dispatch(<bang>0, <q-args>)
|
||||
|
||||
function! s:dispatch(bang, file) abort
|
||||
if a:bang && empty(a:file) && filereadable(get(g:, 'this_obsession', v:this_session))
|
||||
echo 'Deleting session in '.fnamemodify(get(g:, 'this_obsession', v:this_session), ':~:.')
|
||||
call delete(get(g:, 'this_obsession', v:this_session))
|
||||
unlet! g:this_obsession
|
||||
return ''
|
||||
elseif empty(a:file) && exists('g:this_obsession')
|
||||
echo 'Pausing session in '.fnamemodify(g:this_obsession, ':~:.')
|
||||
unlet g:this_obsession
|
||||
return ''
|
||||
elseif empty(a:file) && !empty(v:this_session)
|
||||
let file = v:this_session
|
||||
elseif empty(a:file)
|
||||
let file = getcwd() . '/Session.vim'
|
||||
elseif isdirectory(a:file)
|
||||
let file = fnamemodify(expand(a:file), ':p') . '/Session.vim'
|
||||
else
|
||||
let file = fnamemodify(expand(a:file), ':p')
|
||||
endif
|
||||
if !a:bang
|
||||
\ && file !~# 'Session\.vim$'
|
||||
\ && filereadable(file)
|
||||
\ && getfsize(file) > 0
|
||||
\ && readfile(file, '', 1)[0] !=# 'let SessionLoad = 1'
|
||||
return 'mksession '.fnameescape(file)
|
||||
endif
|
||||
let g:this_obsession = file
|
||||
let error = s:persist()
|
||||
if empty(error)
|
||||
echo 'Tracking session in '.fnamemodify(file, ':~:.')
|
||||
let v:this_session = file
|
||||
return ''
|
||||
else
|
||||
return error
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:persist()
|
||||
if exists('g:this_obsession')
|
||||
let sessionoptions = &sessionoptions
|
||||
try
|
||||
set sessionoptions-=options
|
||||
execute 'mksession! '.fnameescape(g:this_obsession)
|
||||
call writefile(insert(readfile(g:this_obsession), 'let g:this_obsession = v:this_session', -2), g:this_obsession)
|
||||
catch
|
||||
unlet g:this_obsession
|
||||
return 'echoerr '.string(v:exception)
|
||||
finally
|
||||
let &sessionoptions = sessionoptions
|
||||
endtry
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
augroup obsession
|
||||
autocmd!
|
||||
autocmd BufEnter,VimLeavePre * exe s:persist()
|
||||
augroup END
|
||||
|
||||
" vim:set et sw=2:
|
3
vim/bundle/vim-rails/.gitignore
vendored
3
vim/bundle/vim-rails/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
/rails.zip
|
||||
/rails.vba
|
||||
/doc/tags
|
|
@ -1,16 +0,0 @@
|
|||
If your [commit message sucks][suck], I'm not going to accept your pull
|
||||
request. I've explained very politely dozens of times that [my general
|
||||
guidelines][guidelines] are absolute rules on my own repositories, so I may
|
||||
lack the energy to explain it to you yet another time. And please, if I ask
|
||||
you to change something, `git commit --amend` and `git push -f`.
|
||||
|
||||
If a feature idea is nontrivial, you should probably open an issue to [discuss
|
||||
it][] before attempting a pull request. One of the biggest challenges in
|
||||
maintaining rails.vim has been beating back the bloat, so do not assume that
|
||||
your idea will make the cut. And if I like your idea, I'm generally amenable
|
||||
to just knocking it out myself, rather than making you familiarize yourself
|
||||
with a 4 thousand line code base.
|
||||
|
||||
[suck]: http://stopwritingramblingcommitmessages.com/
|
||||
[guidelines]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[discuss it]: http://www.igvita.com/2011/12/19/dont-push-your-pull-requests/
|
|
@ -1,135 +0,0 @@
|
|||
# rails.vim
|
||||
|
||||
Remember when everybody and their mother was using TextMate for Ruby on
|
||||
Rails development? Well if it wasn't for rails.vim, we'd still be in
|
||||
that era. So shut up and pay some respect. And check out these
|
||||
features:
|
||||
|
||||
* Easy navigation of the Rails directory structure. `gf` considers
|
||||
context and knows about partials, fixtures, and much more. There are
|
||||
two commands, `:A` (alternate) and `:R` (related) for easy jumping
|
||||
between files, including favorites like model to schema, template to
|
||||
helper, and controller to functional test. Commands like `:Emodel`,
|
||||
`:Eview`, `:Econtroller`, are provided to `:edit` files by type, along
|
||||
with `S`, `V`, and `T` variants for `:split`, `:vsplit`, and
|
||||
`:tabedit`. Throw a bang on the end (`:Emodel foo!`) to automatically
|
||||
create the file with the standard boilerplate if it doesn't exist.
|
||||
`:help rails-navigation`
|
||||
|
||||
* Enhanced syntax highlighting. From `has_and_belongs_to_many` to
|
||||
`distance_of_time_in_words`, it's here. For easy completion of these
|
||||
long method names, `'completefunc'` is set to enable syntax based
|
||||
completion on CTRL-X CTRL-U.
|
||||
|
||||
* Interface to rake. Use `:Rake` to run the current test, spec, or
|
||||
feature. Use `:.Rake` to do a focused run of just the method,
|
||||
example, or scenario on the current line. `:Rake` can also run
|
||||
arbitrary migrations, load individual fixtures, and more.
|
||||
`:help rails-rake`
|
||||
|
||||
* Interface to the `rails` command. Generally, use `:Rails console` to
|
||||
call `rails console`. Many commands have wrappers with additional features:
|
||||
`:Rgenerate controller Blog` generates a blog controller and loads the
|
||||
generated files into the quickfix list, and `:Rrunner` wraps `rails runner`
|
||||
and doubles as a direct test runner. `:help rails-scripts`
|
||||
|
||||
* Partial and concern extraction. In a view, `:Rextract {file}`
|
||||
replaces the desired range (typically selected in visual line mode)
|
||||
with `render '{file}'`, which is automatically created with your
|
||||
content. In a model or controller, a concern is created, with the
|
||||
appropriate `include` declaration left behind.
|
||||
`:help rails-:Rextract`
|
||||
|
||||
* Fully customizable. Define "projections" at the global, app, or gem
|
||||
level to define navigation commands and override the alternate file,
|
||||
default rake task, syntax highlighting, abbreviations, and more.
|
||||
`:help rails-projections`.
|
||||
|
||||
* Integration with other plugins. If
|
||||
[dbext.vim](http://www.vim.org/scripts/script.php?script_id=356) is
|
||||
installed, it will be transparently configured to reflect
|
||||
`database.yml`. Users of
|
||||
[abolish.vim](https://github.com/tpope/vim-abolish) get pluralize and
|
||||
tableize coercions, and users of
|
||||
[bundler.vim](https://github.com/tpope/vim-bundler) get a smattering of
|
||||
features. `:help rails-integration`
|
||||
|
||||
## Installation
|
||||
|
||||
If you don't have a preferred installation method, I recommend
|
||||
installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and
|
||||
then simply copy and paste:
|
||||
|
||||
cd ~/.vim/bundle
|
||||
git clone git://github.com/tpope/vim-rails.git
|
||||
git clone git://github.com/tpope/vim-bundler.git
|
||||
|
||||
You don't strictly need [bundler.vim][], but it helps.
|
||||
|
||||
Once help tags have been generated, you can view the manual with
|
||||
`:help rails`.
|
||||
|
||||
[bundler.vim]: https://github.com/tpope/vim-bundler
|
||||
|
||||
## FAQ
|
||||
|
||||
> I installed the plugin and started Vim. Why does only the `:Rails`
|
||||
> command exist?
|
||||
|
||||
This plugin cares about the current file, not the current working
|
||||
directory. Edit a file from a Rails application.
|
||||
|
||||
> I opened a new tab. Why does only the `:Rails` command exist?
|
||||
|
||||
This plugin cares about the current file, not the current working
|
||||
directory. Edit a file from a Rails application. You can use the `:RT`
|
||||
family of commands to open a new tab and edit a file at the same time.
|
||||
|
||||
> Can I use rails.vim to edit Rails engines?
|
||||
|
||||
It's not supported, but if you `touch config/environment.rb` in the root
|
||||
of the engine, things should mostly work.
|
||||
|
||||
> Can I use rails.vim to edit other Ruby projects?
|
||||
|
||||
I wrote [rake.vim](https://github.com/tpope/vim-rake) for exactly that
|
||||
purpose. It activates for any project with a `Rakefile` that's not a
|
||||
Rails application.
|
||||
|
||||
> What Rails versions are supported?
|
||||
|
||||
All of them. A few features like syntax highlighting tend to reflect the
|
||||
latest version only.
|
||||
|
||||
> Rake is slow. How about making `:Rake` run
|
||||
> `testrb`/`rspec`/`cucumber` directly instead of `rake`?
|
||||
|
||||
Well then it wouldn't make sense to call it `:Rake`, now, would it?
|
||||
Maybe one day I'll add a separate `:Run` command or something. In the
|
||||
meantime, here's how you can set up `:make` to run the current test:
|
||||
|
||||
autocmd FileType cucumber compiler cucumber | setl makeprg=cucumber\ \"%:p\"
|
||||
autocmd FileType ruby
|
||||
\ if expand('%') =~# '_test\.rb$' |
|
||||
\ compiler rubyunit | setl makeprg=testrb\ \"%:p\" |
|
||||
\ elseif expand('%') =~# '_spec\.rb$' |
|
||||
\ compiler rspec | setl makeprg=rspec\ \"%:p\" |
|
||||
\ else |
|
||||
\ compiler ruby | setl makeprg=ruby\ -wc\ \"%:p\" |
|
||||
\ endif
|
||||
autocmd User Bundler
|
||||
\ if &makeprg !~# 'bundle' | setl makeprg^=bundle\ exec\ | endif
|
||||
|
||||
## Self-Promotion
|
||||
|
||||
Like rails.vim? Follow the repository on
|
||||
[GitHub](https://github.com/tpope/vim-rails) and vote for it on
|
||||
[vim.org](http://www.vim.org/scripts/script.php?script_id=1567). And if
|
||||
you're feeling especially charitable, follow [tpope](http://tpo.pe/) on
|
||||
[Twitter](http://twitter.com/tpope) and
|
||||
[GitHub](https://github.com/tpope).
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
|
||||
See `:help license`.
|
File diff suppressed because it is too large
Load Diff
|
@ -1,930 +0,0 @@
|
|||
*rails.txt* Plugin for working with Ruby on Rails applications
|
||||
|
||||
Author: Tim Pope <http://tpo.pe/>
|
||||
|
||||
|rails-introduction| Introduction and Feature Summary
|
||||
|rails-commands| General Commands
|
||||
|rails-navigation| Navigation
|
||||
|rails-gf| File Under Cursor - gf
|
||||
|rails-alternate-related| Alternate and Related Files
|
||||
|rails-type-navigation| File Type Commands
|
||||
|rails-rake| Rake
|
||||
|rails-scripts| Script Wrappers
|
||||
|rails-refactoring| Refactoring Helpers
|
||||
|rails-partials| Partial Extraction
|
||||
|rails-migrations| Migration Inversion
|
||||
|rails-integration| Integration
|
||||
|rails-vim-integration| Integration with the Vim Universe
|
||||
|rails-rails-integration| Integration with the Rails Universe
|
||||
|rails-abbreviations| Abbreviations
|
||||
|rails-syntax| Syntax Highlighting
|
||||
|rails-options| Managed Vim Options
|
||||
|rails-projections| Projections
|
||||
|rails-configuration| Configuration
|
||||
|rails-global-settings| Global Settings
|
||||
|rails-about| About rails.vim
|
||||
|rails-license| License
|
||||
|
||||
This plugin is only available if 'compatible' is not set.
|
||||
|
||||
{Vi does not have any of this}
|
||||
|
||||
INTRODUCTION *rails-introduction* *rails*
|
||||
|
||||
Whenever you edit a file in a Rails application, this plugin will be
|
||||
automatically activated. This sets various options and defines a few
|
||||
buffer-specific commands.
|
||||
|
||||
If you are in a hurry to get started, with a minimal amount of reading, you
|
||||
are encouraged to at least skim through the headings and command names in this
|
||||
file, to get a better idea of what is offered. If you only read one thing,
|
||||
make sure it is the navigation section: |rails-navigation|.
|
||||
|
||||
GENERAL COMMANDS *rails-commands*
|
||||
|
||||
All commands are buffer local, unless otherwise stated. This means you must
|
||||
actually edit a file from a Rails application.
|
||||
|
||||
*rails-:Rails-new*
|
||||
:Rails new {directory} The only global command. Invokes "rails new
|
||||
{directory}" and loads the generated files into the
|
||||
quickfix list.
|
||||
|
||||
*rails-:Rails!*
|
||||
:Rails! Show the version of rails.vim installed. If rails.vim
|
||||
is active for the current buffer, also show the type
|
||||
of Rails file detected.
|
||||
|
||||
*rails-:Redit*
|
||||
:Redit {file} Obsolete alias for |:R| or |:A|.
|
||||
|
||||
*rails-:Rfind*
|
||||
:Rfind [{file}] Obsolete alias for |:find|.
|
||||
|
||||
*rails-:Rlog*
|
||||
:Rlog [{logfile}] Split window and open {logfile} ($RAILS_ENV or
|
||||
development by default). The control characters used
|
||||
for highlighting are removed. If you have a :Tail
|
||||
command (provided by |tailminusf|.vim), that is used;
|
||||
otherwise, the file does NOT reload upon change.
|
||||
Use |:checktime| to tell Vim to check for changes.
|
||||
|G| has been mapped to do just that prior to jumping
|
||||
to the end of the file, and q is mapped to close the
|
||||
window. If the delay in loading is too long, you
|
||||
might like :Rake log:clear.
|
||||
|
||||
*rails-:Rpreview*
|
||||
:Rpreview [path] Open the given [path] for the current app in a
|
||||
browser. The host and port are determined by applying
|
||||
some netstat/lsof trickery to the current server pid.
|
||||
If no server is running, Pow is consulted, and if all
|
||||
else fails, a default of localhost:3000 is used. If
|
||||
[path] is omitted, a sensible default is used
|
||||
(considers the current controller/template, but does
|
||||
not take routing into account). The default is
|
||||
overridden by comments like the following that are
|
||||
either before the current method call or at the top of
|
||||
the file: >
|
||||
|
||||
# GET /users
|
||||
# PUT /users/1
|
||||
<
|
||||
If it's not using the right browser, define an OpenURL
|
||||
command:
|
||||
>
|
||||
:command -bar -nargs=1 OpenURL :!open <args>
|
||||
<
|
||||
*rails-:Rpreview!*
|
||||
:Rpreview! [{path}] Like :Rpreview, but open the path inside Vim using
|
||||
|netrw| instead.
|
||||
|
||||
*rails-:Rrefresh*
|
||||
:Rrefresh Refreshes certain cached settings. Most noticeably,
|
||||
this clears the cached list of classes that are syntax
|
||||
highlighted as railsUserClass.
|
||||
|
||||
*rails-:Rrefresh!*
|
||||
:Rrefresh! As above, and also reloads rails.vim.
|
||||
|
||||
*rails-:Cd* *rails-:Rcd*
|
||||
:Cd [{directory}] |:cd| to /path/to/railsapp/{directory}.
|
||||
|
||||
*rails-:Lcd* *rails-:Rlcd*
|
||||
:Lcd [{directory}] |:lcd| to /path/to/railsapp/{directory}.
|
||||
|
||||
*rails-:Ctags* *rails-:Rtags*
|
||||
:Ctags Calls ctags -R on the current application root.
|
||||
Exuberant ctags must be installed. Additional
|
||||
arguments can be passed to ctags with
|
||||
|g:rails_ctags_arguments|.
|
||||
|
||||
NAVIGATION *rails-navigation*
|
||||
|
||||
Navigation is where the real power of this plugin lies. Efficient use of the
|
||||
following features will greatly ease navigating the Rails file structure.
|
||||
|
||||
The standard Rails load path is prepended to 'path', enabling |:find| to work:
|
||||
>
|
||||
:find application_controller.rb
|
||||
<
|
||||
File Under Cursor - gf ~
|
||||
*rails-gf*
|
||||
The |gf| command, which normally edits the current file under the cursor, has
|
||||
been remapped to take context into account. |CTRL-W_f| (open in new window)
|
||||
and |CTRL-W_gf| (open in new tab) are also remapped.
|
||||
|
||||
Example uses of |gf|, and where they might lead.
|
||||
(* indicates cursor position)
|
||||
>
|
||||
Pos*t.first
|
||||
< app/models/post.rb ~
|
||||
>
|
||||
has_many :c*omments
|
||||
< app/models/comment.rb ~
|
||||
>
|
||||
link_to 'Home', :controller => 'bl*og'
|
||||
< app/controllers/blog_controller.rb ~
|
||||
>
|
||||
<%= render 'sh*ared/sidebar' %>
|
||||
< app/views/shared/_sidebar.html.erb ~
|
||||
>
|
||||
<%= stylesheet_link_tag 'scaf*fold' %>
|
||||
< public/stylesheets/scaffold.css ~
|
||||
>
|
||||
class BlogController < Applica*tionController
|
||||
< app/controllers/application_controller.rb ~
|
||||
>
|
||||
class ApplicationController < ActionCont*roller::Base
|
||||
< .../action_controller/base.rb ~
|
||||
>
|
||||
fixtures :pos*ts
|
||||
< test/fixtures/posts.yml ~
|
||||
>
|
||||
layout :pri*nt
|
||||
< app/views/layouts/print.html.erb ~
|
||||
>
|
||||
<%= link_to "New", new_comme*nt_path %>
|
||||
< app/controllers/comments_controller.rb (jumps to def new) ~
|
||||
|
||||
In the last example, the controller and action for the named route are
|
||||
determined by evaluating routes.rb as Ruby and doing some introspection. This
|
||||
means code from the application is executed. Keep this in mind when
|
||||
navigating unfamiliar applications.
|
||||
|
||||
Alternate and Related Files ~
|
||||
*rails-alternate-related*
|
||||
Two commands, :A and :R, are used to quickly jump to an "alternate" and a
|
||||
"related" file, defined below.
|
||||
|
||||
*rails-:A* *rails-:AE* *rails-:AS* *rails-:AV* *rails-:AT* *rails-:AD*
|
||||
:A These commands were picked to mimic Michael Sharpe's
|
||||
:AE a.vim. Briefly, they edit the "alternate" file, in
|
||||
:AS either the same window (:A and :AE), a new split
|
||||
:AV window (:AS), a new vertically split window (:AV), a
|
||||
:AT new tab (:AT), or read it into the current buffer
|
||||
:AD (:AD).
|
||||
|
||||
*rails-:R* *rails-:RE* *rails-:RS* *rails-:RV* *rails-:RT* *rails-:RD*
|
||||
:R These are similar |rails-:A| and friends above, only
|
||||
:RE they jump to the "related" file rather than the
|
||||
:RS "alternate." With a file name argument, they edit
|
||||
:RV a file relative to the application root (:R Rakefile),
|
||||
:RT and with a count and a file name argument, they find a
|
||||
:RD file in 'path' (e.g., :1R PostsController.) You can
|
||||
also append a line number (post.rb:42) or a method
|
||||
(PostsController#index) to both forms.
|
||||
|
||||
*rails-alternate* *rails-related*
|
||||
The alternate file is most frequently the test file, though there are
|
||||
exceptions. The related file varies, and is sometimes dependent on current
|
||||
location in the file. For example, when editing a controller, the related
|
||||
file is template for the method currently being edited.
|
||||
|
||||
The easiest way to learn these commands is to experiment. A few examples of
|
||||
alternate and related files for a Test::Unit application follow:
|
||||
|
||||
Current file Alternate file Related file ~
|
||||
model unit test schema definition
|
||||
controller (in method) functional test template (view)
|
||||
template (view) functional test controller (jump to method)
|
||||
migration previous migration next migration
|
||||
database.yml database.example.yml environments/*.rb
|
||||
|
||||
Alternates can be tweaked with |rails-projections|.
|
||||
|
||||
File Type Navigation Commands ~
|
||||
*rails-type-navigation*
|
||||
For the less common cases, a more deliberate set of commands are provided.
|
||||
Each of the upcoming commands takes an optional argument (with tab completion)
|
||||
but defaults to a reasonable guess. Commands that default to the current
|
||||
model or controller generally behave like you'd expect in other file types.
|
||||
For example, in app/helpers/posts_helper.rb, the current controller is
|
||||
"posts", and in test/fixtures/comments.yml, the current model is "comment".
|
||||
In model related files, the current controller is the pluralized model name,
|
||||
and in controller related files, the current model is the singularized
|
||||
controller name.
|
||||
|
||||
Each of the following commands has variants for splitting, vertical splitting,
|
||||
opening in a new tab, and reading the file into the current buffer. For
|
||||
:Emodel, those variants would be :Smodel, :Vmodel, :Tmodel, and :Dmodel.
|
||||
They also allow for jumping to methods or line numbers using the same syntax
|
||||
as |:R|, and file creation (with a bit of boilerplate) can be forced by adding
|
||||
a ! after the filename (not after the command itself!).
|
||||
|
||||
There are also "classic" versions of these commands that start with :R (e.g.,
|
||||
:Rmodel, :RSmodel, :RVmodel, :RTmodel, and :RDmodel).
|
||||
|
||||
:Econtroller |rails-:Econtroller|
|
||||
:Eenvironment |rails-:Eenvironment|
|
||||
:Efixtures |rails-:Efixtures|
|
||||
:Efunctionaltest |rails-:Efunctionaltest|
|
||||
:Ehelper |rails-:Ehelper|
|
||||
:Einitializer |rails-:Einitializer|
|
||||
:Eintegrationtest |rails-:Eintegrationtest|
|
||||
:Ejavascript |rails-:Ejavascript|
|
||||
:Elayout |rails-:Elayout|
|
||||
:Elib |rails-:Elib|
|
||||
:Elocale |rails-:Elocale|
|
||||
:Emailer |rails-:Emailer|
|
||||
:Emigration |rails-:Emigration|
|
||||
:Emodel |rails-:Emodel|
|
||||
:Eschema |rails-:Eschema|
|
||||
:Espec |rails-:Espec|
|
||||
:Estylesheet |rails-:Estylesheet|
|
||||
:Etask |rails-:Etask|
|
||||
:Eunittest |rails-:Eunittest|
|
||||
:Eview |rails-:Eview|
|
||||
|
||||
*rails-:Econtroller* *rails-:Rcontroller*
|
||||
:Econtroller [{name}] Edit the specified or current controller.
|
||||
|
||||
*rails-:Eenvironment* *rails-:Renvironment*
|
||||
:Eenvironment [{name}] Edit the config/environments file specified. With no
|
||||
argument, defaults to editing config/application.rb
|
||||
or config/environment.rb.
|
||||
|
||||
*rails-:Efixtures* *rails-:Rfixtures*
|
||||
:Efixtures [{name}] Edit the fixtures for the given or current model. If
|
||||
an argument is given, it must be pluralized, like the
|
||||
final filename (this may change in the future). If
|
||||
omitted, the current model is pluralized. An optional
|
||||
extension can be given, to distinguish between YAML
|
||||
and CSV fixtures.
|
||||
|
||||
*rails-:Efunctionaltest* *rails-:Rfunctionaltest*
|
||||
:Efunctionaltest [{name}]
|
||||
Edit the functional test or controller spec for the
|
||||
specified or current controller.
|
||||
|
||||
*rails-:Ehelper* *rails-:Rhelper*
|
||||
:Ehelper [{name}] Edit the helper for the specified name or current
|
||||
controller.
|
||||
|
||||
*rails-:Einitializer* *rails-:Rinitializer*
|
||||
:Einitializer [{name}] Edit the config/initializers file specified. With no
|
||||
argument, defaults to editing config/routes.rb.
|
||||
|
||||
*rails-:Eintegrationtest* *rails-:Rintegrationtest*
|
||||
:Eintegrationtest [{name}]
|
||||
Edit the integration test, integration spec, or
|
||||
cucumber feature specified. With no argument,
|
||||
defaults to editing test/test_helper.rb.
|
||||
|
||||
*rails-:Ejavascript* *rails-:Rjavascript*
|
||||
:Ejavascript [{name}] Edit the JavaScript for the specified name or current
|
||||
controller. Also supports CoffeeScript in
|
||||
app/scripts/.
|
||||
|
||||
*rails-:Elayout* *rails-:Rlayout*
|
||||
:Elayout [{name}] Edit the specified layout. Defaults to the layout for
|
||||
the current controller, or the application layout if
|
||||
that cannot be found. A new layout will be created if
|
||||
an extension is given.
|
||||
|
||||
*rails-:Elib* *rails-:Rlib*
|
||||
:Elib [{name}] Edit the library from the lib directory for the
|
||||
specified name. With no argument, defaults to editing
|
||||
the application Gemfile (a task formally handled by
|
||||
the defunct :Rplugin).
|
||||
|
||||
*rails-:Elocale* *rails-:Rlocale*
|
||||
:Elocale [{name}] Edit the config/locale file specified, optionally
|
||||
adding a yml or rb extension if none is given. With
|
||||
no argument, checks config/environment.rb for the
|
||||
default locale.
|
||||
|
||||
*rails-:Emailer* *rails-:Rmailer*
|
||||
:Emailer [{name}] Edit the mailer specified. This looks in both
|
||||
app/mailers for Rails 3 and app/models for older
|
||||
versions of Rails but only tab completes the former.
|
||||
|
||||
*rails-:Emigration* *rails-:Rmigration*
|
||||
:Emigration [{pattern}] If {pattern} is a number, find the migration for that
|
||||
particular set of digits, zero-padding if necessary.
|
||||
Otherwise, find the newest migration containing the
|
||||
given pattern. Omitting the pattern selects the
|
||||
latest migration. Give a numeric argument of 0 to edit
|
||||
db/seeds.rb.
|
||||
|
||||
*rails-:Emodel* *rails-:Rmodel*
|
||||
:Emodel [{name}] Edit the specified or current model.
|
||||
|
||||
*rails-:Espec* *rails-:Rspec*
|
||||
:Espec [{name}] Edit the given spec. With no argument, defaults to
|
||||
editing spec/spec_helper.rb (If you want to jump to
|
||||
the spec for the given file, use |:A| instead). This
|
||||
command is only defined if there is a spec folder in
|
||||
the root of the application.
|
||||
|
||||
*rails-:Eschema* *rails-:Rschema*
|
||||
:Eschema [{table}] Edit the schema and optionally jump to the specified
|
||||
table.
|
||||
|
||||
*rails-:Estylesheet* *rails-:Rstylesheet*
|
||||
:Estylesheet [{name}] Edit the stylesheet for the specified name or current
|
||||
controller. Also supports Sass and SCSS.
|
||||
|
||||
*rails-:Etask* *rails-:Rtask*
|
||||
:Etask [{name}] Edit the .rake file from lib/tasks for the specified
|
||||
name. If no argument is given, the application
|
||||
Rakefile is edited.
|
||||
|
||||
*rails-:Eunittest* *rails-:Runittest*
|
||||
:Eunittest [{name}] Edit the unit test or model spec for the specified
|
||||
name or current model.
|
||||
|
||||
*rails-:Eview* *rails-:Rview*
|
||||
:Eview [[{controller}/]{view}]
|
||||
Edit the specified view. The controller will default
|
||||
sensibly, and the view name can be omitted when
|
||||
editing a method of a controller. If a view name is
|
||||
given with an extension, a new file will be created.
|
||||
This is a quick way to create a new view.
|
||||
|
||||
Finally, one Vim feature that proves helpful in conjunction with all of the
|
||||
above is |CTRL-^|. This keystroke edits the previous file, and is helpful to
|
||||
back out of any of the above commands.
|
||||
|
||||
RAKE *rails-rake*
|
||||
|
||||
Rake integration happens through the :Rake command.
|
||||
|
||||
*rails-:Rake*
|
||||
:[range]Rake {targets} Calls |:make!| {targets} (with 'makeprg' being rake,
|
||||
or `bundle exec rake` if bundler.vim is active) and
|
||||
opens the quickfix window if there were any errors.
|
||||
An argument of "-" reruns the last task. If {targets}
|
||||
are omitted, :Rake defaults to something sensible as
|
||||
described below. Giving a line number argument may
|
||||
affect that default.
|
||||
|
||||
*rails-:Rake!*
|
||||
:[range]Rake! {targets} Called with a bang, :Rake will forgo opening the
|
||||
quickfix window.
|
||||
|
||||
*rails-rake-defaults*
|
||||
|
||||
Generally, the default task is one that runs the test you'd expect. For
|
||||
example, if you're in a view in an RSpec application, the view spec is run,
|
||||
but if it's a Test::Unit application, the functional test for the
|
||||
corresponding controller is run. The following table lists the most
|
||||
interesting mappings:
|
||||
|
||||
File Task ~
|
||||
unit test test:units TEST=...
|
||||
functional test test:functionals TEST=...
|
||||
integration test test:integration TEST=...
|
||||
spec spec SPEC=...
|
||||
feature cucumber FEATURE=...
|
||||
model test:units TEST=... spec SPEC=...
|
||||
controller test:functionals TEST=... spec SPEC=...
|
||||
helper test:functionals TEST=... spec SPEC=...
|
||||
view test:functionals TEST=... spec SPEC=...
|
||||
fixtures db:fixtures:load FIXTURES=...
|
||||
migration db:migrate VERSION=...
|
||||
config/routes.rb routes
|
||||
db/seeds.rb db:seed
|
||||
|
||||
Additionally, when :Rake is given a line number (e.g., :.Rake), the following
|
||||
additional tasks can be invoked:
|
||||
|
||||
File Task ~
|
||||
unit test test:units TEST=... TESTOPTS=-n...
|
||||
functional test test:functionals TEST=... TESTOPTS=-n...
|
||||
integration test test:integration TEST=... TESTOPTS=-n...
|
||||
spec spec SPEC=...:...
|
||||
feature cucumber FEATURE=...:...
|
||||
controller routes CONTROLLER=...
|
||||
fixtures db:fixtures:identify LABEL=...
|
||||
migration in self.up db:migrate:up VERSION=...
|
||||
migration in self.down db:migrate:down VERSION=...
|
||||
migration elsewhere db:migrate:redo VERSION=...
|
||||
task ... (try to guess currently edited declaration)
|
||||
|
||||
Finally, you can override the default task with a comment like "# rake ..."
|
||||
before the method pointed to by [range] or at the top of the file.
|
||||
|
||||
SCRIPT WRAPPERS *rails-scripts*
|
||||
|
||||
The following commands are wrappers around the scripts in the script directory
|
||||
of the Rails application. Most have extra features beyond calling the script.
|
||||
A limited amount of completion with <Tab> is supported.
|
||||
|
||||
|
||||
*rails-:Rails*
|
||||
:Rails {command} [options]
|
||||
Depending on the Rails version, invoke one of
|
||||
"bin/rails {command}", "script/rails {command}", or
|
||||
"script/{command}".
|
||||
|
||||
*rails-:Rscript*
|
||||
:Rscript {command} [options]
|
||||
Deprecated alias for |:Rails| {command}. Defaults to
|
||||
calling |:Rails| console.
|
||||
|
||||
*rails-:Rrunner*
|
||||
:[range]Rrunner [file] Run the given file or code with rails runner and load
|
||||
:Rrunner {code} the results in to the quickfix list, using the error
|
||||
parser from the "ruby" |:compiler|. If the file looks
|
||||
like a test, spec, or cucumber feature, the
|
||||
"rubyunit", "rspec", or "cucumber" |:compiler| will be
|
||||
used instead. If provided, [range] is passed to the
|
||||
test runner to restrict execution to a particular
|
||||
line. With no argument, defaults to running the test
|
||||
for the current file.
|
||||
|
||||
*rails-:Rp*
|
||||
:[range]Rp {code} Use rails runner to execute "p begin {code} end" and
|
||||
echo the result.
|
||||
|
||||
*rails-:Rpp*
|
||||
:[range]Rpp {code} Like :Rp, but with pp (pretty print).
|
||||
|
||||
*rails-:Rgenerate*
|
||||
:Rgenerate {options} Calls rails generate {options} and loads the
|
||||
generated files into the quickfix list. Use ! to
|
||||
surpress jumping to the first file.
|
||||
|
||||
*rails-:Rdestroy*
|
||||
:Rdestroy {options} Calls rails destroy {options} and loads the destroyed
|
||||
files into the quickfix list.
|
||||
|
||||
*rails-:Rserver*
|
||||
:Rserver {options} Launches rails server {options} in the background.
|
||||
On win32, this means |!start|. Otherwise, the
|
||||
--daemon option is passed in.
|
||||
|
||||
*rails-:Rserver!*
|
||||
:Rserver! {options} Kill the pid found in tmp/pids/server.pid and then
|
||||
invoke |:Rserver|.
|
||||
|
||||
REFACTORING HELPERS *rails-refactoring*
|
||||
|
||||
A few features are dedicated to helping you refactor your code.
|
||||
|
||||
Partial Extraction ~
|
||||
*rails-partials*
|
||||
|
||||
The :Rextract command can be used to extract part of a view to a partial, part
|
||||
of a helper to another helper, or part of a model or controller to a concern.
|
||||
|
||||
*rails-:Rextract*
|
||||
:[range]Rextract [{controller}/]{name}
|
||||
Create a {name} partial from [range] lines (default:
|
||||
current line). Only available in views.
|
||||
|
||||
:[range]Rextract {helper}
|
||||
Create a {name} helper from [range] lines (default:
|
||||
current line). Only available in helpers.
|
||||
|
||||
:[range]Rextract {concern}
|
||||
Create a {name} concern from [range] lines (default:
|
||||
current line). Only available in models and
|
||||
controllers.
|
||||
|
||||
If this is your file, in app/views/blog/show.html.erb: >
|
||||
|
||||
1 <div>
|
||||
2 <h2><%= @post.title %></h2>
|
||||
3 <p><%= @post.body %></p>
|
||||
4 </div>
|
||||
|
||||
And you issue this command: >
|
||||
|
||||
:2,3Rextract post
|
||||
|
||||
Your file will change to this: >
|
||||
|
||||
1 <div>
|
||||
2 <%= render 'post' %>
|
||||
3 </div>
|
||||
|
||||
And app/views/blog/_post.html.erb will now contain: >
|
||||
|
||||
1 <h2><%= @post.title %></h2>
|
||||
2 <p><%= @post.body %></p>
|
||||
<
|
||||
The easiest way to choose what to extract is to use |linewise-visual| mode.
|
||||
Then, a simple >
|
||||
:'<,'>Rextract blog/post
|
||||
will suffice. (Note the use of a controller name in this example.)
|
||||
|
||||
Migration Inversion ~
|
||||
*rails-migrations* *rails-:Rinvert*
|
||||
:Rinvert In a migration, rewrite the self.up method into a
|
||||
self.down method. If self.up is empty, the process is
|
||||
reversed. This chokes on more complicated
|
||||
instructions, but works reasonably well for simple
|
||||
calls to create_table, add_column, and the like.
|
||||
Newer versions of Rails provide increasingly good
|
||||
support for reversible migration definitions, so this
|
||||
command is deprecated and no longer maintained.
|
||||
|
||||
INTEGRATION *rails-integration*
|
||||
|
||||
Having one foot in Rails and one in Vim, rails.vim has two worlds with which
|
||||
to interact.
|
||||
|
||||
Integration with the Vim Universe ~
|
||||
*rails-vim-integration*
|
||||
|
||||
A handful of Vim plugins are enhanced by rails.vim. All plugins mentioned can
|
||||
be found at http://www.vim.org/.
|
||||
|
||||
*rails-:Rdbext* *rails-dbext*
|
||||
:Rdbext [{environment}] This command is only provided when the |dbext| plugin
|
||||
is installed. Loads the {environment} configuration
|
||||
(defaults to $RAILS_ENV or development) from
|
||||
config/database.yml and uses it to configure dbext.
|
||||
The configuration is cached on a per application
|
||||
basis. With dbext version 8.00 and newer, this
|
||||
command is called automatically when needed. When
|
||||
dbext is configured, you can execute SQL directly from
|
||||
Vim: >
|
||||
:Select * from posts order by id desc
|
||||
:Update comments set author_id = 1
|
||||
<
|
||||
*rails-surround*
|
||||
The |surround| plugin available from vim.org enables adding and removing
|
||||
"surroundings" like parentheses, quotes, and HTML tags. Even by itself, it is
|
||||
quite useful for Rails development, particularly eRuby editing. When coupled
|
||||
with this plugin, a few additional replacement surroundings are available in
|
||||
eRuby files. See the |surround| documentation for details on how to use them.
|
||||
The table below uses ^ to represent the position of the surrounded text.
|
||||
|
||||
Key Surrounding ~
|
||||
= <%= ^ %>
|
||||
- <% ^ -%>
|
||||
# <%# ^ %>
|
||||
<C-E> <% ^ -%>\n<% end -%>
|
||||
|
||||
The last surrounding is particularly useful in insert mode with the following
|
||||
map in one's vimrc. Use Alt+o to open a new line below the current one. This
|
||||
works nicely even in a terminal (where most alt/meta maps will fail) because
|
||||
most terminals send <M-o> as <Esc>o anyways.
|
||||
>
|
||||
imap <M-o> <Esc>o
|
||||
<
|
||||
One can also use the <C-E> surrounding in a plain Ruby file to append a bare
|
||||
"end" on the following line.
|
||||
|
||||
*rails-abolish*
|
||||
Among the many features of |abolish| on vim.org is the ability to change the
|
||||
inflection of the word under the cursor. For example, one can hit crs to
|
||||
change from MixedCase to snake_case. This plugin adds two additional
|
||||
inflections: crl for alternating between the singular and plural, and crt for
|
||||
altering between tableize and classify. The latter is useful in changing
|
||||
constructs like BlogPost.all to current_user.blog_posts.all and vice versa.
|
||||
|
||||
*rails-rspec*
|
||||
The presence of a spec directory causes several additional behaviors to
|
||||
activate. :A knows about specs and will jump to them (but Test::Unit files
|
||||
still get priority). The associated controller or model of a spec is
|
||||
detected, so all navigation commands should work as expected inside a spec
|
||||
file. :Rake in a spec runs just that spec, and in a model, controller, or
|
||||
helper, runs the associated spec.
|
||||
|
||||
|:Eunittest| and |:Efunctionaltest| lead double lives, handling model/helper
|
||||
and controller/mailer specs respectively. For view specs, you can use
|
||||
|:Espec|, or define your own navigation commands:
|
||||
>
|
||||
Rnavcommand specview spec/views -glob=**/* -suffix=_spec.rb
|
||||
<
|
||||
ABBREVIATIONS *rails-abbreviations* *rails-snippets*
|
||||
|
||||
Abbreviations are "snippets lite". They may later be extracted into a
|
||||
separate plugin, or removed entirely.
|
||||
|
||||
*rails-:Rabbrev*
|
||||
:Rabbrev List all Rails abbreviations.
|
||||
|
||||
:Rabbrev {abbr} {expn} [{extra}]
|
||||
Define a new Rails abbreviation. {extra} is permitted
|
||||
if and only if {expn} ends with "(".
|
||||
|
||||
*rails-:Rabbrev!*
|
||||
:Rabbrev! {abbr} Remove an abbreviation.
|
||||
|
||||
Rails abbreviations differ from regular abbreviations in that they only expand
|
||||
after a <C-]> (see |i_CTRL-]|) or a <Tab> (if <Tab> does not work, it is
|
||||
likely mapped by another plugin). If the abbreviation ends in certain
|
||||
punctuation marks, additional expansions are possible. A few examples will
|
||||
hopefully clear this up (all of the following are enabled by default in
|
||||
appropriate file types).
|
||||
|
||||
Command Sequence typed Resulting text ~
|
||||
Rabbrev rp( render :partial\ => rp( render(:partial =>
|
||||
Rabbrev rp( render :partial\ => rp<Tab> render :partial =>
|
||||
Rabbrev vs( validates_size_of vs( validates_size_of(
|
||||
Rabbrev pa[ params pa[:id] params[:id]
|
||||
Rabbrev pa[ params pa<C-]> params
|
||||
Rabbrev pa[ params pa.inspect params.inspect
|
||||
Rabbrev AR:: ActionRecord AR::Base ActiveRecord::Base
|
||||
|
||||
In short, ( expands on (, :: expands on . and :, and [ expands on . and [.
|
||||
These trailing punctuation marks are NOT part of the final abbreviation, and
|
||||
you cannot have two mappings that differ only by punctuation.
|
||||
|
||||
You must escape spaces in your expansion, either as "\ " or as "<Space>". For
|
||||
an abbreviation ending with "(", you may define where to insert the
|
||||
parenthesis by splitting the expansion into two parts (divided by an unescaped
|
||||
space).
|
||||
|
||||
You can also define abbreviations as a hash in |g:rails_abbreviations| or by
|
||||
using |rails-projection-abbreviations|:
|
||||
>
|
||||
let g:rails_abbreviations = {
|
||||
\ "AE::": "ActiveResource",
|
||||
\ "p[": "params",
|
||||
\ "rj(": ["render", "json: "]}
|
||||
<
|
||||
Many abbreviations are provided by default: use :Rabbrev to list them. They
|
||||
vary depending on the type of file (models have different abbreviations than
|
||||
controllers).
|
||||
|
||||
SYNTAX HIGHLIGHTING *rails-syntax*
|
||||
|
||||
Syntax highlighting is by and large a transparent process. For the full
|
||||
effect, however, you need a colorscheme which accentuates rails.vim
|
||||
extensions. One such colorscheme is vividchalk, available from vim.org.
|
||||
|
||||
The following is a summary of the changes made by rails.vim to the standard
|
||||
syntax highlighting.
|
||||
|
||||
*rails-syntax-keywords*
|
||||
Rails specific keywords are highlighted in a filetype specific manner. For
|
||||
example, in a model, has_many is highlighted, whereas in a controller,
|
||||
before_filter is highlighted. A wide variety of syntax groups are used but
|
||||
they all link by default to railsMethod.
|
||||
|
||||
*rails-syntax-classes*
|
||||
Models, helpers, and controllers are given special highlighting. Depending on
|
||||
the version of Vim installed, you may need a rails.vim aware colorscheme in
|
||||
order to see this. Said colorscheme needs to provide highlighting for the
|
||||
railsUserClass syntax group.
|
||||
|
||||
The class names are determined by camelizing filenames from certain
|
||||
directories of your application. If app/models/line_item.rb exists, the class
|
||||
"LineItem" will be highlighted.
|
||||
|
||||
The list of classes is refreshed automatically after certain commands like
|
||||
|:Rgenerate|. Use |:Rrefresh| to trigger the process manually.
|
||||
|
||||
*rails-syntax-assertions*
|
||||
If you define custom assertions in test_helper.rb, these will be highlighted
|
||||
in your tests. These are found by scanning test_helper.rb for lines of the
|
||||
form " def assert_..." and extracting the method name. The railsUserMethod
|
||||
syntax group is used. The list of assertions can be refreshed with
|
||||
|:Rrefresh|.
|
||||
|
||||
*rails-syntax-strings*
|
||||
A string literal using %Q<> or %<> delimiters will have its contents
|
||||
highlighted as HTML. This is sometimes useful when writing helpers. >
|
||||
link = %<<a href="http://www.vim.org">Vim</a>>.html_safe
|
||||
<
|
||||
*rails-syntax-yaml*
|
||||
YAML syntax highlighting has been extended to highlight eRuby, which can be
|
||||
used in most Rails YAML files (including database.yml and fixtures).
|
||||
|
||||
MANAGED VIM OPTIONS *rails-options*
|
||||
|
||||
The following options are set local to buffers where the plugin is active.
|
||||
|
||||
*rails-'shiftwidth'* *rails-'sw'*
|
||||
*rails-'softtabstop'* *rails-'sts'*
|
||||
*rails-'expandtab'* *rails-'et'*
|
||||
Indent settings are no longer adjusted by default. Install sleuth.vim, or try
|
||||
this in your vimrc instead: >
|
||||
autocmd FileType ruby set sw=2 sts=2 et
|
||||
<
|
||||
*rails-'path'* *rails-'pa'*
|
||||
All the relevant directories from your application are added to your 'path'.
|
||||
This makes it easy to access a buried file: >
|
||||
:find blog_controller
|
||||
<
|
||||
*rails-'includeexpr'* *rails-'inex'*
|
||||
The 'includeexpr' option is set to enable the magic described in |rails-gf|.
|
||||
|
||||
*rails-'filetype'* *rails-'ft'*
|
||||
The 'filetype' is sometimes adjusted for Rails files. Most notably, *.rxml
|
||||
and *.rjs are treated as Ruby files, and files that have been falsely
|
||||
identified as Mason sources are changed back to eRuby files (but only when
|
||||
they are part of a Rails application).
|
||||
|
||||
*rails-'completefunc'* *rails-'cfu'*
|
||||
A 'completefunc' is provided (if not already set). It is very simple, as it
|
||||
uses syntax highlighting to make its guess. See |i_CTRL-X_CTRL-U|.
|
||||
|
||||
PROJECTIONS *rails-config/projections.json* *rails-projections*
|
||||
|
||||
The bulk of rails.vim features support core Rails conventions and a just a
|
||||
handful of popular additions (such as RSpec). Projections let you teach
|
||||
rails.vim about app specific and gem specific behavior.
|
||||
|
||||
There are four primary ways to define projections:
|
||||
|
||||
1. Globally, in |g:rails_projections|.
|
||||
2. Per app, in config/projections.json.
|
||||
3. Per bundled gem, in |g:rails_gem_projections| (requires bundler.vim).
|
||||
4. Inside a bundled gem, in lib/rails/projections.json (requires bundler.vim).
|
||||
|
||||
Vim syntax looks a lot like JSON, but with funky |line-continuation|:
|
||||
>
|
||||
let g:rails_projections = {
|
||||
\ "app/uploaders/*_uploader.rb": {
|
||||
\ "command": "uploader",
|
||||
\ "template":
|
||||
\ "class %SUploader < CarrierWave::Uploader::Base\nend",
|
||||
\ "test": [
|
||||
\ "test/unit/%s_uploader_test.rb",
|
||||
\ "spec/models/%s_uploader_spec.rb"
|
||||
\ ],
|
||||
\ "keywords": "process version"
|
||||
\ },
|
||||
\ "features/support/*.rb": {"command": "support"},
|
||||
\ "features/support/env.rb": {"command": "support"}}
|
||||
|
||||
Keys can be either literal file names or globs containing a single asterisk.
|
||||
In the latter case, you can use placeholders in the values to plug in some
|
||||
variant of the variable portion:
|
||||
|
||||
%s: original
|
||||
%p: pluralized
|
||||
%i: singularized
|
||||
%S: camelized
|
||||
%h: humanized
|
||||
|
||||
The full list of available options is as follows:
|
||||
|
||||
*rails-projection-alternate*
|
||||
"alternate" ~
|
||||
Determines the destination of the |rails-:A| command. If this is a
|
||||
list, the first readable file will be used.
|
||||
*rails-projection-related*
|
||||
"related" ~
|
||||
Determines the destination of the |rails-:R| and :.A commands. In
|
||||
addition to the standard placeholders, %d can be used for the current
|
||||
'define' match (typically a method).
|
||||
*rails-projection-test*
|
||||
"test" ~
|
||||
Determines the default test file to run with |rails-:Rrunner| and
|
||||
|rails-:Rake|. Also serves as a default for "alternate".
|
||||
*rails-projection-task*
|
||||
"task" ~
|
||||
Determines the default rake task to run. Provide %l or %d to
|
||||
substitute the current line or 'define' match (typically a method), or
|
||||
just a bare % (like |:_%|) to substitute the current file name. If a
|
||||
list with two tasks is provided, the first will be used when a line
|
||||
number is given, and the second when it's omitted.
|
||||
*rails-projection-compiler*
|
||||
"compiler" ~
|
||||
Determines the |:compiler| plugin to use with |rails-:Rrunner|.
|
||||
*rails-projection-keywords*
|
||||
"keywords" ~
|
||||
Provides a whitespace delimited list of keywords to syntax highlight.
|
||||
*rails-projection-abbreviations*
|
||||
"abbreviations" ~
|
||||
Provides a dictionary of abbreviations to define. See
|
||||
|rails-abbreviations|. You might consider setting this in a "*"
|
||||
projection.
|
||||
*rails-projection-command*
|
||||
"command" ~
|
||||
Names a navigation command to be created. Use the same name on
|
||||
multiple projections to combine them into a single command. Glob
|
||||
keys are used when the command is given an argument, and literal file
|
||||
keys are used when no argument is given. See the "features/support"
|
||||
entries above for an example :Esupport that defaults to env.
|
||||
*rails-projection-affinity*
|
||||
"affinity" ~
|
||||
Provide this if the root of your file name corresponds to either
|
||||
a model or controller. The root of a helper generally corresponds to
|
||||
a controller, for example, so a "helper" projection would have an
|
||||
"affinity" of "controller". You can also provide "collection" if it
|
||||
corresponds to a plural model (e.g., fixtures), or "resource" if it
|
||||
corresponds to a singular controller. Providing this lets you use
|
||||
other affiliated commands without an argument, and determines the
|
||||
default if a command has no literal file name.
|
||||
*rails-projection-template*
|
||||
"template" ~
|
||||
If you provide a ! after the argument to the navigation command (that
|
||||
is, :Euploader foo!, NOT :Euploader! foo), and a new file is created,
|
||||
this will be used as the body.
|
||||
|
||||
CONFIGURATION *rails-configuration*
|
||||
|
||||
In addition to projections (described above) and the crude hammer of global
|
||||
settings (described below), rails.vim provides a few different mechanisms for
|
||||
configuration.
|
||||
|
||||
*rails-:autocmd* *rails-autocommands*
|
||||
If you would like to set your own custom Vim settings whenever a Rails file is
|
||||
loaded, you can use an autocommand like the following in your vimrc: >
|
||||
|
||||
autocmd User Rails silent! Lcd
|
||||
autocmd User Rails map <buffer> <F9> :Rake<CR>
|
||||
|
||||
There used to be autocommands that fire based on the "type" or file name of
|
||||
the buffer, but they have been removed. If you still need to execute code for
|
||||
certain file types only, use the bare User Rails event above and check
|
||||
rails#buffer().relative() for the path relative to the Rails root.
|
||||
|
||||
*macros/rails.vim*
|
||||
If you have several commands to run on initialization for all file types, they
|
||||
can be placed in a "macros/rails.vim" file in the 'runtimepath' (for example,
|
||||
"~/.vim/macros/rails.vim"). This file is sourced by rails.vim each time a
|
||||
Rails file is loaded.
|
||||
|
||||
*config/rails.vim*
|
||||
This file used to be sourced automatically from the root of the application,
|
||||
but has been superseded by |rails-projections|.
|
||||
|
||||
*rails-:Rnavcommand*
|
||||
:Rnavcommand This command has been superseded by
|
||||
|rails-projections|.
|
||||
|
||||
*rails-:Rset*
|
||||
:Rset This command has been superseded by
|
||||
|rails-projections|.
|
||||
|
||||
GLOBAL SETTINGS *rails-global-settings*
|
||||
|
||||
When all else fails, set a global.
|
||||
|
||||
*g:rails_abbreviations*
|
||||
Dictionary of additional abbreviations. See |rails-abbreviations|.
|
||||
|
||||
This variable was formerly used to globally disable abbreviations. Use
|
||||
g:rails_no_abbreviations if you want to do that.
|
||||
|
||||
*g:rails_ctags_arguments*
|
||||
Additional arguments to pass to ctags from |:Ctags|. Defaults to ignoring
|
||||
JavaScript files, since ctags has a tendency to choke on those.
|
||||
>
|
||||
let g:rails_ctags_arguments = ['--languages=-javascript']
|
||||
<
|
||||
*g:rails_projections* >
|
||||
Defines the set of globally available projections. See |rails-projections|.
|
||||
Where possible, it is generally advisable to use |g:rails_gem_projections| or
|
||||
|config/projections.json| instead.
|
||||
|
||||
*g:rails_gem_projections*
|
||||
This is a dictionary where the keys are gem names and the values are
|
||||
projection dictionaries. Projections are only used if the given gem is
|
||||
bundled (requires bundler.vim).
|
||||
>
|
||||
let g:rails_gem_projections = {
|
||||
\ "active_model_serializers": {
|
||||
\ "app/serializers/*_serializer.rb": {
|
||||
\ "command": "serializer",
|
||||
\ "affinity": "model"}},
|
||||
\ "fabrication": {
|
||||
\ "spec/fabricators/*_fabricator.rb": {
|
||||
\ "command": "fabricator",
|
||||
\ "affinity": "model",
|
||||
\ "alternate": "app/models/%s.rb",
|
||||
\ "related": "db/schema.rb#%p",
|
||||
\ "test": "spec/models/%s_spec.rb",
|
||||
\ "template": "Fabricator :%s do\nend"}}}
|
||||
<
|
||||
See |rails-projections|. Generally, you should prefer these gem projections
|
||||
over global projections to avoid getting a bunch of useless commands in every
|
||||
single project.
|
||||
|
||||
Gem maintainers may also provide custom projections by placing them in
|
||||
lib/rails/projections.json.
|
||||
|
||||
ABOUT *rails-about* *rails-plugin-author*
|
||||
|
||||
The latest stable version can be found at
|
||||
http://www.vim.org/scripts/script.php?script_id=1567
|
||||
|
||||
Bugs can be reported and the very latest development version can be retrieved
|
||||
from GitHub:
|
||||
https://github.com/tpope/vim-rails >
|
||||
git clone git://github.com/tpope/vim-rails.git
|
||||
<
|
||||
*rails-license*
|
||||
Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
|
||||
See |license|.
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
|
@ -1,128 +0,0 @@
|
|||
" rails.vim - Detect a rails application
|
||||
" Author: Tim Pope <http://tpo.pe/>
|
||||
" GetLatestVimScripts: 1567 1 :AutoInstall: rails.vim
|
||||
|
||||
" Install this file as plugin/rails.vim.
|
||||
|
||||
if exists('g:loaded_rails') || &cp || v:version < 700
|
||||
finish
|
||||
endif
|
||||
let g:loaded_rails = 1
|
||||
|
||||
" Utility Functions {{{1
|
||||
|
||||
function! s:error(str)
|
||||
echohl ErrorMsg
|
||||
echomsg a:str
|
||||
echohl None
|
||||
let v:errmsg = a:str
|
||||
endfunction
|
||||
|
||||
function! s:autoload(...)
|
||||
if !exists("g:autoloaded_rails") && v:version >= 700
|
||||
runtime! autoload/rails.vim
|
||||
endif
|
||||
if exists("g:autoloaded_rails")
|
||||
if a:0
|
||||
exe a:1
|
||||
endif
|
||||
return 1
|
||||
endif
|
||||
if !exists("g:rails_no_autoload_warning")
|
||||
let g:rails_no_autoload_warning = 1
|
||||
if v:version >= 700
|
||||
call s:error("Disabling rails.vim: autoload/rails.vim is missing")
|
||||
else
|
||||
call s:error("Disabling rails.vim: Vim version 7 or higher required")
|
||||
endif
|
||||
endif
|
||||
return ""
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
" Detection {{{1
|
||||
|
||||
function! s:Detect(filename)
|
||||
if exists('b:rails_root')
|
||||
return s:BufInit(b:rails_root)
|
||||
endif
|
||||
let fn = substitute(fnamemodify(a:filename,":p"),'\c^file://','','')
|
||||
let sep = matchstr(fn,'^[^\\/]\{3,\}\zs[\\/]')
|
||||
if sep != ""
|
||||
let fn = getcwd().sep.fn
|
||||
endif
|
||||
if isdirectory(fn)
|
||||
let fn = fnamemodify(fn,':s?[\/]$??')
|
||||
else
|
||||
let fn = fnamemodify(fn,':s?\(.*\)[\/][^\/]*$?\1?')
|
||||
endif
|
||||
let ofn = ""
|
||||
while fn != ofn
|
||||
if filereadable(fn . "/config/environment.rb")
|
||||
return s:BufInit(resolve(fn))
|
||||
endif
|
||||
let ofn = fn
|
||||
let fn = fnamemodify(ofn,':h')
|
||||
endwhile
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:BufInit(path)
|
||||
if s:autoload()
|
||||
return RailsBufInit(a:path)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
" Initialization {{{1
|
||||
|
||||
augroup railsPluginDetect
|
||||
autocmd!
|
||||
autocmd BufNewFile,BufRead * call s:Detect(expand("<afile>:p"))
|
||||
autocmd VimEnter * if expand("<amatch>") == "" && !exists("b:rails_root") | call s:Detect(getcwd()) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif
|
||||
autocmd FileType netrw if !exists("b:rails_root") | call s:Detect(expand("%:p")) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif
|
||||
autocmd BufEnter * if exists("b:rails_root")|silent doau User BufEnterRails|endif
|
||||
autocmd BufLeave * if exists("b:rails_root")|silent doau User BufLeaveRails|endif
|
||||
autocmd Syntax railslog if s:autoload()|call rails#log_syntax()|endif
|
||||
augroup END
|
||||
|
||||
command! -bar -bang -nargs=* -complete=dir Rails :if s:autoload()|execute rails#new_app_command(<bang>0,<f-args>)|endif
|
||||
|
||||
" }}}1
|
||||
" abolish.vim support {{{1
|
||||
|
||||
function! s:function(name)
|
||||
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
|
||||
endfunction
|
||||
|
||||
augroup railsPluginAbolish
|
||||
autocmd!
|
||||
autocmd VimEnter * call s:abolish_setup()
|
||||
augroup END
|
||||
|
||||
function! s:abolish_setup()
|
||||
if exists('g:Abolish') && has_key(g:Abolish,'Coercions')
|
||||
if !has_key(g:Abolish.Coercions,'l')
|
||||
let g:Abolish.Coercions.l = s:function('s:abolish_l')
|
||||
endif
|
||||
if !has_key(g:Abolish.Coercions,'t')
|
||||
let g:Abolish.Coercions.t = s:function('s:abolish_t')
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:abolish_l(word)
|
||||
let singular = rails#singularize(a:word)
|
||||
return a:word ==? singular ? rails#pluralize(a:word) : singular
|
||||
endfunction
|
||||
|
||||
function! s:abolish_t(word)
|
||||
if a:word =~# '\u'
|
||||
return rails#pluralize(rails#underscore(a:word))
|
||||
else
|
||||
return rails#singularize(rails#camelize(a:word))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
" vim:set sw=2 sts=2:
|
|
@ -1 +0,0 @@
|
|||
Subproject commit d25c7ebb65a0ca3058d075158ce1b6605c954c82
|
1
vim/bundle/webapi-vim/.gitignore
vendored
1
vim/bundle/webapi-vim/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
doc/tags
|
|
@ -1,11 +0,0 @@
|
|||
all : webapi-vim.zip
|
||||
|
||||
remove-zip:
|
||||
-rm -f doc/tags
|
||||
-rm -f webapi-vim.zip
|
||||
|
||||
webapi-vim.zip: remove-zip
|
||||
zip -r webapi-vim.zip autoload doc README
|
||||
|
||||
release: webapi-vim.zip
|
||||
vimup update-script webapi.vim
|
|
@ -1,34 +0,0 @@
|
|||
webapi-vim: Vim Interface to Web API
|
||||
|
||||
Description:
|
||||
Interface to WEB APIs.
|
||||
Currently this library support following protocols.
|
||||
|
||||
* Basic HTTP
|
||||
* OAuth
|
||||
* Atompub
|
||||
* SOAP (in progress)
|
||||
* XMLRPC
|
||||
* MetaWeblog API
|
||||
|
||||
This library contains:
|
||||
XML Parser
|
||||
HTML Parser(Hack Way)
|
||||
JSON Praser
|
||||
BASE64 Hash Algorism
|
||||
SHA1 Hash Algorism
|
||||
HMAC HASH Algorism
|
||||
Bit Operation Library
|
||||
Converter for "UTF-8 to Unicode"
|
||||
|
||||
Require:
|
||||
|
||||
curl command : http://curl.haxx.se/
|
||||
|
||||
Thanks To:
|
||||
|
||||
Yukihiro Nakadaira : http://sites.google.com/site/yukihironakadaira/
|
||||
autoload/base64.vim (I added small changes)
|
||||
autoload/hmac.vim
|
||||
autoload/sha1.vim
|
||||
|
|
@ -1,226 +0,0 @@
|
|||
" atom
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc5023.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:system = function(get(g:, 'webapi#system_function', 'system'))
|
||||
|
||||
let s:author_template = {
|
||||
\ "name": "",
|
||||
\}
|
||||
|
||||
let s:link_template = {
|
||||
\ "rel": "",
|
||||
\ "href": "",
|
||||
\}
|
||||
|
||||
let s:category_template = {
|
||||
\ "term": "",
|
||||
\ "scheme": "",
|
||||
\ "label": "",
|
||||
\}
|
||||
|
||||
let s:feed_template = {
|
||||
\ "id": "",
|
||||
\ "icon": "",
|
||||
\ "logo": "",
|
||||
\ "title": "",
|
||||
\ "link": [],
|
||||
\ "category": [],
|
||||
\ "author": [],
|
||||
\ "contirubutor": [],
|
||||
\ "entry": [],
|
||||
\}
|
||||
|
||||
let s:entry_template = {
|
||||
\ "id": "",
|
||||
\ "icon": "",
|
||||
\ "logo": "",
|
||||
\ "title": "",
|
||||
\ "link": [],
|
||||
\ "category": [],
|
||||
\ "author": [],
|
||||
\ "contirubutor": [],
|
||||
\ "copyright": "",
|
||||
\ "content": "",
|
||||
\ "content.type": "text/plain",
|
||||
\ "content.mode": "escaped",
|
||||
\ "summary": "",
|
||||
\ "created": "",
|
||||
\ "updated": "",
|
||||
\}
|
||||
|
||||
for s:name in ['author', 'link', 'category', 'feed', 'entry']
|
||||
for s:key in keys(eval('s:'.s:name.'_template'))
|
||||
let key = substitute(s:key, '\.\(.\)', '\=toupper(submatch(1))', '')
|
||||
exe "function s:".s:name."_template.set".toupper(key[0]).key[1:]."(v) dict\n"
|
||||
\. " let self['".s:key."'] = a:v\n"
|
||||
\. "endfunction\n"
|
||||
exe "function s:".s:name."_template.get".toupper(key[0]).key[1:]."() dict\n"
|
||||
\. " return self['".s:key."']\n"
|
||||
\. "endfunction\n"
|
||||
endfor
|
||||
endfor
|
||||
function s:entry_template.setContentFromFile(file) dict
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
let bits = substitute(s:system("xxd -ps ".quote.file.quote), "[ \n\r]", '', 'g')
|
||||
let self['mode'] = "base64"
|
||||
let self['content'] = webapi#base64#b64encodebin(bits)
|
||||
endfunction
|
||||
|
||||
unlet s:name
|
||||
unlet s:key
|
||||
|
||||
function! webapi#atom#newEntry()
|
||||
return deepcopy(s:entry_template)
|
||||
endfunction
|
||||
|
||||
function! s:createXml(entry)
|
||||
let entry = webapi#xml#createElement("entry")
|
||||
let entry.attr["xmlns"] = "http://purl.org/atom/ns#"
|
||||
|
||||
for key in keys(a:entry)
|
||||
if type(a:entry[key]) == 1 && key !~ '\.'
|
||||
let node = webapi#xml#createElement(key)
|
||||
call node.value(a:entry[key])
|
||||
if key == "content"
|
||||
let node.attr["type"] = a:entry['content.type']
|
||||
let node.attr["mode"] = a:entry['content.mode']
|
||||
endif
|
||||
call add(entry.child, node)
|
||||
endif
|
||||
endfor
|
||||
let xml = '<?xml version="1.0" encoding="utf-8"?>' . entry.toString()
|
||||
return iconv(xml, &encoding, "utf-8")
|
||||
endfunction
|
||||
|
||||
function! s:createWsse(user, pass)
|
||||
let now = localtime()
|
||||
let nonce = webapi#sha1#sha1(now . " " . now)[0:28]
|
||||
let created = strftime("%Y-%m-%dT%H:%M:%SZ", now)
|
||||
let passworddigest = webapi#base64#b64encodebin(webapi#sha1#sha1(nonce.created.a:pass))
|
||||
let nonce = webapi#base64#b64encode(nonce)
|
||||
return 'UsernameToken Username="'.a:user.'", PasswordDigest="'.passworddigest.'", Nonce="'.nonce.'", Created="'.created.'"'
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#deleteEntry(uri, user, pass)
|
||||
let res = webapi#http#post(a:uri, "",
|
||||
\ {
|
||||
\ "Content-Type": "application/x.atom+xml",
|
||||
\ "X-WSSE": s:createWsse(a:user, a:pass)
|
||||
\ }, "DELETE")
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#updateEntry(uri, user, pass, entry, ...)
|
||||
let headdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata["Content-Type"] = "application/x.atom+xml"
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
let res = webapi#http#post(a:uri, s:createXml(a:entry), headdata, "PUT")
|
||||
let location = filter(res.header, 'v:val =~ "^Location:"')
|
||||
if len(location)
|
||||
return split(location[0], '\s*:\s\+')[1]
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#createEntry(uri, user, pass, entry, ...)
|
||||
let headdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata["Content-Type"] = "application/x.atom+xml"
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
let headdata["WWW-Authenticate"] = "WSSE profile=\"UsernameToken\""
|
||||
let res = webapi#http#post(a:uri, s:createXml(a:entry), headdata, "POST")
|
||||
let location = filter(res.header, 'v:val =~ "^Location:"')
|
||||
if len(location)
|
||||
return split(location[0], '\s*:\s\+')[1]
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:parse_node(target, parent)
|
||||
for node in a:parent.child
|
||||
if type(node) != 4 || !has_key(a:target, node.name)
|
||||
unlet node
|
||||
continue
|
||||
endif
|
||||
if node.name == 'content'
|
||||
let a:target[node.name] = node.value()
|
||||
if has_key(node.attr, 'type')
|
||||
let a:target['content.type'] = node.attr['type']
|
||||
endif
|
||||
if has_key(node.attr, 'type')
|
||||
let a:target['content.type'] = node.attr['type']
|
||||
endif
|
||||
elseif node.name == 'link'
|
||||
let link = deepcopy(s:link_template)
|
||||
for attr in keys(node.attr)
|
||||
if !has_key(link, attr)
|
||||
continue
|
||||
endif
|
||||
let link[attr] = node.attr[attr]
|
||||
endfor
|
||||
call add(a:target.link, link)
|
||||
elseif node.name == 'author'
|
||||
let author = deepcopy(s:author_template)
|
||||
for item in node.child
|
||||
if type(item) == 4 && has_key(author, item.name)
|
||||
let author[item.name] = item.value()
|
||||
endif
|
||||
unlet item
|
||||
endfor
|
||||
call add(a:target.author, author)
|
||||
elseif node.name == 'entry'
|
||||
let entry = deepcopy(s:entry_template)
|
||||
call s:parse_node(entry, node)
|
||||
call add(a:target.entry, entry)
|
||||
elseif type(a:target[node.name]) == 3
|
||||
call add(a:target[node.name], parent.value())
|
||||
else
|
||||
let a:target[node.name] = node.value()
|
||||
endif
|
||||
unlet node
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#getFeed(uri, user, pass)
|
||||
let headdata = {}
|
||||
if len(a:user) > 0 && len(a:pass) > 0
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
endif
|
||||
let res = webapi#http#get(a:uri, {}, headdata)
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
let feed = deepcopy(s:feed_template)
|
||||
call s:parse_node(feed, dom)
|
||||
return feed
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#getService(uri, user, pass)
|
||||
let headdata = {}
|
||||
if len(a:user) > 0 && len(a:pass) > 0
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
endif
|
||||
let res = webapi#http#get(a:uri, {}, headdata)
|
||||
return webapi#xml#parse(res.content)
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#getEntry(uri, user, pass)
|
||||
let headdata = {}
|
||||
if len(a:user) > 0 && len(a:pass) > 0
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
endif
|
||||
let res = webapi#http#get(a:uri, {}, headdata)
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
let entry = deepcopy(s:entry_template)
|
||||
call s:parse_node(entry, dom)
|
||||
return entry
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,140 +0,0 @@
|
|||
" base64 codec
|
||||
" Last Change: 2010-07-25
|
||||
" Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" [The Base16, Base32, and Base64 Data Encodings]
|
||||
" http://tools.ietf.org/rfc/rfc3548.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#base64#b64encode(data)
|
||||
let b64 = s:b64encode(s:str2bytes(a:data), s:standard_table, '=')
|
||||
return join(b64, '')
|
||||
endfunction
|
||||
|
||||
function! webapi#base64#b64encodebin(data)
|
||||
let b64 = s:b64encode(s:binstr2bytes(a:data), s:standard_table, '=')
|
||||
return join(b64, '')
|
||||
endfunction
|
||||
|
||||
function! webapi#base64#b64decode(data)
|
||||
let bytes = s:b64decode(split(a:data, '\zs'), s:standard_table, '=')
|
||||
return s:bytes2str(bytes)
|
||||
endfunction
|
||||
|
||||
function! webapi#base64#test()
|
||||
if webapi#base64#b64encode("hello, world") ==# "aGVsbG8sIHdvcmxk"
|
||||
echo "test1: ok"
|
||||
else
|
||||
echoerr "test1: failed"
|
||||
endif
|
||||
if webapi#base64#b64encode("hello, worldx") ==# "aGVsbG8sIHdvcmxkeA=="
|
||||
echo "test2: ok"
|
||||
else
|
||||
echoerr "test2: failed"
|
||||
endif
|
||||
if webapi#base64#b64encode("hello, worldxx") ==# "aGVsbG8sIHdvcmxkeHg="
|
||||
echo "test3: ok"
|
||||
else
|
||||
echoerr "test3: falied"
|
||||
endif
|
||||
if webapi#base64#b64encode("hello, worldxxx") ==# "aGVsbG8sIHdvcmxkeHh4"
|
||||
echo "test4: ok"
|
||||
else
|
||||
echoerr "test4: falied"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, world")) ==# "hello, world"
|
||||
echo "test5: ok"
|
||||
else
|
||||
echoerr "test5: failed"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, worldx")) ==# "hello, worldx"
|
||||
echo "test6: ok"
|
||||
else
|
||||
echoerr "test6: failed"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, worldxx")) ==# "hello, worldxx"
|
||||
echo "test7: ok"
|
||||
else
|
||||
echoerr "test7: failed"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, worldxxx")) ==# "hello, worldxxx"
|
||||
echo "test8: ok"
|
||||
else
|
||||
echoerr "test8: failed"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:standard_table = [
|
||||
\ "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
|
||||
\ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
|
||||
\ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
|
||||
\ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"]
|
||||
|
||||
let s:urlsafe_table = [
|
||||
\ "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
|
||||
\ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
|
||||
\ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
|
||||
\ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","-","_"]
|
||||
|
||||
function! s:b64encode(bytes, table, pad)
|
||||
let b64 = []
|
||||
for i in range(0, len(a:bytes) - 1, 3)
|
||||
let n = a:bytes[i] * 0x10000
|
||||
\ + get(a:bytes, i + 1, 0) * 0x100
|
||||
\ + get(a:bytes, i + 2, 0)
|
||||
call add(b64, a:table[n / 0x40000])
|
||||
call add(b64, a:table[n / 0x1000 % 0x40])
|
||||
call add(b64, a:table[n / 0x40 % 0x40])
|
||||
call add(b64, a:table[n % 0x40])
|
||||
endfor
|
||||
if len(a:bytes) % 3 == 1
|
||||
let b64[-1] = a:pad
|
||||
let b64[-2] = a:pad
|
||||
endif
|
||||
if len(a:bytes) % 3 == 2
|
||||
let b64[-1] = a:pad
|
||||
endif
|
||||
return b64
|
||||
endfunction
|
||||
|
||||
function! s:b64decode(b64, table, pad)
|
||||
let a2i = {}
|
||||
for i in range(len(a:table))
|
||||
let a2i[a:table[i]] = i
|
||||
endfor
|
||||
let bytes = []
|
||||
for i in range(0, len(a:b64) - 1, 4)
|
||||
let n = a2i[a:b64[i]] * 0x40000
|
||||
\ + a2i[a:b64[i + 1]] * 0x1000
|
||||
\ + (a:b64[i + 2] == a:pad ? 0 : a2i[a:b64[i + 2]]) * 0x40
|
||||
\ + (a:b64[i + 3] == a:pad ? 0 : a2i[a:b64[i + 3]])
|
||||
call add(bytes, n / 0x10000)
|
||||
call add(bytes, n / 0x100 % 0x100)
|
||||
call add(bytes, n % 0x100)
|
||||
endfor
|
||||
if a:b64[-1] == a:pad
|
||||
unlet a:b64[-1]
|
||||
endif
|
||||
if a:b64[-2] == a:pad
|
||||
unlet a:b64[-1]
|
||||
endif
|
||||
return bytes
|
||||
endfunction
|
||||
|
||||
function! s:binstr2bytes(str)
|
||||
return map(range(len(a:str)/2), 'eval("0x".a:str[v:val*2 : v:val*2+1])')
|
||||
endfunction
|
||||
|
||||
function! s:str2bytes(str)
|
||||
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
|
||||
endfunction
|
||||
|
||||
function! s:bytes2str(bytes)
|
||||
return eval('"' . join(map(copy(a:bytes), 'printf(''\x%02x'', v:val)'), '') . '"')
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
|
@ -1,56 +0,0 @@
|
|||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#bit#dec2bin(v)
|
||||
let v = a:v
|
||||
if v == 0 | return 0 | endif
|
||||
let ret = ""
|
||||
while v > 0
|
||||
let i = v % 2
|
||||
let ret = i . ret
|
||||
let v = v / 2
|
||||
endwhile
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#bin2dec(v)
|
||||
let v = a:v
|
||||
if len(v) == 0 | return 0 | endif
|
||||
let i = 1
|
||||
let ret = ""
|
||||
for n in reverse(split(v, '\zs'))
|
||||
if n == 1
|
||||
let ret = ret + i
|
||||
endif
|
||||
let i = i * 2
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#or(a,b)
|
||||
let a = webapi#bit#dec2bin(a:a)
|
||||
let b = webapi#bit#dec2bin(a:b)
|
||||
return webapi#bit#bin2dec(tr((a + b), '2', '1'))
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#and(a,b)
|
||||
let a = webapi#bit#dec2bin(a:a)
|
||||
let b = webapi#bit#dec2bin(a:b)
|
||||
return webapi#bit#bin2dec(tr((a + b), '21', '10'))
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#shift(a,b)
|
||||
let a = webapi#bit#dec2bin(a:a)
|
||||
let a = repeat('0', 32-len(a)) . a
|
||||
if a:b < 0
|
||||
let a = (repeat('0', -a:b) . a[: a:b-1])[-32:]
|
||||
elseif a:b > 0
|
||||
let a = (a . repeat('0', a:b))[-32:]
|
||||
endif
|
||||
return webapi#bit#bin2dec(a)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,53 +0,0 @@
|
|||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:attr(node, name)
|
||||
let n = a:node.childNode(a:name)
|
||||
if empty(n)
|
||||
return ""
|
||||
endif
|
||||
return n.value()
|
||||
endfunction
|
||||
|
||||
function! webapi#feed#parseURL(url)
|
||||
let dom = webapi#xml#parseURL(a:url)
|
||||
let items = []
|
||||
if dom.name == 'rss'
|
||||
let channel = dom.childNode('channel')
|
||||
for item in channel.childNodes('item')
|
||||
call add(items, {
|
||||
\ "title": s:attr(item, 'title'),
|
||||
\ "link": s:attr(item, 'link'),
|
||||
\ "content": s:attr(item, 'description'),
|
||||
\ "id": s:attr(item, 'guid'),
|
||||
\ "date": s:attr(item, 'pubDate'),
|
||||
\})
|
||||
endfor
|
||||
elseif dom.name == 'rdf:RDF'
|
||||
for item in dom.childNodes('item')
|
||||
call add(items, {
|
||||
\ "title": s:attr(item, 'title'),
|
||||
\ "link": s:attr(item, 'link'),
|
||||
\ "content": s:attr(item, 'description'),
|
||||
\ "id": s:attr(item, 'guid'),
|
||||
\ "date": s:attr(item, 'dc:date'),
|
||||
\})
|
||||
endfor
|
||||
elseif dom.name == 'feed'
|
||||
for item in dom.childNodes('entry')
|
||||
call add(items, {
|
||||
\ "title": s:attr(item, 'title'),
|
||||
\ "link": item.childNode('link').attr['href'],
|
||||
\ "content": s:attr(item, 'content'),
|
||||
\ "id": s:attr(item, 'id'),
|
||||
\ "date": s:attr(item, 'updated'),
|
||||
\})
|
||||
endfor
|
||||
endif
|
||||
return items
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,166 +0,0 @@
|
|||
" This is a port of rfc2104 hmac function.
|
||||
" http://www.ietf.org/rfc/rfc2104.txt
|
||||
" Last Change: 2010-02-13
|
||||
" Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
|
||||
" @param mixed key List or String
|
||||
" @param mixed text List or String
|
||||
" @param Funcref hash function digest_hex(key:List, text:List):String
|
||||
" @param Number blocksize
|
||||
function webapi#hmac#hmac(key, text, hash, blocksize)
|
||||
let key = (type(a:key) == type("")) ? s:str2bytes(a:key) : a:key
|
||||
let text = (type(a:text) == type("")) ? s:str2bytes(a:text) : a:text
|
||||
return s:Hmac(key, text, a:hash, a:blocksize)
|
||||
endfunction
|
||||
|
||||
function webapi#hmac#md5(key, text)
|
||||
return webapi#hmac#hmac(a:key, a:text, 'webapi#md5#md5bin', 64)
|
||||
endfunction
|
||||
|
||||
function webapi#hmac#sha1(key, text)
|
||||
return webapi#hmac#hmac(a:key, a:text, 'webapi#sha1#sha1bin', 64)
|
||||
endfunction
|
||||
|
||||
" http://www.ietf.org/rfc/rfc2202.txt
|
||||
" Test Cases for HMAC-MD5 and HMAC-SHA-1
|
||||
function webapi#hmac#test()
|
||||
" Test Cases for HMAC-MD5
|
||||
call s:test("md5: 1", "webapi#hmac#md5",
|
||||
\ repeat("\x0b", 16),
|
||||
\ "Hi There",
|
||||
\ "9294727a3638bb1c13f48ef8158bfc9d")
|
||||
call s:test("md5: 2", "webapi#hmac#md5",
|
||||
\ "Jefe",
|
||||
\ "what do ya want for nothing?",
|
||||
\ "750c783e6ab0b503eaa86e310a5db738")
|
||||
call s:test("md5: 3", "webapi#hmac#md5",
|
||||
\ repeat("\xaa", 16),
|
||||
\ repeat("\xdd", 50),
|
||||
\ "56be34521d144c88dbb8c733f0e8b3f6")
|
||||
call s:test("md5: 4", "webapi#hmac#md5",
|
||||
\ s:hex2bytes("0102030405060708090a0b0c0d0e0f10111213141516171819"),
|
||||
\ repeat([0xcd], 50),
|
||||
\ "697eaf0aca3a3aea3a75164746ffaa79")
|
||||
call s:test("md5: 5", "webapi#hmac#md5",
|
||||
\ repeat("\x0c", 16),
|
||||
\ "Test With Truncation",
|
||||
\ "56461ef2342edc00f9bab995690efd4c")
|
||||
call s:test("md5: 6", "webapi#hmac#md5",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
\ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd")
|
||||
call s:test("md5: 7", "webapi#hmac#md5",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
|
||||
\ "6f630fad67cda0ee1fb1f562db3aa53e")
|
||||
|
||||
" Test Cases for HMAC-SHA1
|
||||
call s:test("sha1: 1", "webapi#hmac#sha1",
|
||||
\ repeat("\x0b", 20),
|
||||
\ "Hi There",
|
||||
\ "b617318655057264e28bc0b6fb378c8ef146be00")
|
||||
call s:test("sha1: 2", "webapi#hmac#sha1",
|
||||
\ "Jefe",
|
||||
\ "what do ya want for nothing?",
|
||||
\ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")
|
||||
call s:test("sha1: 3", "webapi#hmac#sha1",
|
||||
\ repeat("\xaa", 20),
|
||||
\ repeat("\xdd", 50),
|
||||
\ "125d7342b9ac11cd91a39af48aa17b4f63f175d3")
|
||||
call s:test("sha1: 4", "webapi#hmac#sha1",
|
||||
\ s:hex2bytes("0102030405060708090a0b0c0d0e0f10111213141516171819"),
|
||||
\ repeat([0xcd], 50),
|
||||
\ "4c9007f4026250c6bc8414f9bf50c86c2d7235da")
|
||||
call s:test("sha1: 5", "webapi#hmac#sha1",
|
||||
\ repeat("\x0c", 20),
|
||||
\ "Test With Truncation",
|
||||
\ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04")
|
||||
call s:test("sha1: 6", "webapi#hmac#sha1",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
\ "aa4ae5e15272d00e95705637ce8a3b55ed402112")
|
||||
call s:test("sha1: 7", "webapi#hmac#sha1",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
|
||||
\ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91")
|
||||
endfunction
|
||||
|
||||
function s:test(name, func, key, data, digest)
|
||||
let result = call(a:func, [a:key, a:data])
|
||||
echo "test_case:" a:name
|
||||
echo "expect:" a:digest
|
||||
echo "result:" result
|
||||
if a:digest ==? result
|
||||
echo "test: OK"
|
||||
else
|
||||
echohl Error
|
||||
echo "test: NG"
|
||||
echohl None
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" @param List key
|
||||
" @param List text
|
||||
" @param Funcref hash
|
||||
" @param Number blocksize
|
||||
function! s:Hmac(key, text, hash, blocksize)
|
||||
let key = a:key
|
||||
if len(key) > a:blocksize
|
||||
let key = s:hex2bytes(call(a:hash, [key]))
|
||||
endif
|
||||
let k_ipad = repeat([0], a:blocksize)
|
||||
let k_opad = repeat([0], a:blocksize)
|
||||
for i in range(a:blocksize)
|
||||
let k_ipad[i] = s:bitwise_xor(get(key, i, 0), 0x36)
|
||||
let k_opad[i] = s:bitwise_xor(get(key, i, 0), 0x5c)
|
||||
endfor
|
||||
let hash1 = s:hex2bytes(call(a:hash, [k_ipad + a:text]))
|
||||
let hmac = call(a:hash, [k_opad + hash1])
|
||||
return hmac
|
||||
endfunction
|
||||
|
||||
function! s:str2bytes(str)
|
||||
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
|
||||
endfunction
|
||||
|
||||
function! s:hex2bytes(str)
|
||||
return map(split(a:str, '..\zs'), 'str2nr(v:val, 16)')
|
||||
endfunction
|
||||
|
||||
let s:xor = [
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE],
|
||||
\ [0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD],
|
||||
\ [0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC],
|
||||
\ [0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB],
|
||||
\ [0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA],
|
||||
\ [0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9],
|
||||
\ [0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8],
|
||||
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||||
\ [0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6],
|
||||
\ [0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5],
|
||||
\ [0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4],
|
||||
\ [0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3],
|
||||
\ [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2],
|
||||
\ [0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1],
|
||||
\ [0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0]
|
||||
\ ]
|
||||
|
||||
function! s:bitwise_xor(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a || b
|
||||
let r += s:xor[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) != (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
" html
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
"
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! webapi#html#decodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '>', '>', 'g')
|
||||
let str = substitute(str, '<', '<', 'g')
|
||||
let str = substitute(str, '"', '"', 'g')
|
||||
let str = substitute(str, ''', "'", 'g')
|
||||
let str = substitute(str, ' ', ' ', 'g')
|
||||
let str = substitute(str, '¥', '\¥', 'g')
|
||||
let str = substitute(str, '&#\(\d\+\);', '\=s:nr2enc_char(submatch(1))', 'g')
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
let str = substitute(str, '»', '>', 'g')
|
||||
let str = substitute(str, '«', '<', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! webapi#html#encodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
let str = substitute(str, '>', '\>', 'g')
|
||||
let str = substitute(str, '<', '\<', 'g')
|
||||
let str = substitute(str, "\n", '\
', 'g')
|
||||
let str = substitute(str, '"', '\"', 'g')
|
||||
let str = substitute(str, "'", '\'', 'g')
|
||||
let str = substitute(str, ' ', '\ ', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! webapi#html#parse(html)
|
||||
let html = substitute(a:html, '<\(area\|base\|basefont\|br\|nobr\|col\|frame\|hr\|img\|input\|isindex\|link\|meta\|param\|embed\|keygen\|command\)\([^>]*[^/]\|\)>', '<\1\2/>', 'g')
|
||||
return webapi#xml#parse(html)
|
||||
endfunction
|
||||
|
||||
function! webapi#html#parseFile(fname)
|
||||
return webapi#html#parse(join(readfile(a:fname), "\n"))
|
||||
endfunction
|
||||
|
||||
function! webapi#html#parseURL(url)
|
||||
return webapi#html#parse(webapi#http#get(a:url).content)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,251 +0,0 @@
|
|||
" http
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:system = function(get(g:, 'webapi#system_function', 'system'))
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
elseif a:nr < 0x10000
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
elseif a:nr < 0x200000
|
||||
return nr2char(a:nr/262144%16+240).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
elseif a:nr < 0x4000000
|
||||
return nr2char(a:nr/16777216%16+248).nr2char(a:nr/262144%16+128).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/1073741824%16+252).nr2char(a:nr/16777216%16+128).nr2char(a:nr/262144%16+128).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! s:nr2hex(nr)
|
||||
let n = a:nr
|
||||
let r = ""
|
||||
while n
|
||||
let r = '0123456789ABCDEF'[n % 16] . r
|
||||
let n = n / 16
|
||||
endwhile
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:urlencode_char(c)
|
||||
let utf = iconv(a:c, &encoding, "utf-8")
|
||||
if utf == ""
|
||||
let utf = a:c
|
||||
endif
|
||||
let s = ""
|
||||
for i in range(strlen(utf))
|
||||
let s .= printf("%%%02X", char2nr(utf[i]))
|
||||
endfor
|
||||
return s
|
||||
endfunction
|
||||
|
||||
function! webapi#http#decodeURI(str)
|
||||
let ret = a:str
|
||||
let ret = substitute(ret, '+', ' ', 'g')
|
||||
let ret = substitute(ret, '%\(\x\x\)', '\=printf("%c", str2nr(submatch(1), 16))', 'g')
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#http#escape(str)
|
||||
return substitute(a:str, '[^a-zA-Z0-9_.~/-]', '\=s:urlencode_char(submatch(0))', 'g')
|
||||
endfunction
|
||||
|
||||
function! webapi#http#encodeURI(items)
|
||||
let ret = ''
|
||||
if type(a:items) == 4
|
||||
for key in sort(keys(a:items))
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= key . "=" . webapi#http#encodeURI(a:items[key])
|
||||
endfor
|
||||
elseif type(a:items) == 3
|
||||
for item in sort(a:items)
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= item
|
||||
endfor
|
||||
else
|
||||
let ret = substitute(a:items, '[^a-zA-Z0-9_.~-]', '\=s:urlencode_char(submatch(0))', 'g')
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#http#encodeURIComponent(items)
|
||||
let ret = ''
|
||||
if type(a:items) == 4
|
||||
for key in sort(keys(a:items))
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= key . "=" . webapi#http#encodeURIComponent(a:items[key])
|
||||
endfor
|
||||
elseif type(a:items) == 3
|
||||
for item in sort(a:items)
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= item
|
||||
endfor
|
||||
else
|
||||
let items = iconv(a:items, &enc, "utf-8")
|
||||
let len = strlen(items)
|
||||
let i = 0
|
||||
while i < len
|
||||
let ch = items[i]
|
||||
if ch =~# '[0-9A-Za-z-._~!''()*]'
|
||||
let ret .= ch
|
||||
elseif ch == ' '
|
||||
let ret .= '+'
|
||||
else
|
||||
let ret .= '%' . substitute('0' . s:nr2hex(char2nr(ch)), '^.*\(..\)$', '\1', '')
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#http#get(url, ...)
|
||||
let getdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata = a:0 > 1 ? a:000[1] : {}
|
||||
let follow = a:0 > 2 ? a:000[2] : 1
|
||||
let url = a:url
|
||||
let getdatastr = webapi#http#encodeURI(getdata)
|
||||
if strlen(getdatastr)
|
||||
let url .= "?" . getdatastr
|
||||
endif
|
||||
if executable('curl')
|
||||
let command = printf('curl %s -s -k -i', follow ? '-L' : '')
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " -H " . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " -H " . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
let res = s:system(command)
|
||||
elseif executable('wget')
|
||||
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " --header=" . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " --header=" . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
let res = s:system(command)
|
||||
else
|
||||
throw "require `curl` or `wget` command"
|
||||
endif
|
||||
if follow != 0
|
||||
while res =~ '^HTTP/1.\d 3' || res =~ '^HTTP/1\.\d 200 Connection established' || res =~ '^HTTP/1\.\d 100 Continue'
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let res = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let res = strpart(res, pos+2)
|
||||
endif
|
||||
endwhile
|
||||
endif
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let content = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let content = strpart(res, pos+2)
|
||||
endif
|
||||
return {
|
||||
\ "header" : split(res[:pos-1], '\r\?\n'),
|
||||
\ "content" : content
|
||||
\}
|
||||
endfunction
|
||||
|
||||
function! webapi#http#post(url, ...)
|
||||
let postdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata = a:0 > 1 ? a:000[1] : {}
|
||||
let method = a:0 > 2 ? a:000[2] : "POST"
|
||||
let follow = a:0 > 3 ? a:000[3] : 1
|
||||
let url = a:url
|
||||
if type(postdata) == 4
|
||||
let postdatastr = webapi#http#encodeURI(postdata)
|
||||
else
|
||||
let postdatastr = postdata
|
||||
endif
|
||||
let file = tempname()
|
||||
if executable('curl')
|
||||
let command = printf('curl %s -s -k -i -X %s', (follow ? '-L' : ''), len(method) ? method : 'POST')
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " -H " . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " -H " . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
call writefile(split(postdatastr, "\n"), file, "b")
|
||||
let res = s:system(command . " --data-binary @" . quote.file.quote)
|
||||
elseif executable('wget')
|
||||
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
|
||||
let headdata['X-HTTP-Method-Override'] = method
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " --header=" . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " --header=" . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
call writefile(split(postdatastr, "\n"), file, "b")
|
||||
let res = s:system(command . " --post-data @" . quote.file.quote)
|
||||
else
|
||||
throw "require `curl` or `wget` command"
|
||||
endif
|
||||
call delete(file)
|
||||
if follow != 0
|
||||
while res =~ '^HTTP/1.\d 3' || res =~ '^HTTP/1\.\d 200 Connection established' || res =~ '^HTTP/1\.\d 100 Continue'
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let res = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let res = strpart(res, pos+2)
|
||||
endif
|
||||
endwhile
|
||||
endif
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let content = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let content = strpart(res, pos+2)
|
||||
endif
|
||||
return {
|
||||
\ "header" : split(res[:pos-1], '\r\?\n'),
|
||||
\ "content" : content
|
||||
\}
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,135 +0,0 @@
|
|||
" json
|
||||
" Last Change: 2012-03-08
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
"
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#json#null()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! webapi#json#true()
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! webapi#json#false()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! s:fixup(val, tmp)
|
||||
if type(a:val) == 0
|
||||
return a:val
|
||||
elseif type(a:val) == 1
|
||||
if a:val == a:tmp.'null'
|
||||
return function('webapi#json#null')
|
||||
elseif a:val == a:tmp.'true'
|
||||
return function('webapi#json#true')
|
||||
elseif a:val == a:tmp.'false'
|
||||
return function('webapi#json#false')
|
||||
endif
|
||||
return a:val
|
||||
elseif type(a:val) == 2
|
||||
return a:val
|
||||
elseif type(a:val) == 3
|
||||
return map(a:val, 's:fixup(v:val, a:tmp)')
|
||||
elseif type(a:val) == 4
|
||||
return map(a:val, 's:fixup(v:val, a:tmp)')
|
||||
else
|
||||
return string(a:val)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! webapi#json#decode(json)
|
||||
let json = iconv(a:json, "utf-8", &encoding)
|
||||
if get(g:, 'webapi#json#parse_strict', 1) == 1 && substitute(substitute(substitute(
|
||||
\ json,
|
||||
\ '\\\%(["\\/bfnrt]\|u[0-9a-fA-F]\{4}\)', '\@', 'g'),
|
||||
\ '"[^\"\\\n\r]*\"\|true\|false\|null\|-\?\d\+'
|
||||
\ . '\%(\.\d*\)\?\%([eE][+\-]\{-}\d\+\)\?', ']', 'g'),
|
||||
\ '\%(^\|:\|,\)\%(\s*\[\)\+', '', 'g') !~ '^[\],:{} \t\n]*$'
|
||||
throw json
|
||||
endif
|
||||
let json = substitute(json, '\n', '', 'g')
|
||||
let json = substitute(json, '\\u34;', '\\"', 'g')
|
||||
if v:version >= 703 && has('patch780')
|
||||
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=iconv(nr2char(str2nr(submatch(1), 16), 1), "utf-8", &encoding)', 'g')
|
||||
else
|
||||
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=s:nr2enc_char("0x".submatch(1))', 'g')
|
||||
endif
|
||||
if get(g:, 'webapi#json#allow_nil', 0) != 0
|
||||
let tmp = '__WEBAPI_JSON__'
|
||||
while 1
|
||||
if stridx(json, tmp) == -1
|
||||
break
|
||||
endif
|
||||
let tmp .= '_'
|
||||
endwhile
|
||||
let [null,true,false] = [
|
||||
\ tmp.'null',
|
||||
\ tmp.'true',
|
||||
\ tmp.'false']
|
||||
sandbox let ret = eval(json)
|
||||
call s:fixup(ret, tmp)
|
||||
else
|
||||
let [null,true,false] = [0,1,0]
|
||||
sandbox let ret = eval(json)
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#json#encode(val)
|
||||
if type(a:val) == 0
|
||||
return a:val
|
||||
elseif type(a:val) == 1
|
||||
let json = '"' . escape(a:val, '\"') . '"'
|
||||
let json = substitute(json, "\r", '\\r', 'g')
|
||||
let json = substitute(json, "\n", '\\n', 'g')
|
||||
let json = substitute(json, "\t", '\\t', 'g')
|
||||
let json = substitute(json, '\([[:cntrl:]]\)', '\=printf("\x%02d", char2nr(submatch(1)))', 'g')
|
||||
return iconv(json, &encoding, "utf-8")
|
||||
elseif type(a:val) == 2
|
||||
let s = string(a:val)
|
||||
if s == "function('webapi#json#null')"
|
||||
return 'null'
|
||||
elseif s == "function('webapi#json#true')"
|
||||
return 'true'
|
||||
elseif s == "function('webapi#json#false')"
|
||||
return 'false'
|
||||
endif
|
||||
elseif type(a:val) == 3
|
||||
return '[' . join(map(copy(a:val), 'webapi#json#encode(v:val)'), ',') . ']'
|
||||
elseif type(a:val) == 4
|
||||
return '{' . join(map(keys(a:val), 'webapi#json#encode(v:val).":".webapi#json#encode(a:val[v:val])'), ',') . '}'
|
||||
else
|
||||
return string(a:val)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,73 +0,0 @@
|
|||
" jsonrpc
|
||||
" Last Change: 2012-03-08
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc4627.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#jsonrpc#call(uri, func, args)
|
||||
let data = webapi#json#encode({
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'method': a:func,
|
||||
\ 'params': a:args,
|
||||
\})
|
||||
let res = webapi#http#post(a:uri, data, {"Content-Type": "application/json"})
|
||||
let obj = webapi#json#decode(res.content)
|
||||
if has_key(obj, 'error')
|
||||
if type(obj.error) == 0 && obj.error != 0
|
||||
throw obj.error
|
||||
elseif type(obj.error) == 1 && obj.error != ''
|
||||
throw obj.error
|
||||
elseif type(obj.error) == 2 && string(obj.error) != "function('webapi#json#null')"
|
||||
throw obj.error
|
||||
endif
|
||||
endif
|
||||
if has_key(obj, 'result')
|
||||
return obj.result
|
||||
endif
|
||||
throw "Parse Error"
|
||||
endfunction
|
||||
|
||||
function! webapi#jsonrpc#wrap(contexts)
|
||||
let api = {}
|
||||
for context in a:contexts
|
||||
let target = api
|
||||
let namespaces = split(context.name, '\.')[:-2]
|
||||
if len(namespaces) > 0
|
||||
for ns in namespaces
|
||||
if !has_key(target, ns)
|
||||
let target[ns] = {".uri": context.uri}
|
||||
endif
|
||||
let target = target[ns]
|
||||
endfor
|
||||
endif
|
||||
if !has_key(context, 'argnames')
|
||||
let context['argnames'] = ['args']
|
||||
let arglist = 'a:args'
|
||||
else
|
||||
if len(context.argnames) && context.argnames[-1] == '...'
|
||||
let arglist = '[' . join(map(copy(context.argnames[:-2]),'"a:".v:val'),',') . ']+a:000'
|
||||
else
|
||||
let arglist = '[' . join(map(copy(context.argnames),'"a:".v:val'),',') . ']'
|
||||
endif
|
||||
endif
|
||||
if has_key(context, 'alias')
|
||||
exe "function api.".context.alias."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#jsonrpc#call(self['.uri'], '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
else
|
||||
exe "function api.".context.name."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#jsonrpc#call('".context.uri."', '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
endif
|
||||
endfor
|
||||
return api
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,46 +0,0 @@
|
|||
" metaweblog
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc3529.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:template = {"uri" : ""}
|
||||
|
||||
function! s:template.newPost(blogid, username, password, content, publish) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.newPost', [a:blogid, a:username, a:password, a:content, a:publish])
|
||||
endfunction
|
||||
|
||||
function! s:template.editPost(postid, username, password, content, publish) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.editPost', [a:postid, a:username, a:password, a:content, a:publish])
|
||||
endfunction
|
||||
|
||||
function! s:template.getPost(postid, username, password) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.getPost', [a:postid, a:username, a:password])
|
||||
endfunction
|
||||
|
||||
function! s:template.getRecentPosts(blogid, username, password, numberOfPosts) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.getRecentPosts', [a:blogid, a:username, a:password, a:numberOfPosts])
|
||||
endfunction
|
||||
|
||||
function! s:template.deletePost(appkey, postid, username, password, ...) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'blogger.deletePost', [a:apikey, a:postid, a:username, a:password])
|
||||
endfunction
|
||||
|
||||
function! s:template.newMediaObject(blogid, username, password, file) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.newMediaObject', [a:blogid, a:username, a:password, a:file])
|
||||
endfunction
|
||||
|
||||
function! webapi#metaWeblog#proxy(uri)
|
||||
let ctx = deepcopy(s:template)
|
||||
let ctx.uri = a:uri
|
||||
return ctx
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,162 +0,0 @@
|
|||
" oauth
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc5849.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#oauth#request_token(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "POST"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_version"] = "1.0"
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
let query_string = "POST&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&", query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
let res = webapi#http#post(a:url, query, {})
|
||||
let a:ctx.request_token = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token='")[0], '^[^=]*=', '', ''))
|
||||
let a:ctx.request_token_secret = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token_secret='")[0], '^[^=]*=', '', ''))
|
||||
return a:ctx
|
||||
endfunction
|
||||
|
||||
function! webapi#oauth#access_token(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "POST"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_token"] = a:ctx.request_token
|
||||
let query["oauth_token_secret"] = a:ctx.request_token_secret
|
||||
let query["oauth_version"] = "1.0"
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
let query_string = "POST&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&" . webapi#http#encodeURI(a:ctx.request_token_secret), query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
let res = webapi#http#post(a:url, query, {})
|
||||
let a:ctx.access_token = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token='")[0], '^[^=]*=', '', ''))
|
||||
let a:ctx.access_token_secret = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token_secret='")[0], '^[^=]*=', '', ''))
|
||||
return a:ctx
|
||||
endfunction
|
||||
|
||||
function! webapi#oauth#get(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let getdata = a:0 > 1 ? a:000[1] : {}
|
||||
let headdata = a:0 > 2 ? a:000[2] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "GET"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_token"] = a:ctx.access_token
|
||||
let query["oauth_version"] = "1.0"
|
||||
if type(params) == 4
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
endif
|
||||
if type(getdata) == 4
|
||||
for key in keys(getdata)
|
||||
let query[key] = getdata[key]
|
||||
endfor
|
||||
endif
|
||||
let query_string = query["oauth_request_method"] . "&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&" . webapi#http#encodeURI(a:ctx.access_token_secret), query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
if type(getdata) == 4
|
||||
for key in keys(getdata)
|
||||
call remove(query, key)
|
||||
endfor
|
||||
endif
|
||||
let auth = 'OAuth '
|
||||
for key in sort(keys(query))
|
||||
let auth .= key . '="' . webapi#http#encodeURI(query[key]) . '", '
|
||||
endfor
|
||||
let auth = auth[:-3]
|
||||
let headdata["Authorization"] = auth
|
||||
let res = webapi#http#get(a:url, getdata, headdata)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! webapi#oauth#post(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let postdata = a:0 > 1 ? a:000[1] : {}
|
||||
let headdata = a:0 > 2 ? a:000[2] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "POST"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_token"] = a:ctx.access_token
|
||||
let query["oauth_version"] = "1.0"
|
||||
if type(params) == 4
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
endif
|
||||
if type(postdata) == 4
|
||||
for key in keys(postdata)
|
||||
let query[key] = postdata[key]
|
||||
endfor
|
||||
endif
|
||||
let query_string = query["oauth_request_method"] . "&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&" . webapi#http#encodeURI(a:ctx.access_token_secret), query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
if type(postdata) == 4
|
||||
for key in keys(postdata)
|
||||
call remove(query, key)
|
||||
endfor
|
||||
endif
|
||||
let auth = 'OAuth '
|
||||
for key in sort(keys(query))
|
||||
let auth .= webapi#http#escape(key) . '="' . webapi#http#escape(query[key]) . '",'
|
||||
endfor
|
||||
let auth = auth[:-2]
|
||||
let headdata["Authorization"] = auth
|
||||
let res = webapi#http#post(a:url, postdata, headdata)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,746 +0,0 @@
|
|||
" sha1 digest calculator
|
||||
" This is a port of rfc3174 sha1 function.
|
||||
" http://www.ietf.org/rfc/rfc3174.txt
|
||||
" Last Change: 2010-02-13
|
||||
" Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
||||
" Original Copyright:
|
||||
" Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
"
|
||||
" This document and translations of it may be copied and furnished to
|
||||
" others, and derivative works that comment on or otherwise explain it
|
||||
" or assist in its implementation may be prepared, copied, published
|
||||
" and distributed, in whole or in part, without restriction of any
|
||||
" kind, provided that the above copyright notice and this paragraph are
|
||||
" included on all such copies and derivative works. However, this
|
||||
" document itself may not be modified in any way, such as by removing
|
||||
" the copyright notice or references to the Internet Society or other
|
||||
" Internet organizations, except as needed for the purpose of
|
||||
" developing Internet standards in which case the procedures for
|
||||
" copyrights defined in the Internet Standards process must be
|
||||
" followed, or as required to translate it into languages other than
|
||||
" English.
|
||||
"
|
||||
" The limited permissions granted above are perpetual and will not be
|
||||
" revoked by the Internet Society or its successors or assigns.
|
||||
"
|
||||
" This document and the information contained herein is provided on an
|
||||
" "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
||||
" TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
||||
" BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
||||
" HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
||||
" MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#sha1#sha1(str)
|
||||
return s:SHA1Digest(s:str2bytes(a:str))
|
||||
endfunction
|
||||
|
||||
function! webapi#sha1#sha1bin(bin)
|
||||
return s:SHA1Digest(a:bin)
|
||||
endfunction
|
||||
|
||||
function! webapi#sha1#test()
|
||||
call s:main()
|
||||
endfunction
|
||||
|
||||
function! s:SHA1Digest(bytes)
|
||||
let sha = deepcopy(s:SHA1Context, 1)
|
||||
let Message_Digest = repeat([0], 20)
|
||||
|
||||
let err = s:SHA1Reset(sha)
|
||||
if err
|
||||
throw printf("SHA1Reset Error %d", err)
|
||||
endif
|
||||
|
||||
let err = s:SHA1Input(sha, a:bytes)
|
||||
if err
|
||||
throw printf("SHA1Input Error %d", err)
|
||||
endif
|
||||
|
||||
let err = s:SHA1Result(sha, Message_Digest)
|
||||
if err
|
||||
throw printf("SHA1Result Error %d", err)
|
||||
endif
|
||||
|
||||
return join(map(Message_Digest, 'printf("%02x", v:val)'), '')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" sha1.h
|
||||
"
|
||||
" Description:
|
||||
" This is the header file for code which implements the Secure
|
||||
" Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
|
||||
" April 17, 1995.
|
||||
"
|
||||
" Many of the variable names in this code, especially the
|
||||
" single character names, were used because those were the names
|
||||
" used in the publication.
|
||||
"
|
||||
" Please read the file sha1.c for more information.
|
||||
|
||||
"
|
||||
" If you do not have the ISO standard stdint.h header file, then you
|
||||
" must typdef the following:
|
||||
" name meaning
|
||||
" uint32_t unsigned 32 bit integer
|
||||
" uint8_t unsigned 8 bit integer (i.e., unsigned char)
|
||||
" int_least16_t integer of >= 16 bits
|
||||
"
|
||||
"
|
||||
|
||||
" enum
|
||||
let s:shaSuccess = 0
|
||||
let s:shaNull = 1 " Null pointer parameter
|
||||
let s:shaInputTooLong = 2 " input data too long
|
||||
let s:shaStateError = 3 " called Input after Result
|
||||
|
||||
" define
|
||||
let s:SHA1HashSize = 20
|
||||
|
||||
"
|
||||
" This structure will hold context information for the SHA-1
|
||||
" hashing operation
|
||||
"
|
||||
" struct
|
||||
let s:SHA1Context = {}
|
||||
" uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
|
||||
let s:SHA1Context.Intermediate_Hash = repeat([0], s:SHA1HashSize / 4)
|
||||
" uint32_t Length_Low; /* Message length in bits */
|
||||
let s:SHA1Context.Length_Low = 0
|
||||
" uint32_t Length_High; /* Message length in bits */
|
||||
let s:SHA1Context.Length_High = 0
|
||||
" /* Index into message block array */
|
||||
" int_least16_t Message_Block_Index;
|
||||
let s:SHA1Context.Message_Block_Index = 0
|
||||
" uint8_t Message_Block[64]; /* 512-bit message blocks */
|
||||
let s:SHA1Context.Message_Block = repeat([0], 64)
|
||||
" int Computed; /* Is the digest computed? */
|
||||
let s:SHA1Context.Computed = 0
|
||||
" int Corrupted; /* Is the message digest corrupted? */
|
||||
let s:SHA1Context.Corrupted = 0
|
||||
|
||||
"
|
||||
" sha1.c
|
||||
"
|
||||
" Description:
|
||||
" This file implements the Secure Hashing Algorithm 1 as
|
||||
" defined in FIPS PUB 180-1 published April 17, 1995.
|
||||
"
|
||||
" The SHA-1, produces a 160-bit message digest for a given
|
||||
" data stream. It should take about 2**n steps to find a
|
||||
" message with the same digest as a given message and
|
||||
" 2**(n/2) to find any two messages with the same digest,
|
||||
" when n is the digest size in bits. Therefore, this
|
||||
" algorithm can serve as a means of providing a
|
||||
" "fingerprint" for a message.
|
||||
"
|
||||
" Portability Issues:
|
||||
" SHA-1 is defined in terms of 32-bit "words". This code
|
||||
" uses <stdint.h> (included via "sha1.h" to define 32 and 8
|
||||
" bit unsigned integer types. If your C compiler does not
|
||||
" support 32 bit unsigned integers, this code is not
|
||||
" appropriate.
|
||||
"
|
||||
" Caveats:
|
||||
" SHA-1 is designed to work with messages less than 2^64 bits
|
||||
" long. Although SHA-1 allows a message digest to be generated
|
||||
" for messages of any number of bits less than 2^64, this
|
||||
" implementation only works with messages with a length that is
|
||||
" a multiple of the size of an 8-bit character.
|
||||
"
|
||||
"
|
||||
|
||||
"
|
||||
" Define the SHA1 circular left shift macro
|
||||
"
|
||||
"#define SHA1CircularShift(bits,word) \
|
||||
" (((word) << (bits)) | ((word) >> (32-(bits))))
|
||||
function s:SHA1CircularShift(bits, word)
|
||||
return s:bitwise_or(s:bitwise_lshift(a:word, a:bits), s:bitwise_rshift(a:word, 32 - a:bits))
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1Reset
|
||||
"
|
||||
" Description:
|
||||
" This function will initialize the SHA1Context in preparation
|
||||
" for computing a new SHA1 message digest.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The context to reset.
|
||||
"
|
||||
" Returns:
|
||||
" sha Error Code.
|
||||
"
|
||||
"
|
||||
" int SHA1Reset(SHA1Context *context)
|
||||
function s:SHA1Reset(context)
|
||||
if empty(a:context)
|
||||
return s:shaNull
|
||||
endif
|
||||
|
||||
let a:context.Length_Low = 0
|
||||
let a:context.Length_High = 0
|
||||
let a:context.Message_Block_Index = 0
|
||||
|
||||
let a:context.Intermediate_Hash[0] = 0x67452301
|
||||
let a:context.Intermediate_Hash[1] = 0xEFCDAB89
|
||||
let a:context.Intermediate_Hash[2] = 0x98BADCFE
|
||||
let a:context.Intermediate_Hash[3] = 0x10325476
|
||||
let a:context.Intermediate_Hash[4] = 0xC3D2E1F0
|
||||
|
||||
let a:context.Computed = 0
|
||||
let a:context.Corrupted = 0
|
||||
|
||||
return s:shaSuccess
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1Result
|
||||
"
|
||||
" Description:
|
||||
" This function will return the 160-bit message digest into the
|
||||
" Message_Digest array provided by the caller.
|
||||
" NOTE: The first octet of hash is stored in the 0th element,
|
||||
" the last octet of hash in the 19th element.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The context to use to calculate the SHA-1 hash.
|
||||
" Message_Digest: [out]
|
||||
" Where the digest is returned.
|
||||
"
|
||||
" Returns:
|
||||
" sha Error Code.
|
||||
"
|
||||
"
|
||||
"int SHA1Result( SHA1Context *context,
|
||||
" uint8_t Message_Digest[SHA1HashSize])
|
||||
function s:SHA1Result(context, Message_Digest)
|
||||
if empty(a:context) || empty(a:Message_Digest)
|
||||
return s:shaNull
|
||||
endif
|
||||
|
||||
if a:context.Corrupted
|
||||
return a:context.Corrupted
|
||||
endif
|
||||
|
||||
if !a:context.Computed
|
||||
call s:SHA1PadMessage(a:context)
|
||||
for i in range(64)
|
||||
" message may be sensitive, clear it out
|
||||
let a:context.Message_Block[i] = 0
|
||||
endfor
|
||||
let a:context.Length_Low = 0 " and clear length
|
||||
let a:context.Length_High = 0
|
||||
let a:context.Computed = 1
|
||||
endif
|
||||
|
||||
for i in range(s:SHA1HashSize)
|
||||
let a:Message_Digest[i] = s:uint8(
|
||||
\ s:bitwise_rshift(
|
||||
\ a:context.Intermediate_Hash[s:bitwise_rshift(i, 2)],
|
||||
\ 8 * (3 - s:bitwise_and(i, 0x03))
|
||||
\ )
|
||||
\ )
|
||||
endfor
|
||||
|
||||
return s:shaSuccess
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1Input
|
||||
"
|
||||
" Description:
|
||||
" This function accepts an array of octets as the next portion
|
||||
" of the message.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The SHA context to update
|
||||
" message_array: [in]
|
||||
" An array of characters representing the next portion of
|
||||
" the message.
|
||||
" length: [in]
|
||||
" The length of the message in message_array
|
||||
"
|
||||
" Returns:
|
||||
" sha Error Code.
|
||||
"
|
||||
"
|
||||
"int SHA1Input( SHA1Context *context,
|
||||
" const uint8_t *message_array,
|
||||
" unsigned length)
|
||||
function s:SHA1Input(context, message_array)
|
||||
if !len(a:message_array)
|
||||
return s:shaSuccess
|
||||
endif
|
||||
|
||||
if empty(a:context) || empty(a:message_array)
|
||||
return s:shaNull
|
||||
endif
|
||||
|
||||
if a:context.Computed
|
||||
let a:context.Corrupted = s:shaStateError
|
||||
return s:shaStateError
|
||||
endif
|
||||
|
||||
if a:context.Corrupted
|
||||
return a:context.Corrupted
|
||||
endif
|
||||
|
||||
for x in a:message_array
|
||||
if a:context.Corrupted
|
||||
break
|
||||
endif
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = s:bitwise_and(x, 0xFF)
|
||||
let a:context.Message_Block_Index += 1
|
||||
|
||||
let a:context.Length_Low += 8
|
||||
if a:context.Length_Low == 0
|
||||
let a:context.Length_High += 1
|
||||
if a:context.Length_High == 0
|
||||
" Message is too long
|
||||
let a:context.Corrupted = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
if a:context.Message_Block_Index == 64
|
||||
call s:SHA1ProcessMessageBlock(a:context)
|
||||
endif
|
||||
endfor
|
||||
|
||||
return s:shaSuccess
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1ProcessMessageBlock
|
||||
"
|
||||
" Description:
|
||||
" This function will process the next 512 bits of the message
|
||||
" stored in the Message_Block array.
|
||||
"
|
||||
" Parameters:
|
||||
" None.
|
||||
"
|
||||
" Returns:
|
||||
" Nothing.
|
||||
"
|
||||
" Comments:
|
||||
" Many of the variable names in this code, especially the
|
||||
" single character names, were used because those were the
|
||||
" names used in the publication.
|
||||
"
|
||||
"
|
||||
"
|
||||
" void SHA1ProcessMessageBlock(SHA1Context *context)
|
||||
function s:SHA1ProcessMessageBlock(context)
|
||||
" Constants defined in SHA-1
|
||||
let K = [
|
||||
\ 0x5A827999,
|
||||
\ 0x6ED9EBA1,
|
||||
\ 0x8F1BBCDC,
|
||||
\ 0xCA62C1D6
|
||||
\ ]
|
||||
let t = 0 " Loop counter
|
||||
let temp = 0 " Temporary word value
|
||||
let W = repeat([0], 80) " Word sequence
|
||||
let [A, B, C, D, E] = [0, 0, 0, 0, 0] " Word buffers
|
||||
|
||||
"
|
||||
" Initialize the first 16 words in the array W
|
||||
"
|
||||
for t in range(16)
|
||||
let W[t] = s:bitwise_lshift(a:context.Message_Block[t * 4], 24)
|
||||
let W[t] = s:bitwise_or(W[t], s:bitwise_lshift(a:context.Message_Block[t * 4 + 1], 16))
|
||||
let W[t] = s:bitwise_or(W[t], s:bitwise_lshift(a:context.Message_Block[t * 4 + 2], 8))
|
||||
let W[t] = s:bitwise_or(W[t], a:context.Message_Block[t * 4 + 3])
|
||||
endfor
|
||||
|
||||
for t in range(16, 79)
|
||||
let W[t] = s:SHA1CircularShift(1, s:bitwise_xor(s:bitwise_xor(s:bitwise_xor(W[t-3], W[t-8]), W[t-14]), W[t-16]))
|
||||
endfor
|
||||
|
||||
let A = a:context.Intermediate_Hash[0]
|
||||
let B = a:context.Intermediate_Hash[1]
|
||||
let C = a:context.Intermediate_Hash[2]
|
||||
let D = a:context.Intermediate_Hash[3]
|
||||
let E = a:context.Intermediate_Hash[4]
|
||||
|
||||
for t in range(20)
|
||||
let temp = s:SHA1CircularShift(5,A) +
|
||||
\ s:bitwise_or(s:bitwise_and(B, C), s:bitwise_and(s:bitwise_not(B), D)) +
|
||||
\ E + W[t] + K[0]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
for t in range(20, 39)
|
||||
let temp = s:SHA1CircularShift(5,A) + s:bitwise_xor(s:bitwise_xor(B, C), D) + E + W[t] + K[1]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
for t in range(40, 59)
|
||||
let temp = s:SHA1CircularShift(5,A) +
|
||||
\ s:bitwise_or(s:bitwise_or(s:bitwise_and(B, C), s:bitwise_and(B, D)), s:bitwise_and(C, D)) +
|
||||
\ E + W[t] + K[2]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
for t in range(60, 79)
|
||||
let temp = s:SHA1CircularShift(5,A) +
|
||||
\ s:bitwise_xor(s:bitwise_xor(B, C), D) + E + W[t] + K[3]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
let a:context.Intermediate_Hash[0] += A
|
||||
let a:context.Intermediate_Hash[1] += B
|
||||
let a:context.Intermediate_Hash[2] += C
|
||||
let a:context.Intermediate_Hash[3] += D
|
||||
let a:context.Intermediate_Hash[4] += E
|
||||
|
||||
let a:context.Message_Block_Index = 0
|
||||
endfunction
|
||||
|
||||
|
||||
"
|
||||
" SHA1PadMessage
|
||||
"
|
||||
" Description:
|
||||
" According to the standard, the message must be padded to an even
|
||||
" 512 bits. The first padding bit must be a '1'. The last 64
|
||||
" bits represent the length of the original message. All bits in
|
||||
" between should be 0. This function will pad the message
|
||||
" according to those rules by filling the Message_Block array
|
||||
" accordingly. It will also call the ProcessMessageBlock function
|
||||
" provided appropriately. When it returns, it can be assumed that
|
||||
" the message digest has been computed.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The context to pad
|
||||
" ProcessMessageBlock: [in]
|
||||
" The appropriate SHA*ProcessMessageBlock function
|
||||
" Returns:
|
||||
" Nothing.
|
||||
"
|
||||
"
|
||||
" void SHA1PadMessage(SHA1Context *context)
|
||||
function s:SHA1PadMessage(context)
|
||||
"
|
||||
" Check to see if the current message block is too small to hold
|
||||
" the initial padding bits and length. If so, we will pad the
|
||||
" block, process it, and then continue padding into a second
|
||||
" block.
|
||||
"
|
||||
if a:context.Message_Block_Index > 55
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0x80
|
||||
let a:context.Message_Block_Index += 1
|
||||
while a:context.Message_Block_Index < 64
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||||
let a:context.Message_Block_Index += 1
|
||||
endwhile
|
||||
|
||||
call s:SHA1ProcessMessageBlock(a:context)
|
||||
|
||||
while a:context.Message_Block_Index < 56
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||||
let a:context.Message_Block_Index += 1
|
||||
endwhile
|
||||
else
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0x80
|
||||
let a:context.Message_Block_Index += 1
|
||||
while a:context.Message_Block_Index < 56
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||||
let a:context.Message_Block_Index += 1
|
||||
endwhile
|
||||
endif
|
||||
|
||||
"
|
||||
" Store the message length as the last 8 octets
|
||||
"
|
||||
let a:context.Message_Block[56] = s:uint8(s:bitwise_rshift(a:context.Length_High, 24))
|
||||
let a:context.Message_Block[57] = s:uint8(s:bitwise_rshift(a:context.Length_High, 16))
|
||||
let a:context.Message_Block[58] = s:uint8(s:bitwise_rshift(a:context.Length_High, 8))
|
||||
let a:context.Message_Block[59] = s:uint8(a:context.Length_High)
|
||||
let a:context.Message_Block[60] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 24))
|
||||
let a:context.Message_Block[61] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 16))
|
||||
let a:context.Message_Block[62] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 8))
|
||||
let a:context.Message_Block[63] = s:uint8(a:context.Length_Low)
|
||||
|
||||
call s:SHA1ProcessMessageBlock(a:context)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" sha1test.c
|
||||
"
|
||||
" Description:
|
||||
" This file will exercise the SHA-1 code performing the three
|
||||
" tests documented in FIPS PUB 180-1 plus one which calls
|
||||
" SHA1Input with an exact multiple of 512 bits, plus a few
|
||||
" error test checks.
|
||||
"
|
||||
" Portability Issues:
|
||||
" None.
|
||||
"
|
||||
"
|
||||
|
||||
"
|
||||
" Define patterns for testing
|
||||
"
|
||||
let s:TEST1 = "abc"
|
||||
let s:TEST2a = "abcdbcdecdefdefgefghfghighijhi"
|
||||
let s:TEST2b = "jkijkljklmklmnlmnomnopnopq"
|
||||
let s:TEST2 = s:TEST2a . s:TEST2b
|
||||
let s:TEST3 = "a"
|
||||
let s:TEST4a = "01234567012345670123456701234567"
|
||||
let s:TEST4b = "01234567012345670123456701234567"
|
||||
" an exact multiple of 512 bits
|
||||
let s:TEST4 = s:TEST4a . s:TEST4b
|
||||
let s:testarray = [
|
||||
\ s:TEST1,
|
||||
\ s:TEST2,
|
||||
\ s:TEST3,
|
||||
\ s:TEST4
|
||||
\ ]
|
||||
let s:repeatcount = [1, 1, 1000000, 10]
|
||||
let s:resultarray = [
|
||||
\ "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
|
||||
\ "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
|
||||
\ "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
|
||||
\ "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
|
||||
\ ]
|
||||
|
||||
function s:main()
|
||||
let sha = deepcopy(s:SHA1Context, 1)
|
||||
let Message_Digest = repeat([0], 20)
|
||||
|
||||
"
|
||||
" Perform SHA-1 tests
|
||||
"
|
||||
for j in range(len(s:testarray))
|
||||
if j == 2
|
||||
echo "Test 3 will take about 1 hour. Press CTRL-C to skip."
|
||||
endif
|
||||
echo ""
|
||||
echo printf("Test %d: %d, '%s'",
|
||||
\ j+1,
|
||||
\ s:repeatcount[j],
|
||||
\ s:testarray[j])
|
||||
|
||||
let err = s:SHA1Reset(sha)
|
||||
if err
|
||||
echo printf("SHA1Reset Error %d.", err )
|
||||
break " out of for j loop
|
||||
endif
|
||||
|
||||
try
|
||||
for i in range(s:repeatcount[j])
|
||||
let err = s:SHA1Input(sha, s:str2bytes(s:testarray[j]))
|
||||
if err
|
||||
echo printf("SHA1Input Error %d.", err )
|
||||
break " out of for i loop */
|
||||
endif
|
||||
endfor
|
||||
catch /^Vim:Interrupt$/
|
||||
echo "Skip ..."
|
||||
while getchar(0) | endwhile
|
||||
continue
|
||||
endtry
|
||||
|
||||
let err = s:SHA1Result(sha, Message_Digest)
|
||||
if err
|
||||
echo printf("SHA1Result Error %d, could not compute message digest.", err)
|
||||
else
|
||||
echo "\t"
|
||||
for i in range(20)
|
||||
echon printf("%02X ", Message_Digest[i])
|
||||
endfor
|
||||
echo ""
|
||||
endif
|
||||
echo "Should match:"
|
||||
echo printf("\t%s", s:resultarray[j])
|
||||
endfor
|
||||
|
||||
" Test some error returns
|
||||
let err = s:SHA1Input(sha, s:str2bytes(s:testarray[1][0:0]))
|
||||
echo printf("\nError %d. Should be %d.", err, s:shaStateError)
|
||||
let err = s:SHA1Reset(0)
|
||||
echo printf("\nError %d. Should be %d.", err, s:shaNull)
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
"---------------------------------------------------------------------
|
||||
" misc
|
||||
function! s:str2bytes(str)
|
||||
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
|
||||
endfunction
|
||||
|
||||
function! s:cmp(a, b)
|
||||
let a = printf("%08x", a:a)
|
||||
let b = printf("%08x", a:b)
|
||||
return a < b ? -1 : a > b ? 1 : 0
|
||||
endfunction
|
||||
|
||||
function! s:uint8(n)
|
||||
return s:bitwise_and(a:n, 0xFF)
|
||||
endfunction
|
||||
|
||||
let s:k = [
|
||||
\ 0x1, 0x2, 0x4, 0x8,
|
||||
\ 0x10, 0x20, 0x40, 0x80,
|
||||
\ 0x100, 0x200, 0x400, 0x800,
|
||||
\ 0x1000, 0x2000, 0x4000, 0x8000,
|
||||
\ 0x10000, 0x20000, 0x40000, 0x80000,
|
||||
\ 0x100000, 0x200000, 0x400000, 0x800000,
|
||||
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
|
||||
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
|
||||
\ ]
|
||||
|
||||
let s:and = [
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3],
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x8, 0x8, 0xA, 0xA, 0x8, 0x8, 0xA, 0xA],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB, 0x8, 0x9, 0xA, 0xB],
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0xC, 0xC, 0xC, 0xC],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x8, 0x9, 0x8, 0x9, 0xC, 0xD, 0xC, 0xD],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x8, 0x8, 0xA, 0xA, 0xC, 0xC, 0xE, 0xE],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF]
|
||||
\ ]
|
||||
|
||||
let s:or = [
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x1, 0x1, 0x3, 0x3, 0x5, 0x5, 0x7, 0x7, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0x2, 0x3, 0x2, 0x3, 0x6, 0x7, 0x6, 0x7, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
|
||||
\ [0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x5, 0x5, 0x7, 0x7, 0x5, 0x5, 0x7, 0x7, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF],
|
||||
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
|
||||
\ [0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF]
|
||||
\ ]
|
||||
|
||||
let s:xor = [
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE],
|
||||
\ [0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD],
|
||||
\ [0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC],
|
||||
\ [0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB],
|
||||
\ [0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA],
|
||||
\ [0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9],
|
||||
\ [0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8],
|
||||
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||||
\ [0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6],
|
||||
\ [0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5],
|
||||
\ [0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4],
|
||||
\ [0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3],
|
||||
\ [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2],
|
||||
\ [0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1],
|
||||
\ [0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0]
|
||||
\ ]
|
||||
|
||||
function! s:bitwise_lshift(a, n)
|
||||
return a:a * s:k[a:n]
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_rshift(a, n)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let a = a / s:k[a:n]
|
||||
if a:a < 0
|
||||
let a += 0x40000000 / s:k[a:n - 1]
|
||||
endif
|
||||
return a
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_not(a)
|
||||
return -a:a - 1
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_and(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a && b
|
||||
let r += s:and[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) && (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_or(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a || b
|
||||
let r += s:or[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) || (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_xor(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a || b
|
||||
let r += s:xor[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) != (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
|
@ -1,118 +0,0 @@
|
|||
" soap
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc4743.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:soap_call(url, func, ...)
|
||||
let envelope = webapi#xml#createElement("soap:Envelope")
|
||||
let envelope.attr["xmlns:soap"] = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
let envelope.attr["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
|
||||
let body = webapi#xml#createElement("soap:Body")
|
||||
call add(envelope.child, body)
|
||||
let func = webapi#xml#createElement(a:func)
|
||||
call add(body.child, func)
|
||||
|
||||
let n = 1
|
||||
for a in a:000
|
||||
let arg = webapi#xml#createElement("param".n)
|
||||
let arg.attr["xsi:type"] = "xsd:string"
|
||||
call arg.value(a)
|
||||
call add(func.child, arg)
|
||||
let n += 1
|
||||
endfor
|
||||
|
||||
let str = '<?xml version="1.0" encoding="UTF-8"?>' . envelope.toString()
|
||||
let res = webapi#http#post(a:url, str)
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
return s:parse_return(dom.find("return"))
|
||||
endfunction
|
||||
|
||||
function! s:parse_return(node)
|
||||
if a:node.attr["xsi:type"] =~ ":Array$"
|
||||
let arr = []
|
||||
for item in a:node.child
|
||||
call add(ret, s:parse_return(item.child)
|
||||
endfor
|
||||
let ret = arr
|
||||
elseif a:node.attr["xsi:type"] =~ ":Map$"
|
||||
let ret = {}
|
||||
for item in a:node.childNodes("item")
|
||||
let val = item.childNode("value")
|
||||
if val.attr["xsi:type"] =~ ":Map$"
|
||||
let ret[item.childNode("key").value()] = s:parse_return(val)
|
||||
else
|
||||
let ret[item.childNode("key").value()] = item.childNode("value").value()
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
if len(a:node.child)
|
||||
let arr = []
|
||||
for item in a:node.child
|
||||
call add(arr, s:parse_return(item)
|
||||
endfor
|
||||
let ret = arr
|
||||
else
|
||||
let ret = s:parse_return(a:node)
|
||||
endif
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:get_convert_code(arg)
|
||||
let code = ''
|
||||
let arg = a:arg
|
||||
if arg.type == "xsd:string"
|
||||
let code .= "let ".arg.name." = a:".arg.name
|
||||
elseif arg.type == "xsd:int"
|
||||
let code .= "let ".arg.name." = 0+a:".arg.name
|
||||
elseif arg.type == "xsd:boolean"
|
||||
let code .= "let ".arg.name." = (0+a:".arg.name.") ? 'true' : 'false'"
|
||||
elseif arg.type == "xsd:float"
|
||||
let code .= "let ".arg.name." = nr2float(0+a:".arg.name.")"
|
||||
elseif arg.type =~ ":Array$"
|
||||
let code .= "let ".arg.name." = a:".arg.name
|
||||
else
|
||||
throw "unknown type:". arg.type
|
||||
endif
|
||||
return code
|
||||
endfunction
|
||||
|
||||
function! webapi#soap#proxy(url)
|
||||
let dom = webapi#xml#parseURL(a:url)
|
||||
let l:api = {}
|
||||
let action = dom.childNode("service").find("soap:address").attr["location"]
|
||||
let operations = dom.childNode("portType").childNodes("operation")
|
||||
for operation in operations
|
||||
let name = operation.attr["name"]
|
||||
let inp = substitute(operation.childNode("input").attr["message"], "^tns:", "", "")
|
||||
let out = substitute(operation.childNode("output").attr["message"], "^tns:", "", "")
|
||||
let message = dom.childNode("message", {"name": inp})
|
||||
let args = []
|
||||
for part in message.childNodes("part")
|
||||
call add(args, {"name": part.attr["name"], "type": part.attr["type"]})
|
||||
endfor
|
||||
let argnames = []
|
||||
let code = ""
|
||||
for arg in args
|
||||
call add(argnames, arg.name)
|
||||
let code .= " ".s:get_convert_code(arg)."\n"
|
||||
endfor
|
||||
let code .= " return s:soap_call(".string(action).", ".string(name).", ".join(argnames, ",").")\n"
|
||||
let source = "function! l:api.".name."(".join(argnames, ",").") dict\n"
|
||||
let source .= code
|
||||
let source .= "endfunction\n"
|
||||
exe source
|
||||
endfor
|
||||
return api
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,56 +0,0 @@
|
|||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:utf8len = [
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
\ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
\ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
\ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0,
|
||||
\]
|
||||
|
||||
function! webapi#ucs#byte2nr(byte)
|
||||
let p = a:byte
|
||||
let n0 = char2nr(p[0])
|
||||
if n0 < 0x80
|
||||
return n0
|
||||
endif
|
||||
let l = s:utf8len[n0]
|
||||
let n1 = char2nr(p[1])
|
||||
if l > 1 && webapi#bit#and(n1, 0xc0) == 0x80
|
||||
if l == 2
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x1f), 6) + webapi#bit#and(n1, 0x3f)
|
||||
endif
|
||||
let n2 = char2nr(p[2])
|
||||
if webapi#bit#and(n2, 0xc0) == 0x80
|
||||
if l == 3
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x0f), 12) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 6) + webapi#bit#and(n2, 0x3f)
|
||||
endif
|
||||
let n3 = char2nr(p[3])
|
||||
if webapi#bit#and(n3, 0xc0) == 0x80
|
||||
if l == 4
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x07), 18) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 12) + webapi#bit#shift(webapi#bit#and(n2, 0x3f), 6) + webapi#bit#and(n3, 0x3f)
|
||||
endif
|
||||
let n4 = char2nr(p[4])
|
||||
if webapi#bit#and(n4, 0xc0) == 0x80
|
||||
if (l == 5)
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x03), 24) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 18) + webapi#bit#shift(webapi#bit#and(n2, 0x3f), 12) + webapi#bit#shift(webapi#bit#and(n3 & 0x3f), 6) + webapi#bit#and(n4, 0x3f)
|
||||
endif
|
||||
let n5 = char2nr(p[5])
|
||||
if webapi#bit#and(n5, 0xc0) == 0x80 && l == 6
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x01), 30) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 24) + webapi#bit#shift(webapi#bit#and(n2, 0x3f), 18) + webapi#bit#shift(webapi#bit#and(n3, 0x3f), 12) + webapi#bit#shift(webapi#bit#and(n4, 0x3f), 6) + webapi#bit#and(n5, 0x3f)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return n0
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,320 +0,0 @@
|
|||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:template = { 'name': '', 'attr': {}, 'child': [] }
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! s:nr2hex(nr)
|
||||
let n = a:nr
|
||||
let r = ""
|
||||
while n
|
||||
let r = '0123456789ABCDEF'[n % 16] . r
|
||||
let n = n / 16
|
||||
endwhile
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:decodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '>', '>', 'g')
|
||||
let str = substitute(str, '<', '<', 'g')
|
||||
"let str = substitute(str, '"', '"', 'g')
|
||||
"let str = substitute(str, ''', "'", 'g')
|
||||
"let str = substitute(str, ' ', ' ', 'g')
|
||||
"let str = substitute(str, '¥', '\¥', 'g')
|
||||
let str = substitute(str, '&#x\([0-9a-fA-F]\+\);', '\=s:nr2enc_char("0x".submatch(1))', 'g')
|
||||
let str = substitute(str, '&#\(\d\+\);', '\=s:nr2enc_char(submatch(1))', 'g')
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! s:encodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
let str = substitute(str, '>', '\>', 'g')
|
||||
let str = substitute(str, '<', '\<', 'g')
|
||||
let str = substitute(str, '"', '\"', 'g')
|
||||
"let str = substitute(str, "\n", '\
', 'g')
|
||||
"let str = substitute(str, '"', '"', 'g')
|
||||
"let str = substitute(str, "'", ''', 'g')
|
||||
"let str = substitute(str, ' ', ' ', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! s:matchNode(node, cond)
|
||||
if type(a:cond) == 1 && a:node.name == a:cond
|
||||
return 1
|
||||
endif
|
||||
if type(a:cond) == 2
|
||||
return a:cond(a:node)
|
||||
endif
|
||||
if type(a:cond) == 3
|
||||
let ret = 1
|
||||
for l:R in a:cond
|
||||
if !s:matchNode(a:node, l:R) | let ret = 0 | endif
|
||||
unlet l:R
|
||||
endfor
|
||||
return ret
|
||||
endif
|
||||
if type(a:cond) == 4
|
||||
for k in keys(a:cond)
|
||||
if has_key(a:node.attr, k) && a:node.attr[k] == a:cond[k] | return 1 | endif
|
||||
endfor
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:template.childNode(...) dict
|
||||
for c in self.child
|
||||
if type(c) == 4 && s:matchNode(c, a:000)
|
||||
return c
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! s:template.childNodes(...) dict
|
||||
let ret = []
|
||||
for c in self.child
|
||||
if type(c) == 4 && s:matchNode(c, a:000)
|
||||
let ret += [c]
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:template.value(...) dict
|
||||
if a:0
|
||||
let self.child = a:000
|
||||
return
|
||||
endif
|
||||
let ret = ''
|
||||
for c in self.child
|
||||
if type(c) <= 1 || type(c) == 5
|
||||
let ret .= c
|
||||
elseif type(c) == 4
|
||||
let ret .= c.value()
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:template.find(...) dict
|
||||
for c in self.child
|
||||
if type(c) == 4
|
||||
if s:matchNode(c, a:000)
|
||||
return c
|
||||
endif
|
||||
unlet! ret
|
||||
let ret = c.find(a:000)
|
||||
if !empty(ret)
|
||||
return ret
|
||||
endif
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! s:template.findAll(...) dict
|
||||
let ret = []
|
||||
for c in self.child
|
||||
if type(c) == 4
|
||||
if s:matchNode(c, a:000)
|
||||
call add(ret, c)
|
||||
endif
|
||||
let ret += c.findAll(a:000)
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:template.toString() dict
|
||||
let xml = '<' . self.name
|
||||
for attr in keys(self.attr)
|
||||
let xml .= ' ' . attr . '="' . s:encodeEntityReference(self.attr[attr]) . '"'
|
||||
endfor
|
||||
if len(self.child)
|
||||
let xml .= '>'
|
||||
for c in self.child
|
||||
if type(c) == 4
|
||||
let xml .= c.toString()
|
||||
elseif type(c) > 1
|
||||
let xml .= s:encodeEntityReference(string(c))
|
||||
else
|
||||
let xml .= s:encodeEntityReference(c)
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
let xml .= '</' . self.name . '>'
|
||||
else
|
||||
let xml .= ' />'
|
||||
endif
|
||||
return xml
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#createElement(name)
|
||||
let node = deepcopy(s:template)
|
||||
let node.name = a:name
|
||||
return node
|
||||
endfunction
|
||||
|
||||
function! s:parse_tree(ctx, top)
|
||||
let node = a:top
|
||||
let stack = [a:top]
|
||||
let pos = 0
|
||||
" content accumulates the text only tags
|
||||
let content = ""
|
||||
let append_content_to_parent = 'if len(stack) && content != "" | call add(stack[-1].child, content) | let content ="" | endif'
|
||||
|
||||
let mx = '^\s*\(<?xml[^>]\+>\)'
|
||||
if a:ctx['xml'] =~ mx
|
||||
let match = matchstr(a:ctx['xml'], mx)
|
||||
let a:ctx['xml'] = a:ctx['xml'][stridx(a:ctx['xml'], match) + len(match):]
|
||||
let mx = 'encoding\s*=\s*["'']\{0,1}\([^"'' \t]\+\|[^"'']\+\)["'']\{0,1}'
|
||||
let matches = matchlist(match, mx)
|
||||
if len(matches)
|
||||
let encoding = matches[1]
|
||||
if len(encoding) && len(a:ctx['encoding']) == 0
|
||||
let a:ctx['encoding'] = encoding
|
||||
let a:ctx['xml'] = iconv(a:ctx['xml'], encoding, &encoding)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
" this regex matches
|
||||
" 1) the remaining until the next tag begins
|
||||
" 2) maybe closing "/" of tag name
|
||||
" 3) tagname
|
||||
" 4) the attributes of the text (optional)
|
||||
" 5) maybe closing "/" (end of tag name)
|
||||
" or
|
||||
" 6) CDATA or ''
|
||||
" 7) text content of CDATA
|
||||
" 8) the remaining text after the tag (rest)
|
||||
" (These numbers correspond to the indexes in matched list m)
|
||||
let tag_mx = '^\(\_.\{-}\)\%(\%(<\(/\?\)\([^!/>[:space:]]\+\)\(\%([[:space:]]*[^/>=[:space:]]\+[[:space:]]*=[[:space:]]*\%([^"'' >\t]\+\|"[^"]*"\|''[^'']*''\)\|[[:space:]]\+[^/>=[:space:]]\+[[:space:]]*\)*\)[[:space:]]*\(/\?\)>\)\|\%(<!\[\(CDATA\)\[\(.\{-}\)\]\]>\)\|\(<!--.\{-}-->\)\)\(.*\)'
|
||||
|
||||
while len(a:ctx['xml']) > 0
|
||||
let m = matchlist(a:ctx.xml, tag_mx)
|
||||
if empty(m) | break | endif
|
||||
let is_end_tag = m[2] == '/' && m[5] == ''
|
||||
let is_start_and_end_tag = m[2] == '' && m[5] == '/'
|
||||
let tag_name = m[3]
|
||||
let attrs = m[4]
|
||||
|
||||
if len(m[1])
|
||||
let content .= s:decodeEntityReference(m[1])
|
||||
endif
|
||||
|
||||
if is_end_tag
|
||||
" closing tag: pop from stack and continue at upper level
|
||||
exec append_content_to_parent
|
||||
|
||||
if len(stack) " TODO: checking whether opened tag is exist.
|
||||
call remove(stack, -1)
|
||||
endif
|
||||
let a:ctx['xml'] = m[9]
|
||||
continue
|
||||
endif
|
||||
|
||||
" comment tag
|
||||
if m[8] != ''
|
||||
let a:ctx.xml = m[9]
|
||||
continue
|
||||
endif
|
||||
|
||||
" if element is a CDATA
|
||||
if m[6] != ''
|
||||
let content .= m[7]
|
||||
let a:ctx.xml = m[9]
|
||||
continue
|
||||
endif
|
||||
|
||||
let node = deepcopy(s:template)
|
||||
let node.name = tag_name
|
||||
let attr_mx = '\([^=[:space:]]\+\)\s*\%(=\s*''\([^'']*\)''\|=\s*"\([^"]*\)"\|=\s*\(\w\+\)\|\)'
|
||||
while len(attrs) > 0
|
||||
let attr_match = matchlist(attrs, attr_mx)
|
||||
if len(attr_match) == 0
|
||||
break
|
||||
endif
|
||||
let name = attr_match[1]
|
||||
let value = len(attr_match[2]) ? attr_match[2] : len(attr_match[3]) ? attr_match[3] : len(attr_match[4]) ? attr_match[4] : ""
|
||||
if value == ""
|
||||
let value = name
|
||||
endif
|
||||
let node.attr[name] = s:decodeEntityReference(value)
|
||||
let attrs = attrs[stridx(attrs, attr_match[0]) + len(attr_match[0]):]
|
||||
endwhile
|
||||
|
||||
exec append_content_to_parent
|
||||
|
||||
if len(stack)
|
||||
call add(stack[-1].child, node)
|
||||
endif
|
||||
if !is_start_and_end_tag
|
||||
" opening tag, continue parsing its contents
|
||||
call add(stack, node)
|
||||
endif
|
||||
let a:ctx['xml'] = m[9]
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#parse(xml)
|
||||
let top = deepcopy(s:template)
|
||||
let oldmaxmempattern=&maxmempattern
|
||||
let oldmaxfuncdepth=&maxfuncdepth
|
||||
let &maxmempattern=2000000
|
||||
let &maxfuncdepth=2000
|
||||
"try
|
||||
call s:parse_tree({'xml': a:xml, 'encoding': ''}, top)
|
||||
for node in top.child
|
||||
if type(node) == 4
|
||||
return node
|
||||
endif
|
||||
unlet node
|
||||
endfor
|
||||
"catch /.*/
|
||||
"endtry
|
||||
let &maxmempattern=oldmaxmempattern
|
||||
let &maxfuncdepth=oldmaxfuncdepth
|
||||
throw "Parse Error"
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#parseFile(fname)
|
||||
return webapi#xml#parse(join(readfile(a:fname), "\n"))
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#parseURL(url)
|
||||
return webapi#xml#parse(webapi#http#get(a:url).content)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,259 +0,0 @@
|
|||
" xmlrpc
|
||||
" Last Change: 2010-11-05
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc3529.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:system = function(get(g:, 'webapi#system_function', 'system'))
|
||||
|
||||
function! webapi#xmlrpc#nil()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#true()
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#false()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:get_childNode(node)
|
||||
let child = a:node.childNode('value').childNode()
|
||||
if empty(child)
|
||||
let child = a:node.childNode('value')
|
||||
endif
|
||||
return child
|
||||
endfunction
|
||||
|
||||
function! s:from_value(value)
|
||||
let value = a:value
|
||||
if value.name == 'methodResponse'
|
||||
let param = value.childNode('params').childNodes('param')
|
||||
if len(param) == 1
|
||||
return s:from_value(s:get_childNode(param[0]))
|
||||
else
|
||||
let ret = []
|
||||
for v in param
|
||||
call add(ret, s:from_value(s:get_childNode(v)))
|
||||
endfor
|
||||
return ret
|
||||
endif
|
||||
elseif value.name == 'string'
|
||||
return value.value()
|
||||
elseif value.name == 'base64'
|
||||
return value.value()
|
||||
elseif value.name == 'dateTime.iso8601'
|
||||
return value.value()
|
||||
elseif value.name == 'boolean'
|
||||
return 0+substitute(value.value(), "[ \n\r]", '', 'g')
|
||||
elseif value.name == 'int'
|
||||
return 0+substitute(value.value(), "[ \n\r]", '', 'g')
|
||||
elseif value.name == 'i4'
|
||||
return 0+substitute(value.value(), "[ \n\r]", '', 'g')
|
||||
elseif value.name == 'double'
|
||||
return str2float(substitute(value.value(), "[ \n\r]", '', 'g'))
|
||||
elseif value.name == 'struct'
|
||||
let ret = {}
|
||||
for member in value.childNodes('member')
|
||||
let ret[member.childNode('name').value()] = s:from_value(s:get_childNode(member))
|
||||
endfor
|
||||
return ret
|
||||
elseif value.name == 'array'
|
||||
let ret = []
|
||||
for v in value.childNode('data').childNodes('value')
|
||||
let child = v.childNode()
|
||||
if !empty(child)
|
||||
call add(ret, s:from_value(child))
|
||||
else
|
||||
call add(ret, v.value())
|
||||
endif
|
||||
endfor
|
||||
return ret
|
||||
elseif value.name == 'nil'
|
||||
if get(g:, 'webapi#xmlrpc#allow_nil', 0) != 0
|
||||
return function('webapi#xmlrpc#nil')
|
||||
endif
|
||||
return 0
|
||||
elseif value.name == 'value'
|
||||
return value.value()
|
||||
else
|
||||
throw "unknown type: ".value.name
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:to_value(content)
|
||||
if type(a:content) == 4
|
||||
if has_key(a:content, 'bits')
|
||||
let struct = webapi#xml#createElement("struct")
|
||||
|
||||
let member = webapi#xml#createElement("member")
|
||||
call add(struct.child, member)
|
||||
let name = webapi#xml#createElement("name")
|
||||
call add(member.child, name)
|
||||
call name.value("name")
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(member.child, value)
|
||||
call add(value.child, s:to_value(a:content["name"]))
|
||||
|
||||
let member = webapi#xml#createElement("member")
|
||||
call add(struct.child, member)
|
||||
let name = webapi#xml#createElement("name")
|
||||
call name.value("bits")
|
||||
call add(member.child, name)
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(member.child, value)
|
||||
let base64 = webapi#xml#createElement("base64")
|
||||
call add(value.child, base64)
|
||||
if has_key(a:content, "bits") && len(a:content["bits"])
|
||||
call base64.value(a:content["bits"])
|
||||
elseif has_key(a:content, "path")
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
let bits = substitute(s:system("xxd -ps ".quote.a:content["path"].quote), "[ \n\r]", '', 'g')
|
||||
call base64.value(webapi#base64#b64encodebin(bits))
|
||||
endif
|
||||
return struct
|
||||
else
|
||||
let struct = webapi#xml#createElement("struct")
|
||||
for key in keys(a:content)
|
||||
let member = webapi#xml#createElement("member")
|
||||
let name = webapi#xml#createElement("name")
|
||||
call name.value(key)
|
||||
call add(member.child, name)
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(value.child, s:to_value(a:content[key]))
|
||||
call add(member.child, value)
|
||||
call add(struct.child, member)
|
||||
endfor
|
||||
return struct
|
||||
endif
|
||||
elseif type(a:content) == 3
|
||||
let array = webapi#xml#createElement("array")
|
||||
let data = webapi#xml#createElement("data")
|
||||
for item in a:content
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(value.child, s:to_value(item))
|
||||
call add(data.child, value)
|
||||
endfor
|
||||
call add(array.child, data)
|
||||
return array
|
||||
elseif type(a:content) == 2
|
||||
if a:content == function('webapi#xmlrpc#true')
|
||||
let true = webapi#xml#createElement("boolean")
|
||||
call true.value('true')
|
||||
return true
|
||||
elseif a:content == function('webapi#xmlrpc#false')
|
||||
let false = webapi#xml#createElement("boolean")
|
||||
call false.value('false')
|
||||
return false
|
||||
else
|
||||
return webapi#xml#createElement("nil")
|
||||
endif
|
||||
elseif type(a:content) <= 1 || type(a:content) == 5
|
||||
if type(a:content) == 0
|
||||
let int = webapi#xml#createElement("int")
|
||||
call int.value(a:content)
|
||||
return int
|
||||
elseif type(a:content) == 1
|
||||
let str = webapi#xml#createElement("string")
|
||||
call str.value(a:content)
|
||||
return str
|
||||
elseif type(a:content) == 5
|
||||
let double = webapi#xml#createElement("double")
|
||||
call double.value(a:content)
|
||||
return double
|
||||
endif
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! s:to_fault(dom)
|
||||
let struct = a:dom.find('struct')
|
||||
let faultCode = ""
|
||||
let faultString = ""
|
||||
for member in struct.childNodes('member')
|
||||
if member.childNode('name').value() == "faultCode"
|
||||
let faultCode = member.childNode('value').value()
|
||||
elseif member.childNode('name').value() == "faultString"
|
||||
let faultString = member.childNode('value').value()
|
||||
endif
|
||||
endfor
|
||||
return faultCode.":".faultString
|
||||
endfunction
|
||||
|
||||
"add_node_params
|
||||
"Add list of args on the xml tree.
|
||||
"input: list of args
|
||||
"output: none
|
||||
function! s:add_node_params(args)
|
||||
let params = webapi#xml#createElement("params")
|
||||
for Arg in a:args
|
||||
let param = webapi#xml#createElement("param")
|
||||
let value = webapi#xml#createElement("value")
|
||||
call value.value(s:to_value(Arg))
|
||||
call add(param.child, value)
|
||||
call add(params.child, param)
|
||||
unlet Arg
|
||||
endfor
|
||||
return params
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#call(uri, func, args)
|
||||
let methodCall = webapi#xml#createElement("methodCall")
|
||||
let methodName = webapi#xml#createElement("methodName")
|
||||
call methodName.value(a:func)
|
||||
call add(methodCall.child, methodName)
|
||||
if !empty(a:args)
|
||||
call add(methodCall.child, s:add_node_params(a:args))
|
||||
endif
|
||||
let xml = '<?xml version="1.0" encoding="utf-8"?>'
|
||||
let xml .= iconv(methodCall.toString(), &encoding, "utf-8")
|
||||
let res = webapi#http#post(a:uri, xml, {"Content-Type": "text/xml"})
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
if len(dom.find('fault'))
|
||||
throw s:to_fault(dom)
|
||||
else
|
||||
return s:from_value(dom)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#wrap(contexts)
|
||||
let api = {}
|
||||
for context in a:contexts
|
||||
let target = api
|
||||
let namespaces = split(context.name, '\.')[:-2]
|
||||
if len(namespaces) > 0
|
||||
for ns in namespaces
|
||||
if !has_key(target, ns)
|
||||
let target[ns] = {".uri": context.uri}
|
||||
endif
|
||||
let target = target[ns]
|
||||
let api['.uri'] = target['.uri']
|
||||
endfor
|
||||
endif
|
||||
if len(context.argnames) && context.argnames[-1] == '...'
|
||||
let arglist = '[' . join(map(copy(context.argnames[:-2]),'"a:".v:val'),',') . ']+a:000'
|
||||
else
|
||||
let arglist = '[' . join(map(copy(context.argnames),'"a:".v:val'),',') . ']'
|
||||
endif
|
||||
if has_key(context, 'alias')
|
||||
exe "function api.".context.alias."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#xmlrpc#call(self['.uri'], '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
else
|
||||
exe "function api.".context.name."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#xmlrpc#call('".context.uri."', '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
endif
|
||||
endfor
|
||||
return api
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
|
@ -1,47 +0,0 @@
|
|||
*webapi-html.txt* HTML parser written in pure vimscript.
|
||||
|
||||
Maintainer: mattn <mattn.jp@gmail.com>
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *webapi-html-contents*
|
||||
|
||||
INTRODUCTION |webapi-html-introduction|
|
||||
INTERFACE |webapi-html-interface|
|
||||
Functions |webapi-html-functions|
|
||||
Structures |webapi-html-structures|
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *webapi-html-introduction*
|
||||
|
||||
*webapi-html* is HTML parser Library.
|
||||
|
||||
==============================================================================
|
||||
INTERFACE *webapi-html-interface*
|
||||
------------------------------------------------------------------------------
|
||||
FUNCTIONS *webapi-html-functions*
|
||||
|
||||
parse(content) *webapi-html.parse()*
|
||||
Parse content into DOM object.
|
||||
|
||||
parseFile(file) *webapi-html.parseFile()*
|
||||
Parse html file into DOM object.
|
||||
|
||||
parseURI(url) *webapi-html.parseURI()*
|
||||
Get and parse html into DOM object.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
STRUCTURES *webapi-html-structures*
|
||||
|
||||
DOM object is structured as |Directory| like following.
|
||||
>
|
||||
{
|
||||
"name": "a",
|
||||
"attr": {
|
||||
"href": "http://example.com",
|
||||
"title": "example",
|
||||
},
|
||||
"child": [...]
|
||||
}
|
||||
<
|
||||
==============================================================================
|
||||
vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl
|
|
@ -1,53 +0,0 @@
|
|||
*webapi-http.txt* simple HTTP client library.
|
||||
|
||||
Maintainer: mattn <mattn.jp@gmail.com>
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *webapi-http-contents*
|
||||
|
||||
INTRODUCTION |webapi-http-introduction|
|
||||
INTERFACE |webapi-http-interface|
|
||||
Functions |webapi-http-functions|
|
||||
Response |webapi-http-response|
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *webapi-http-introduction*
|
||||
|
||||
*webapi-http* is HTTP Utilities Library. It provides simple HTTP client.
|
||||
|
||||
==============================================================================
|
||||
INTERFACE *webapi-http-interface*
|
||||
------------------------------------------------------------------------------
|
||||
FUNCTIONS *webapi-http-functions*
|
||||
|
||||
get(url, param, header) *webapi-http.get()*
|
||||
Send GET request to url.
|
||||
|
||||
post(url, param, header) *webapi-http.post()*
|
||||
Send POST request to url.
|
||||
|
||||
encodeURI(param) *webapi-http.encodeURI()*
|
||||
Encode params as URI query.
|
||||
|
||||
decodeURI(str) *webapi-http.decodeURI()*
|
||||
Decode string as URI params.
|
||||
|
||||
encodeURIComponent(str) *webapi-http.encodeURIComponent()*
|
||||
Encode param as URI components.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
RESPONSE *webapi-http-response*
|
||||
|
||||
|webapi-http.get| and |webapi-http.post| return data structure as
|
||||
|Directory| like following.
|
||||
>
|
||||
{
|
||||
"header": [
|
||||
"Content-Type: text/html",
|
||||
"Content-Length: 310"
|
||||
],
|
||||
"content": "<html> ....."
|
||||
}
|
||||
<
|
||||
==============================================================================
|
||||
vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl
|
|
@ -1,29 +0,0 @@
|
|||
*webapi-json.txt* JSON parser written in pure vimscript.
|
||||
|
||||
Maintainer: mattn <mattn.jp@gmail.com>
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *webapi-json-contents*
|
||||
|
||||
INTRODUCTION |webapi-json-introduction|
|
||||
INTERFACE |webapi-json-interface|
|
||||
Functions |webapi-json-functions|
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *webapi-json-introduction*
|
||||
|
||||
*webapi-json* is JSON parser Library.
|
||||
|
||||
==============================================================================
|
||||
INTERFACE *webapi-json-interface*
|
||||
------------------------------------------------------------------------------
|
||||
FUNCTIONS *webapi-json-functions*
|
||||
|
||||
encode(object) *webapi-json.encode()*
|
||||
Encode object into JSON string.
|
||||
|
||||
decode(json) *webapi-json.decode()*
|
||||
Decode JSON string into variable that vim can treat.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl
|
|
@ -1,47 +0,0 @@
|
|||
*webapi-xml.txt* XML parser written in pure vimscript.
|
||||
|
||||
Maintainer: mattn <mattn.jp@gmail.com>
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *webapi-xml-contents*
|
||||
|
||||
INTRODUCTION |webapi-xml-introduction|
|
||||
INTERFACE |webapi-xml-interface|
|
||||
Functions |webapi-xml-functions|
|
||||
Structures |webapi-xml-structures|
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *webapi-xml-introduction*
|
||||
|
||||
*webapi-xml* is XML parser Library.
|
||||
|
||||
==============================================================================
|
||||
INTERFACE *webapi-xml-interface*
|
||||
------------------------------------------------------------------------------
|
||||
FUNCTIONS *webapi-xml-functions*
|
||||
|
||||
parse(content) *webapi-xml.parse()*
|
||||
Parse content into DOM object.
|
||||
|
||||
parseFile(file) *webapi-xml.parseFile()*
|
||||
Parse html file into DOM object.
|
||||
|
||||
parseURI(url) *webapi-xml.parseURI()*
|
||||
Get and parse html into DOM object.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
STRUCTURES *webapi-xml-structures*
|
||||
|
||||
DOM object is structured as |Directory| like following.
|
||||
>
|
||||
{
|
||||
"name": "a",
|
||||
"attr": {
|
||||
"href": "http://example.com",
|
||||
"title": "example",
|
||||
},
|
||||
"child": [...]
|
||||
}
|
||||
<
|
||||
==============================================================================
|
||||
vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl
|
|
@ -1,43 +0,0 @@
|
|||
function! s:dump(node, syntax)
|
||||
let syntax = a:syntax
|
||||
if type(a:node) == 1
|
||||
if len(syntax) | exe "echohl ".syntax | endif
|
||||
echon webapi#html#decodeEntityReference(a:node)
|
||||
echohl None
|
||||
elseif type(a:node) == 3
|
||||
for n in a:node
|
||||
call s:dump(n, syntax)
|
||||
endfor
|
||||
return
|
||||
elseif type(a:node) == 4
|
||||
"echo a:node.name
|
||||
"echo a:node.attr
|
||||
let syndef = {'kt' : 'Type', 'mi' : 'Number', 'nb' : 'Statement', 'kp' : 'Statement', 'nn' : 'Define', 'nc' : 'Constant', 'no' : 'Constant', 'k' : 'Include', 's' : 'String', 's1' : 'String', 'err': 'Error', 'kd' : 'StorageClass', 'c1' : 'Comment', 'ss' : 'Delimiter', 'vi' : 'Identifier'}
|
||||
for a in keys(syndef)
|
||||
if has_key(a:node.attr, 'class') && a:node.attr['class'] == a | let syntax = syndef[a] | endif
|
||||
endfor
|
||||
if has_key(a:node.attr, 'class') && a:node.attr['class'] == 'line' | echon "\n" | endif
|
||||
for c in a:node.child
|
||||
call s:dump(c, syntax)
|
||||
unlet c
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let no = 357275
|
||||
let res = webapi#http#get(printf('http://gist.github.com/%d.json', no))
|
||||
let obj = webapi#json#decode(res.content)
|
||||
let dom = webapi#html#parse(obj.div)
|
||||
echo "-------------------------------------------------"
|
||||
for file in dom.childNodes('div')
|
||||
unlet! meta
|
||||
let meta = file.childNodes('div')
|
||||
if len(meta) > 1
|
||||
echo "URL:".meta[1].find('a').attr['href']
|
||||
endif
|
||||
echo "\n"
|
||||
call s:dump(file.find('pre'), '')
|
||||
echo "-------------------------------------------------"
|
||||
endfor
|
||||
|
||||
" vim: set et:
|
|
@ -1,40 +0,0 @@
|
|||
set rtp+=.
|
||||
|
||||
let ctx = {}
|
||||
let configfile = expand('~/.google-buzz-vim')
|
||||
if filereadable(configfile)
|
||||
let ctx = eval(join(readfile(configfile), ""))
|
||||
else
|
||||
let ctx.consumer_key = input("consumer_key:")
|
||||
let ctx.consumer_secret = input("consumer_secret:")
|
||||
let ctx.domain = input("domain:")
|
||||
let ctx.callback = input("callback:")
|
||||
|
||||
let request_token_url = "https://www.google.com/accounts/OAuthGetRequestToken"
|
||||
let auth_url = "https://www.google.com/accounts/OAuthAuthorizeToken"
|
||||
let access_token_url = "https://www.google.com/accounts/OAuthGetAccessToken"
|
||||
|
||||
let ctx = webapi#oauth#request_token(request_token_url, ctx, {"scope": "https://www.googleapis.com/auth/buzz", "oauth_callback": ctx.callback})
|
||||
if has("win32") || has("win64")
|
||||
exe "!start rundll32 url.dll,FileProtocolHandler ".auth_url."?oauth_token=".ctx.request_token."&domain=".ctx.domain."&scope=https://www.googleapis.com/auth/buzz"
|
||||
else
|
||||
call system("xdg-open '".auth_url."?oauth_token=".ctx.request_token. "&domain=".ctx.domain."&scope=https://www.googleapis.com/auth/buzz'")
|
||||
endif
|
||||
let verifier = input("VERIFIER:")
|
||||
let ctx = webapi#oauth#access_token(access_token_url, ctx, {"oauth_verifier": verifier})
|
||||
call writefile([string(ctx)], configfile)
|
||||
endif
|
||||
|
||||
let post_url = "https://www.googleapis.com/buzz/v1/activities/@me/@self"
|
||||
let data = ''
|
||||
\.'<entry xmlns:activity="http://activitystrea.ms/spec/1.0/"'
|
||||
\.' xmlns:poco="http://portablecontacts.net/ns/1.0"'
|
||||
\.' xmlns:georss="http://www.georss.org/georss"'
|
||||
\.' xmlns:buzz="http://schemas.google.com/buzz/2010">'
|
||||
\.' <activity:object>'
|
||||
\.' <activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>'
|
||||
\.' <content>ばず! ばず!</content>'
|
||||
\.' </activity:object>'
|
||||
\.'</entry>'
|
||||
let ret = webapi#oauth#post(post_url, ctx, {}, data, {"Content-Type": "application/atom+xml", "GData-Version": "2.0"})
|
||||
echo ret
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user