Update 2022-12-04 23:41 OpenBSD/amd64

This commit is contained in:
c0dev0id 2022-12-04 23:41:31 +01:00
parent 83b82ffc4b
commit 2e35939a4a
90 changed files with 22748 additions and 0 deletions

12
.vim/.netrwhist Normal file
View File

@ -0,0 +1,12 @@
let g:netrw_dirhistmax =10
let g:netrw_dirhistcnt =3
let g:netrw_dirhist_3='/home/sdk'
let g:netrw_dirhist_2='/home/sdk/.vim'
let g:netrw_dirhist_1='sftp://sdk@gopher.codevoid.de/../www/htdocs/gopher/'
let g:netrw_dirhist_0='/home/sdk/code/bcbackup'
let g:netrw_dirhist_9='/home/sdk/code'
let g:netrw_dirhist_8='/home/sdk/code/bar'
let g:netrw_dirhist_7='/home/sdk/code/drist'
let g:netrw_dirhist_6='/home/sdk/code'
let g:netrw_dirhist_5='/home/sdk/.FontForge'
let g:netrw_dirhist_4='/home/sdk/.audacity-data'

264
.vim/autoload/pathogen.vim Normal file
View File

@ -0,0 +1,264 @@
" pathogen.vim - path option manipulation
" Maintainer: Tim Pope <http://tpo.pe/>
" Version: 2.4
" Install in ~/.vim/autoload (or ~\vimfiles\autoload).
"
" For management of individually installed plugins in ~/.vim/bundle (or
" ~\vimfiles\bundle), adding `execute pathogen#infect()` to the top of your
" .vimrc is the only other setup necessary.
"
" The API is documented inline below.
if exists("g:loaded_pathogen") || &cp
finish
endif
let g:loaded_pathogen = 1
" Point of entry for basic default usage. Give a relative path to invoke
" pathogen#interpose() or an absolute path to invoke pathogen#surround().
" Curly braces are expanded with pathogen#expand(): "bundle/{}" finds all
" subdirectories inside "bundle" inside all directories in the runtime path.
" If no arguments are given, defaults "bundle/{}", and also "pack/{}/start/{}"
" on versions of Vim without native package support.
function! pathogen#infect(...) abort
if a:0
let paths = filter(reverse(copy(a:000)), 'type(v:val) == type("")')
else
let paths = ['bundle/{}', 'pack/{}/start/{}']
endif
if has('packages')
call filter(paths, 'v:val !~# "^pack/[^/]*/start/[^/]*$"')
endif
let static = '^\%([$~\\/]\|\w:[\\/]\)[^{}*]*$'
for path in filter(copy(paths), 'v:val =~# static')
call pathogen#surround(path)
endfor
for path in filter(copy(paths), 'v:val !~# static')
if path =~# '^\%([$~\\/]\|\w:[\\/]\)'
call pathogen#surround(path)
else
call pathogen#interpose(path)
endif
endfor
call pathogen#cycle_filetype()
if pathogen#is_disabled($MYVIMRC)
return 'finish'
endif
return ''
endfunction
" Split a path into a list.
function! pathogen#split(path) abort
if type(a:path) == type([]) | return a:path | endif
if empty(a:path) | return [] | endif
let split = split(a:path,'\\\@<!\%(\\\\\)*\zs,')
return map(split,'substitute(v:val,''\\\([\\,]\)'',''\1'',"g")')
endfunction
" Convert a list to a path.
function! pathogen#join(...) abort
if type(a:1) == type(1) && a:1
let i = 1
let space = ' '
else
let i = 0
let space = ''
endif
let path = ""
while i < a:0
if type(a:000[i]) == type([])
let list = a:000[i]
let j = 0
while j < len(list)
let escaped = substitute(list[j],'[,'.space.']\|\\[\,'.space.']\@=','\\&','g')
let path .= ',' . escaped
let j += 1
endwhile
else
let path .= "," . a:000[i]
endif
let i += 1
endwhile
return substitute(path,'^,','','')
endfunction
" Convert a list to a path with escaped spaces for 'path', 'tag', etc.
function! pathogen#legacyjoin(...) abort
return call('pathogen#join',[1] + a:000)
endfunction
" Turn filetype detection off and back on again if it was already enabled.
function! pathogen#cycle_filetype() abort
if exists('g:did_load_filetypes')
filetype off
filetype on
endif
endfunction
" Check if a bundle is disabled. A bundle is considered disabled if its
" basename or full name is included in the list g:pathogen_blacklist or the
" comma delimited environment variable $VIMBLACKLIST.
function! pathogen#is_disabled(path) abort
if a:path =~# '\~$'
return 1
endif
let sep = pathogen#slash()
let blacklist = get(g:, 'pathogen_blacklist', get(g:, 'pathogen_disabled', [])) + pathogen#split($VIMBLACKLIST)
if !empty(blacklist)
call map(blacklist, 'substitute(v:val, "[\\/]$", "", "")')
endif
return index(blacklist, fnamemodify(a:path, ':t')) != -1 || index(blacklist, a:path) != -1
endfunction
" Prepend the given directory to the runtime path and append its corresponding
" after directory. Curly braces are expanded with pathogen#expand().
function! pathogen#surround(path) abort
let sep = pathogen#slash()
let rtp = pathogen#split(&rtp)
let path = fnamemodify(a:path, ':s?[\\/]\=$??')
let before = filter(pathogen#expand(path), '!pathogen#is_disabled(v:val)')
let after = filter(reverse(pathogen#expand(path, sep.'after')), '!pathogen#is_disabled(v:val[0:-7])')
call filter(rtp, 'index(before + after, v:val) == -1')
let &rtp = pathogen#join(before, rtp, after)
return &rtp
endfunction
" For each directory in the runtime path, add a second entry with the given
" argument appended. Curly braces are expanded with pathogen#expand().
function! pathogen#interpose(name) abort
let sep = pathogen#slash()
let name = a:name
if has_key(s:done_bundles, name)
return ""
endif
let s:done_bundles[name] = 1
let list = []
for dir in pathogen#split(&rtp)
if dir =~# '\<after$'
let list += reverse(filter(pathogen#expand(dir[0:-6].name, sep.'after'), '!pathogen#is_disabled(v:val[0:-7])')) + [dir]
else
let list += [dir] + filter(pathogen#expand(dir.sep.name), '!pathogen#is_disabled(v:val)')
endif
endfor
let &rtp = pathogen#join(pathogen#uniq(list))
return 1
endfunction
let s:done_bundles = {}
" Invoke :helptags on all non-$VIM doc directories in runtimepath.
function! pathogen#helptags() abort
let sep = pathogen#slash()
for glob in pathogen#split(&rtp)
for dir in map(split(glob(glob), "\n"), 'v:val.sep."/doc/".sep')
if (dir)[0 : strlen($VIMRUNTIME)] !=# $VIMRUNTIME.sep && filewritable(dir) == 2 && !empty(split(glob(dir.'*.txt'))) && (!filereadable(dir.'tags') || filewritable(dir.'tags'))
silent! execute 'helptags' pathogen#fnameescape(dir)
endif
endfor
endfor
endfunction
command! -bar Helptags :call pathogen#helptags()
" Execute the given command. This is basically a backdoor for --remote-expr.
function! pathogen#execute(...) abort
for command in a:000
execute command
endfor
return ''
endfunction
" Section: Unofficial
function! pathogen#is_absolute(path) abort
return a:path =~# (has('win32') ? '^\%([\\/]\|\w:\)[\\/]\|^[~$]' : '^[/~$]')
endfunction
" Given a string, returns all possible permutations of comma delimited braced
" alternatives of that string. pathogen#expand('/{a,b}/{c,d}') yields
" ['/a/c', '/a/d', '/b/c', '/b/d']. Empty braces are treated as a wildcard
" and globbed. Actual globs are preserved.
function! pathogen#expand(pattern, ...) abort
let after = a:0 ? a:1 : ''
let pattern = substitute(a:pattern, '^[~$][^\/]*', '\=expand(submatch(0))', '')
if pattern =~# '{[^{}]\+}'
let [pre, pat, post] = split(substitute(pattern, '\(.\{-\}\){\([^{}]\+\)}\(.*\)', "\\1\001\\2\001\\3", ''), "\001", 1)
let found = map(split(pat, ',', 1), 'pre.v:val.post')
let results = []
for pattern in found
call extend(results, pathogen#expand(pattern))
endfor
elseif pattern =~# '{}'
let pat = matchstr(pattern, '^.*{}[^*]*\%($\|[\\/]\)')
let post = pattern[strlen(pat) : -1]
let results = map(split(glob(substitute(pat, '{}', '*', 'g')), "\n"), 'v:val.post')
else
let results = [pattern]
endif
let vf = pathogen#slash() . 'vimfiles'
call map(results, 'v:val =~# "\\*" ? v:val.after : isdirectory(v:val.vf.after) ? v:val.vf.after : isdirectory(v:val.after) ? v:val.after : ""')
return filter(results, '!empty(v:val)')
endfunction
" \ on Windows unless shellslash is set, / everywhere else.
function! pathogen#slash() abort
return !exists("+shellslash") || &shellslash ? '/' : '\'
endfunction
function! pathogen#separator() abort
return pathogen#slash()
endfunction
" Convenience wrapper around glob() which returns a list.
function! pathogen#glob(pattern) abort
let files = split(glob(a:pattern),"\n")
return map(files,'substitute(v:val,"[".pathogen#slash()."/]$","","")')
endfunction
" Like pathogen#glob(), only limit the results to directories.
function! pathogen#glob_directories(pattern) abort
return filter(pathogen#glob(a:pattern),'isdirectory(v:val)')
endfunction
" Remove duplicates from a list.
function! pathogen#uniq(list) abort
let i = 0
let seen = {}
while i < len(a:list)
if (a:list[i] ==# '' && exists('empty')) || has_key(seen,a:list[i])
call remove(a:list,i)
elseif a:list[i] ==# ''
let i += 1
let empty = 1
else
let seen[a:list[i]] = 1
let i += 1
endif
endwhile
return a:list
endfunction
" Backport of fnameescape().
function! pathogen#fnameescape(string) abort
if exists('*fnameescape')
return fnameescape(a:string)
elseif a:string ==# '-'
return '\-'
else
return substitute(escape(a:string," \t\n*?[{`$\\%#'\"|!<"),'^[+>]','\\&','')
endif
endfunction
" Like findfile(), but hardcoded to use the runtimepath.
function! pathogen#runtime_findfile(file,count) abort
let rtp = pathogen#join(1,pathogen#split(&rtp))
let file = findfile(a:file,rtp,a:count)
if file ==# ''
return ''
else
return fnamemodify(file,':p')
endif
endfunction
" vim:set et sw=2 foldmethod=expr foldexpr=getline(v\:lnum)=~'^\"\ Section\:'?'>1'\:getline(v\:lnum)=~#'^fu'?'a1'\:getline(v\:lnum)=~#'^endf'?'s1'\:'=':

View File

@ -0,0 +1,120 @@
# diffchar.vim
*Highlight the exact differences, based on characters and words*
```
____ _ ____ ____ _____ _ _ _____ ____
| | | || || || || | | || _ || _ |
| _ || || __|| __|| || | | || | | || | ||
| | | || || |__ | |__ | __|| |_| || |_| || |_||_
| |_| || || __|| __|| | | || || __ |
| || || | | | | |__ | _ || _ || | | |
|____| |_||_| |_| |_____||_| |_||_| |_||_| |_|
```
#### Introduction
This plugin has been developed in order to make diff mode more useful. Vim
highlights all the text in between the first and last different characters on
a changed line. But this plugin will find the exact differences between them,
character by character - so called *DiffChar*.
For example, in diff mode:
![example1](example1.png)
This plugin will exactly show the changed and added units:
![example2](example2.png)
This plugin will synchronously show/reset the highlights of the exact
differences as soon as the diff mode begins/ends. And the exact differences
will be kept updated while editing.
This plugin shows the differences based on a `g:DiffUnit`. Its default is
'Word1' and it handles a `\w\+` word and a `\W` character as a difference unit.
There are other types of word provided and you can also set 'Char' to compare
character by character.
In diff mode, the corresponding `hl-DiffChange` lines are compared between two
windows. You can set a number of matching colors to a `g:DiffColors` to make
it easy to find the corresponding units between two windows. As a default, all
the changed units are highlighted with `hl-DiffText`. In addition,
`hl-DiffAdd` is always used for the added units and both the previous and next
character of the deleted units are shown in bold/underline.
While showing the exact differences, when the cursor is moved on a difference
unit, you can see its corresponding unit highlighted with `hl-Cursor`,
`hl-TermCursor`, or similar one in another window, based on a
`g:DiffPairVisible`. If you change its default, the corresponding unit is
echoed in the command line or displayed in a popup/floating window just below
the cursor position or at the mouse position.
You can use `]b` or `]e` to jump cursor to start or end position of the next
difference unit, and `[b` or `[e` to the start or end position of the previous
unit. Those keymaps are configurable in your vimrc and so on.
Like line-based `:diffget`/`:diffput` and `do`/`dp` vim commands, you can use
`<Leader>g` and `<Leader>p` commands in normal mode to get and put each
difference unit, where the cursor is on, between 2 buffers and undo its
difference.
When the diff mode begins, this plugin locally checks the `hl-DiffChange`
lines in the limited range of the current visible and its upper/lower lines of
a window. And each time a cursor is moved on to a different range upon
scrolling or searching, the new `hl-DiffChange` lines will be incrementally
checked in that range. Which means, independently of the file size, the number
of lines to be checked and then the time consumed are always constant.
This plugin works on each tab page individually. You can use a tab page
variable (t:), instead of a global one (g:), to specify different options on
each tab page. Note that this plugin can not handle more than two diff mode
windows in a tab page. If it would happen, to prevent any trouble, all the
highlighted units are to be reset in the tab page.
To find the exact differences, this plugin uses "An O(NP) Sequence Comparison
Algorithm" developed by S.Wu, et al., which always finds an optimum sequence.
But it takes time to check a long and dissimilar line. To improve the
performance, if there are so many diff units included in a line or it has
taken much time in a diff session, this plugin tries to use the external diff
command together if available.
#### Options
* `g:DiffUnit`, `t:DiffUnit`:
A type of difference unit
* 'Char' : any single character
* 'Word1' : `\w\+` word and any `\W` single character (default)
* 'Word2' : non-space and space words
* 'Word3' : `\<` or `\>` character class boundaries
* 'CSV(,)' : separated by characters such as ',', ';', and '\t'
* `g:DiffColors`, `t:DiffColors`:
Matching colors for changed units
* 0 : `hl-DiffText` (default)
* 1 : `hl-DiffText` + up to 3 other highlights
* 2 : `hl-DiffText` + up to 7 other highlights
* 3 : `hl-DiffText` + up to 15 other highlights
* `g:DiffPairVisible`, `t:DiffPairVisible`:
Visibility of corresponding diff units
* 0 : disable
* 1 : highlight with `hl-Cursor` (default)
* 2 : highlight with `hl-Cursor` + echo in the command line
* 3 : highlight with `hl-Cursor` + popup/floating window at cursor position
* 4 : highlight with `hl-Cursor` + popup/floating window at mouse position
#### Keymaps
* `<Plug>JumpDiffCharPrevStart` (default: `[b`)
* Jump cursor to the start position of the previous difference unit
* `<Plug>JumpDiffCharNextStart` (default: `]b`)
* Jump cursor to the start position of the next difference unit
* `<Plug>JumpDiffCharPrevEnd` (default: `[e`)
* Jump cursor to the end position of the previous difference unit
* `<Plug>JumpDiffCharNextEnd` (default: `]e`)
* Jump cursor to the end position of the next difference unit
* `<Plug>GetDiffCharPair` (default: `<Leader>g`)
* Get a corresponding difference unit from another buffer to undo difference
* `<Plug>PutDiffCharPair` (default: `<Leader>p`)
* Put a corresponding difference unit to another buffer to undo difference
#### Demo
![demo](demo.gif)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,216 @@
*diffchar.txt* Highlight the exact differences, based on characters and words
>
____ _ ____ ____ _____ _ _ _____ ____
| | | || || || || | | || _ || _ |
| _ || || __|| __|| || | | || | | || | ||
| | | || || |__ | |__ | __|| |_| || |_| || |_||_
| |_| || || __|| __|| | | || || __ |
| || || | | | | |__ | _ || _ || | | |
|____| |_||_| |_| |_____||_| |_||_| |_||_| |_|
<
Last Change: 2021/12/07
Version: 8.91
Author: Rick Howe (Takumi Ohtani) <rdcxy754@ybb.ne.jp>
Copyright: (c) 2014-2021 by Rick Howe
-----------------------------------------------------------------------------
INTRODUCTION *diffchar*
This plugin has been developed in order to make diff mode more useful. Vim
highlights all the text in between the first and last different characters on
a changed line. But this plugin will find the exact differences between them,
character by character - so called DiffChar.
For example, in diff mode: ([|hl-DiffText|], <|hl-DiffAdd|>)
>
(window A) The [quick brown fox jumps over the lazy] dog.
(window B) The [lazy fox jumps over the quick brown] dog.
<
this plugin will exactly show the changed and added units:
>
(window A) The [quick] <brown >fox jumps over the [lazy] dog.
(window B) The [lazy] fox jumps over the [quick] <brown >dog.
<
This plugin will synchronously show/reset the highlights of the exact
differences as soon as the diff mode begins/ends. And the exact differences
will be kept updated while editing.
This plugin shows the differences based on a |g:DiffUnit|. Its default is
'Word1' and it handles a \w\+ word and a \W character as a difference unit.
There are other types of word provided and you can also set 'Char' to compare
character by character.
In diff mode, the corresponding |hl-DiffChange| lines are compared between two
windows. You can set a number of matching colors to a |g:DiffColors| to make
it easy to find the corresponding units between two windows. As a default, all
the changed units are highlighted with |hl-DiffText|. In addition,
|hl-DiffAdd| is always used for the added units and both the previous and next
character of the deleted units are shown in bold/underline.
While showing the exact differences, when the cursor is moved on a difference
unit, you can see its corresponding unit highlighted with |hl-Cursor|,
|hl-TermCursor|, or similar one in another window, based on a
|g:DiffPairVisible|. If you change its default, the corresponding unit is
echoed in the command line or displayed in a popup/floating window just below
the cursor position or at the mouse position.
You can use `]b` or `]e` to jump cursor to start or end position of the next
difference unit, and `[b` or `[e` to the start or end position of the previous
unit. Those keymaps are configurable in your vimrc and so on.
Like line-based `:diffget`/`:diffput` and `do`/`dp` vim commands, you can use
`<Leader>g` and `<Leader>p` commands in normal mode to get and put each
difference unit, where the cursor is on, between 2 buffers and undo its
difference.
When the diff mode begins, this plugin locally checks the |hl-DiffChange|
lines in the limited range of the current visible and its upper/lower lines of
a window. And each time a cursor is moved on to a different range upon
scrolling or searching, the new |hl-DiffChange| lines will be incrementally
checked in that range. Which means, independently of the file size, the number
of lines to be checked and then the time consumed are always constant.
This plugin works on each tab page individually. You can use a tab page
variable (t:), instead of a global one (g:), to specify different options on
each tab page. Note that this plugin can not handle more than two diff mode
windows in a tab page. If it would happen, to prevent any trouble, all the
highlighted units are to be reset in the tab page.
To find the exact differences, this plugin uses "An O(NP) Sequence Comparison
Algorithm" developed by S.Wu, et al., which always finds an optimum sequence.
But it takes time to check a long and dissimilar line. To improve the
performance, if there are so many diff units included in a line or it has
taken much time in a diff session, this plugin tries to use the external diff
command together if available.
-----------------------------------------------------------------------------
OPTIONS *diffchar-options*
|g:DiffUnit|, |t:DiffUnit|
A type of difference unit
'Char' : any single character
'Word1' : \w\+ word and any \W single character (default)
'Word2' : non-space and space words
'Word3' : \< or \> character class boundaries
'CSV(,)' : separated by characters such as ',', ';', and '\t'
|g:DiffColors|, |t:DiffColors|
Matching colors for changed units
0 : |hl-DiffText| (default)
1 : |hl-DiffText| + up to 3 other highlights
2 : |hl-DiffText| + up to 7 other highlights
3 : |hl-DiffText| + up to 15 other highlights
|g:DiffPairVisible|, |t:DiffPairVisible|
Visibility of corresponding diff units
0 : disable
1 : highlight with |hl-Cursor| (default)
2 : highlight with |hl-Cursor| + echo in the command line
3 : highlight with |hl-Cursor| + popup/floating window at cursor position
4 : highlight with |hl-Cursor| + popup/floating window at mouse position
-----------------------------------------------------------------------------
KEYMAPS *diffchar-keymaps*
<Plug>JumpDiffCharPrevStart (default: `[b`)
Jump cursor to the start position of the previous difference unit
<Plug>JumpDiffCharNextStart (default: `]b`)
Jump cursor to the start position of the next difference unit
<Plug>JumpDiffCharPrevEnd (default: `[e`)
Jump cursor to the end position of the previous difference unit
<Plug>JumpDiffCharNextEnd (default: `]e`)
Jump cursor to the end position of the next difference unit
<Plug>GetDiffCharPair (default: `<Leader>g`)
Get a corresponding difference unit from another buffer to undo difference
<Plug>PutDiffCharPair (default: `<Leader>p`)
Put a corresponding difference unit to another buffer to undo difference
-----------------------------------------------------------------------------
CHANGE HISTORY *diffchar-history*
Update : 8.91
* Updated to check a new WinClosed event (patch-8.2.3591) to appropriately
reset or repair the highlighted DiffChar units when a window is closed.
Update : 8.9
* Fixed not to overrule syntax highlighting.
* Fixed to successfully sync with diff mode even without patch-8.1.414.
* Changed the highlighting groups used in |g:DiffColors| option.
Update : 8.8
* Changed the highlighting groups used in |g:DiffColors| option, to completely
highlight a changed diff unit and to make each unit more visible.
* Changed to use |hl-Cursor|, |hl-TermCursor|, or similar one, as appropriate,
to highlight a corresponding diff unit, for |g:DiffPairVisible| option.
* Fixed to use proper |hl-Diff| highlighting groups even if they are linked.
* Optimized how to draw each unit and then improved performance.
Update : 8.7
* Enhanced |g:DiffPairVisible| option to show a corresponding diff unit as
well in a floating window on nvim, if its value is 3, and show a popup (not
a balloon) window at the mouse position, if its value is 4.
* Improved performance, use the external diff command together if available,
if there are so many diff units included in a line or it has taken much time
in a diff session.
* Removed |g:DiffMaxLines| option, and locally checks the limited number of
the |hl-DiffChange| lines and incrementally checks them upon scrolling or
searching.
* Removed |g:DiffModeSync| option, and always synchronize with the diff mode.
* `:SDChar`, `:RDChar`, `:TDChar`, and `:EDChar` commands are still available
but deprecated.
Update : 8.6
* Enhanced |g:DiffPairVisible| option to show a corresponding diff unit as a
popup-window just below the cursor position (available on patch-8.1.1391).
And changed its default as 1 (diff unit highlighting only).
* Fixed not to stop monitoring the changes of text and 'diffopt' option,
even if there is no |hl-DiffChange| line, when |g:DiffModeSync| option is
enabled.
Update : 8.5
* Enhanced to show a balloon on GUI and display a corresponding diff unit,
where the mouse is pointing, if |g:DiffPairVisible| option is enabled
(patch-8.1.647 is required to correctly display multibyte characters).
* Fixed to correctly handle |hl-DiffChange| lines while editing.
Update : 8.4
* Extended |g:DiffMaxLines| option to allow a negative value as multiples of
the window height and changed its default as -3.
* Fixed to reset all highlighted DiffChar units when more than two windows
become diff mode in a tab page.
* Deleted |g:DiffSplitTime| option.
Update : 8.3
* Fixed not to detect more |hl-DiffChange| lines than |g:DiffMaxLines| option.
Update : 8.2
* Fixed to correctly update the highlighted DiffChar units while editing when
a new internal diff is not specified in 'diffopt' option (patch-8.1.360).
Update : 8.1
* Fixed to properly detect |hl-DiffChange| lines even when all visible lines
of current window are in a closed fold if a |g:DiffMaxLines| option is
enabled.
Update : 8.0
* Introduced a |g:DiffMaxLines| option to dynamically detect a limited number
of |hl-DiffChange| lines, when the diff mode begins and whenever a cursor is
moved onto an undetected line. It enables to always take a minimum constant
time, independently of the file size.
* Enhanced to check a new DiffUpdated event (patch-8.1.397) to follow diff
updates and some changes of 'diffopt' option.
* Enhanced to support new iwhiteall and iwhiteeol of 'diffopt' option
(patch-8.1.360).
* Removed |g:DiffUpdate| option and merged it into |g:DiffModeSync|.
* Removed keymap for <F7> and <F8>, which toggle to show/reset the highlights.
* Changed to work in diff mode, not in non-diff mode.
* Removed a support for vim version 7.x.
* Changed not to set 'diffexpr' option when a new internal diff is specified
in 'diffopt' (patch-8.1.360).
vim:tw=78:ts=8:ft=help:norl:

View File

@ -0,0 +1,5 @@
diffchar diffchar.txt /*diffchar*
diffchar-history diffchar.txt /*diffchar-history*
diffchar-keymaps diffchar.txt /*diffchar-keymaps*
diffchar-options diffchar.txt /*diffchar-options*
diffchar.txt diffchar.txt /*diffchar.txt*

View File

@ -0,0 +1,118 @@
" diffchar.vim: Highlight the exact differences, based on characters and words
"
" ____ _ ____ ____ _____ _ _ _____ ____
" | | | || || || || | | || _ || _ |
" | _ || || __|| __|| || | | || | | || | ||
" | | | || || |__ | |__ | __|| |_| || |_| || |_||_
" | |_| || || __|| __|| | | || || __ |
" | || || | | | | |__ | _ || _ || | | |
" |____| |_||_| |_| |_____||_| |_||_| |_||_| |_|
"
" Last Change: 2021/12/07
" Version: 8.91
" Author: Rick Howe (Takumi Ohtani) <rdcxy754@ybb.ne.jp>
" Copyright: (c) 2014-2021 by Rick Howe
if exists('g:loaded_diffchar') || !has('diff') || v:version < 800
finish
endif
let g:loaded_diffchar = 8.91
let s:save_cpo = &cpoptions
set cpo&vim
" Commands
command! -range -bar SDChar
\ call diffchar#ShowDiffChar(range(<line1>, <line2>))
command! -range -bar RDChar
\ call diffchar#ResetDiffChar(range(<line1>, <line2>))
command! -range -bar TDChar
\ call diffchar#ToggleDiffChar(range(<line1>, <line2>))
command! -range -bang -bar EDChar
\ call diffchar#EchoDiffChar(range(<line1>, <line2>), <bang>1)
" Configurable Keymaps
for [key, plg, cmd] in [
\['[b', '<Plug>JumpDiffCharPrevStart',
\':call diffchar#JumpDiffChar(0, 0)'],
\[']b', '<Plug>JumpDiffCharNextStart',
\':call diffchar#JumpDiffChar(1, 0)'],
\['[e', '<Plug>JumpDiffCharPrevEnd',
\':call diffchar#JumpDiffChar(0, 1)'],
\[']e', '<Plug>JumpDiffCharNextEnd',
\':call diffchar#JumpDiffChar(1, 1)'],
\['<Leader>g', '<Plug>GetDiffCharPair',
\':call diffchar#CopyDiffCharPair(0)'],
\['<Leader>p', '<Plug>PutDiffCharPair',
\':call diffchar#CopyDiffCharPair(1)']]
if !hasmapto(plg, 'n') && empty(maparg(key, 'n'))
if get(g:, 'DiffCharDoMapping', 1)
execute 'nmap <silent> ' . key . ' ' . plg
endif
endif
execute 'nnoremap <silent> ' plg . ' ' . cmd . '<CR>'
endfor
" a type of difference unit
if !exists('g:DiffUnit')
let g:DiffUnit = 'Word1' " \w\+ word and any \W single character
" let g:DiffUnit = 'Word2' " non-space and space words
" let g:DiffUnit = 'Word3' " \< or \> character class boundaries
" let g:DiffUnit = 'Char' " any single character
" let g:DiffUnit = 'CSV(,)' " split characters
endif
" matching colors for changed units
if !exists('g:DiffColors')
let g:DiffColors = 0 " always 1 color
" let g:DiffColors = 1 " up to 4 colors in fixed order
" let g:DiffColors = 2 " up to 8 colors in fixed order
" let g:DiffColors = 3 " up to 16 colors in fixed order
" let g:DiffColors = 4 " all available colors in fixed order
" let g:DiffColors = 100 " all colors in dynamic random order
endif
" a visibility of corresponding diff units
if !exists('g:DiffPairVisible')
let g:DiffPairVisible = 1 " highlight
" let g:DiffPairVisible = 2 " highlight + echo
" let g:DiffPairVisible = 3 " highlight + popup/floating at cursor pos
" let g:DiffPairVisible = 4 " highlight + popup/floating at mouse pos
" let g:DiffPairVisible = 0 " disable
endif
" Set this plugin's DiffCharExpr() to the diffexpr option if empty
" and when internal diff is not used
if !exists('g:DiffExpr')
let g:DiffExpr = 1 " enable
" let g:DiffExpr = 0 " disable
endif
if g:DiffExpr && empty(&diffexpr) && &diffopt !~ 'internal'
let &diffexpr = 'diffchar#DiffCharExpr()'
endif
" an event group of this plugin
if has('patch-8.0.736') " OptionSet triggered with diff option
let g:DiffCharInitEvent = ['augroup diffchar', 'autocmd!',
\'autocmd OptionSet diff call diffchar#ToggleDiffModeSync(0)',
\'augroup END']
call execute(g:DiffCharInitEvent)
if has('patch-8.1.1113') || has('nvim-0.4.0')
call execute('autocmd diffchar VimEnter * ++once
\ if &diff | call diffchar#ToggleDiffModeSync(1) | endif')
else
call execute('autocmd diffchar VimEnter *
\ if &diff | call diffchar#ToggleDiffModeSync(1) | endif |
\ autocmd! diffchar VimEnter')
endif
else
let g:DiffCharInitEvent = ['augroup diffchar', 'autocmd!',
\'autocmd FilterWritePost * call diffchar#SetDiffModeSync()',
\'augroup END']
call execute(g:DiffCharInitEvent)
endif
let &cpoptions = s:save_cpo
unlet s:save_cpo
" vim: ts=4 sw=4

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,891 @@
easy-align.txt easy-align Last change: December 14 2014
EASY-ALIGN - TABLE OF CONTENTS *easyalign* *easy-align* *easy-align-toc*
==============================================================================
vim-easy-align
Demo |easy-align-1|
Features |easy-align-2|
Installation |easy-align-3|
TLDR - One-minute guide |easy-align-4|
Usage |easy-align-5|
Concept of alignment rule |easy-align-5-1|
Execution models |easy-align-5-2|
1. Using <Plug> mappings |easy-align-5-2-1|
2. Using :EasyAlign command |easy-align-5-2-2|
Interactive mode |easy-align-5-3|
Predefined alignment rules |easy-align-5-3-1|
Examples |easy-align-5-3-2|
Using regular expressions |easy-align-5-3-3|
Alignment options in interactive mode |easy-align-5-3-4|
Live interactive mode |easy-align-5-4|
Non-interactive mode |easy-align-5-5|
Partial alignment in blockwise-visual mode |easy-align-5-6|
Alignment options |easy-align-6|
List of options |easy-align-6-1|
Filtering lines |easy-align-6-2|
Examples |easy-align-6-2-1|
Ignoring delimiters in comments or strings |easy-align-6-3|
Ignoring unmatched lines |easy-align-6-4|
Aligning delimiters of different lengths |easy-align-6-5|
Adjusting indentation |easy-align-6-6|
Alignments over multiple occurrences of delimiters |easy-align-6-7|
Extending alignment rules |easy-align-6-8|
Examples |easy-align-6-8-1|
Other options |easy-align-7|
Disabling &foldmethod during alignment |easy-align-7-1|
Left/right/center mode switch in interactive mode |easy-align-7-2|
Advanced examples and use cases |easy-align-8|
Related work |easy-align-9|
Author |easy-align-10|
License |easy-align-11|
VIM-EASY-ALIGN *vim-easy-align*
==============================================================================
A simple, easy-to-use Vim alignment plugin.
*easy-align-1*
DEMO *easy-align-demo*
==============================================================================
Screencast:
https://raw.githubusercontent.com/junegunn/i/master/vim-easy-align.gif
(Too fast? Slower GIF is {here}{1})
{1} https://raw.githubusercontent.com/junegunn/i/master/vim-easy-align-slow.gif
*easy-align-2*
FEATURES *easy-align-features*
==============================================================================
- Easy to use
- Comes with a predefined set of alignment rules
- Provides a fast and intuitive interface
- Extensible
- You can define your own rules
- Supports arbitrary regular expressions
- Optimized for code editing
- Takes advantage of syntax highlighting feature to avoid unwanted
alignments
*easy-align-3*
INSTALLATION *easy-align-installation*
==============================================================================
Use your favorite plugin manager.
Using {vim-plug}{2}:
>
Plug 'junegunn/vim-easy-align'
<
{2} https://github.com/junegunn/vim-plug
*easy-align-4*
TLDR - ONE-MINUTE GUIDE *easy-align-tldr-one-minute-guide*
==============================================================================
Add the following mappings to your .vimrc.
*<Plug>(EasyAlign)*
>
" Start interactive EasyAlign in visual mode (e.g. vip<Enter>)
vmap <Enter> <Plug>(EasyAlign)
" Start interactive EasyAlign for a motion/text object (e.g. gaip)
nmap ga <Plug>(EasyAlign)
<
And with the following lines of text,
>
apple =red
grass+=green
sky-= blue
<
try these commands:
- vip<Enter>=
- `v`isual-select `i`nner `p`aragraph
- Start EasyAlign command (<Enter>)
- Align around `=`
- `gaip=`
- Start EasyAlign command (`ga`) for `i`nner `p`aragraph
- Align around `=`
Notice that the commands are repeatable with `.` key if you have installed
{repeat.vim}{3}. Install {visualrepeat}{4} as well if you want to repeat in
visual mode.
{3} https://github.com/tpope/vim-repeat
{4} https://github.com/vim-scripts/visualrepeat
*easy-align-5*
USAGE *easy-align-usage*
==============================================================================
< Concept of alignment rule >_________________________________________________~
*easy-align-concept-of-alignment-rule*
*easy-align-5-1*
Though easy-align can align lines of text around any delimiter, it provides
shortcuts for the most common use cases with the concept of "alignment rule".
An alignment rule is a predefined set of options for common alignment tasks,
which is identified by a single character, DELIMITER KEY, such as <Space>,
`=`, `:`, `.`, `|`, `&`, `#`, and `,`.
Think of it as a shortcut. Instead of writing regular expression and setting
several options, you can just type in a single character.
< Execution models >__________________________________________________________~
*easy-align-execution-models*
*easy-align-5-2*
There are two ways to use easy-align.
1. Using <Plug> mappings~
*easy-align-1-using-plug-mappings*
*easy-align-5-2-1*
The recommended method is to use <Plug> mappings as described earlier.
*<Plug>(LiveEasyAlign)*
----------------------+--------+-----------------------------------------------------
Mapping | Mode | Description ~
----------------------+--------+-----------------------------------------------------
<Plug>(EasyAlign) | normal | Start interactive mode for a motion/text object
<Plug>(EasyAlign) | visual | Start interactive mode for the selection
<Plug>(LiveEasyAlign) | normal | Start live-interactive mode for a motion/text object
<Plug>(LiveEasyAlign) | visual | Start live-interactive mode for the selection
----------------------+--------+-----------------------------------------------------
2. Using :EasyAlign command~
*easy-align-2-using-easyalign-command*
*easy-align-5-2-2*
*:EasyAlign*
If you prefer command-line or do not want to start interactive mode, you can
use `:EasyAlign` command instead.
*:LiveEasyAlign*
-------------------------------------------+-----------------------------------------------
Mode | Command ~
-------------------------------------------+-----------------------------------------------
Interactive mode | `:EasyAlign[!] [OPTIONS]`
Live interactive mode | `:LiveEasyAlign[!] [...]`
Non-interactive mode (predefined rules) | `:EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS]`
Non-interactive mode (regular expressions) | `:EasyAlign[!] [N-th] /REGEXP/ [OPTIONS]`
-------------------------------------------+-----------------------------------------------
< Interactive mode >__________________________________________________________~
*easy-align-interactive-mode*
*easy-align-5-3*
The following sections will assume that you have <Plug>(EasyAlign) mappings in
your .vimrc as below:
>
" Start interactive EasyAlign in visual mode (e.g. vip<Enter>)
vmap <Enter> <Plug>(EasyAlign)
" Start interactive EasyAlign for a motion/text object (e.g. gaip)
nmap ga <Plug>(EasyAlign)
<
With these mappings, you can align text with only a few keystrokes.
1. <Enter> key in visual mode, or `ga` followed by a motion or a text object to
start interactive mode
2. Optional: Enter keys to select alignment mode (left, right, or center)
3. Optional: N-th delimiter (default: 1)
- `1` Around the 1st occurrences of delimiters
- `2` Around the 2nd occurrences of delimiters
- ...
- `*` Around all occurrences of delimiters
- `**` Left-right alternating alignment around all delimiters
- `-` Around the last occurrences of delimiters (`-1`)
- `-2` Around the second to last occurrences of delimiters
- ...
4. Delimiter key (a single keystroke; <Space>, `=`, `:`, `.`, `|`, `&`, `#`, `,`)
Predefined alignment rules~
*easy-align-predefined-alignment-rules*
*easy-align-5-3-1*
--------------+--------------------------------------------------------------------
Delimiter key | Description/Use cases ~
--------------+--------------------------------------------------------------------
<Space> | General alignment around whitespaces
`=` | Operators containing equals sign ( `=` , `==,` `!=` , `+=` , `&&=` , ...)
`:` | Suitable for formatting JSON or YAML
`.` | Multi-line method chaining
`,` | Multi-line method arguments
`&` | LaTeX tables (matches `&` and `\\` )
`#` | Ruby/Python comments
`"` | Vim comments
<Bar> | Table markdown
--------------+--------------------------------------------------------------------
*g:easy_align_delimiters*
You can override these default rules or define your own rules with
`g:easy_align_delimiters`, which will be described in {the later section}{5}.
{5} https://github.com/junegunn/vim-easy-align#extending-alignment-rules
Examples~
*easy-align-examples*
*easy-align-5-3-2*
------------------+------------------------------------+--------------------
With visual map | Description | Equivalent command ~
------------------+------------------------------------+--------------------
<Enter><Space> | Around 1st whitespaces | :'<,'>EasyAlign\
<Enter>2<Space> | Around 2nd whitespaces | :'<,'>EasyAlign2\
<Enter>-<Space> | Around the last whitespaces | :'<,'>EasyAlign-\
<Enter>-2<Space> | Around the 2nd to last whitespaces | :'<,'>EasyAlign-2\
<Enter>: | Around 1st colon ( `key: value` ) | :'<,'>EasyAlign:
<Enter><Right>: | Around 1st colon ( `key : value` ) | :'<,'>EasyAlign:<l1
<Enter>= | Around 1st operators with = | :'<,'>EasyAlign=
<Enter>3= | Around 3rd operators with = | :'<,'>EasyAlign3=
<Enter>*= | Around all operators with = | :'<,'>EasyAlign*=
<Enter>**= | Left-right alternating around = | :'<,'>EasyAlign**=
<Enter><Enter>= | Right alignment around 1st = | :'<,'>EasyAlign!=
<Enter><Enter>**= | Right-left alternating around = | :'<,'>EasyAlign!**=
------------------+------------------------------------+--------------------
Using regular expressions~
*easy-align-using-regular-expressions*
*easy-align-5-3-3*
Instead of finishing the command with a predefined delimiter key, you can type
in a regular expression after CTRL-/ or CTRL-X key. For example, if you want
to align text around all occurrences of numbers:
- <Enter>
- `*`
- CTRL-X
- `[0-9]\+`
Alignment options in interactive mode~
*easy-align-alignment-options-in-interactive-mode*
*easy-align-5-3-4*
While in interactive mode, you can set alignment options using special
shortcut keys listed below. The meaning of each option will be described in
{the following sections}{6}.
--------+--------------------+---------------------------------------------------
Key | Option | Values ~
--------+--------------------+---------------------------------------------------
CTRL-F | `filter` | Input string ( `[gv]/.*/?` )
CTRL-I | `indentation` | shallow, deep, none, keep
CTRL-L | `left_margin` | Input number or string
CTRL-R | `right_margin` | Input number or string
CTRL-D | `delimiter_align` | left, center, right
CTRL-U | `ignore_unmatched` | 0, 1
CTRL-G | `ignore_groups` | [], ["String'], ["Comment'], ["String', "Comment']
CTRL-A | `align` | Input string ( `/[lrc]+\*{0,2}/` )
<Left> | `stick_to_left` | `{ 'stick_to_left': 1, 'left_margin': 0 }`
<Right> | `stick_to_left` | `{ 'stick_to_left': 0, 'left_margin': 1 }`
<Down> | `*_margin` | `{ 'left_margin': 0, 'right_margin': 0 }`
--------+--------------------+---------------------------------------------------
{6} https://github.com/junegunn/vim-easy-align#alignment-options
< Live interactive mode >_____________________________________________________~
*easy-align-live-interactive-mode*
*easy-align-5-4*
If you're performing a complex alignment where multiple options should be
carefully adjusted, try "live interactive mode" where you can preview the
result of the alignment on-the-fly as you type in.
Live interactive mode can be started with either <Plug>(LiveEasyAlign) map or
`:LiveEasyAlign` command. Or you can switch to live interactive mode while in
ordinary interactive mode by pressing CTRL-P. (P for Preview)
In live interactive mode, you have to type in the same delimiter (or CTRL-X on
regular expression) again to finalize the alignment. This allows you to
preview the result of the alignment and freely change the delimiter using
backspace key without leaving the interactive mode.
< Non-interactive mode >______________________________________________________~
*easy-align-non-interactive-mode*
*easy-align-5-5*
Instead of starting interactive mode, you can use declarative, non-interactive
`:EasyAlign` command.
>
" Using predefined alignment rules
" :EasyAlign[!] [N-th] DELIMITER_KEY [OPTIONS]
:EasyAlign :
:EasyAlign =
:EasyAlign *=
:EasyAlign 3\
" Using arbitrary regular expressions
" :EasyAlign[!] [N-th] /REGEXP/ [OPTIONS]
:EasyAlign /[:;]\+/
:EasyAlign 2/[:;]\+/
:EasyAlign */[:;]\+/
:EasyAlign **/[:;]\+/
<
A command can end with alignment options, {each of which will be discussed in
detail later}{6}, in Vim dictionary format.
- `:EasyAlign * /[:;]\+/ { 'stick_to_left': 1, 'left_margin': 0 }`
`stick_to_left` of 1 means that the matched delimiter should be positioned
right next to the preceding token, and `left_margin` of 0 removes the margin
on the left. So we get:
>
apple;: banana:: cake
data;; exchange:; format
<
Option names are fuzzy-matched, so you can write as follows:
- `:EasyAlign * /[:;]\+/ { 'stl': 1, 'l': 0 }`
You can even omit spaces between the arguments, so concisely (or cryptically):
- `:EasyAlign*/[:;]\+/{'s':1,'l':0}`
Nice. But let's make it even shorter. Option values can be written in
shorthand notation.
- `:EasyAlign*/[:;]\+/<l0`
The following table summarizes the shorthand notation.
-------------------+-----------
Option | Expression~
-------------------+-----------
`filter` | `[gv]/.*/`
`left_margin` | `l[0-9]+`
`right_margin` | `r[0-9]+`
`stick_to_left` | `<` or `>`
`ignore_unmatched` | `iu[01]`
`ignore_groups` | `ig\[.*\]`
`align` | `a[lrc*]*`
`delimiter_align` | `d[lrc]`
`indentation` | `i[ksdn]`
-------------------+-----------
For your information, the same operation can be done in interactive mode as
follows:
- <Enter>
- `*`
- <Left>
- CTRL-X
- `[:;]\+`
{6} https://github.com/junegunn/vim-easy-align#alignment-options
< Partial alignment in blockwise-visual mode >________________________________~
*easy-align-partial-alignment-in-blockwise-visual-mode*
*easy-align-5-6*
In blockwise-visual mode (CTRL-V), EasyAlign command aligns only the selected
text in the block, instead of the whole lines in the range.
Consider the following case where you want to align text around `=>`
operators.
>
my_hash = { :a => 1,
:aa => 2,
:aaa => 3 }
<
In non-blockwise visual mode (`v` / `V`), <Enter>= won't work since the
assignment operator in the first line gets in the way. So we instead enter
blockwise-visual mode (CTRL-V), and select the text around`=>` operators, then
press <Enter>=.
>
my_hash = { :a => 1,
:aa => 2,
:aaa => 3 }
<
However, in this case, we don't really need blockwise visual mode since the
same can be easily done using the negative N-th parameter: <Enter>-=
*easy-align-6*
ALIGNMENT OPTIONS *easy-align-alignment-options*
==============================================================================
< List of options >___________________________________________________________~
*easy-align-list-of-options*
*easy-align-6-1*
-------------------+---------+-----------------------+--------------------------------------------------------
Option | Type | Default | Description ~
-------------------+---------+-----------------------+--------------------------------------------------------
`filter` | string | | Line filtering expression: `g/../` or `v/../`
`left_margin` | number | 1 | Number of spaces to attach before delimiter
`left_margin` | string | `' '` | String to attach before delimiter
`right_margin` | number | 1 | Number of spaces to attach after delimiter
`right_margin` | string | `' '` | String to attach after delimiter
`stick_to_left` | boolean | 0 | Whether to position delimiter on the left-side
`ignore_groups` | list | ["String', "Comment'] | Delimiters in these syntax highlight groups are ignored
`ignore_unmatched` | boolean | 1 | Whether to ignore lines without matching delimiter
`indentation` | string | `k` | Indentation method (keep, deep, shallow, none)
`delimiter_align` | string | `r` | Determines how to align delimiters of different lengths
`align` | string | `l` | Alignment modes for multiple occurrences of delimiters
-------------------+---------+-----------------------+--------------------------------------------------------
There are 4 ways to set alignment options (from lowest precedence to highest):
1. Some option values can be set with corresponding global variables
2. Option values can be specified in the definition of each alignment rule
3. Option values can be given as arguments to `:EasyAlign` command
4. Option values can be set in interactive mode using special shortcut keys
*g:easy_align_ignore_groups* *g:easy_align_ignore_unmatched*
*g:easy_align_indentation* *g:easy_align_delimiter_align*
-------------------+-----------------+-------------+--------------------------------
Option name | Shortcut key | Abbreviated | Global variable ~
-------------------+-----------------+-------------+--------------------------------
`filter` | CTRL-F | `[gv]/.*/` |
`left_margin` | CTRL-L | `l[0-9]+` |
`right_margin` | CTRL-R | `r[0-9]+` |
`stick_to_left` | <Left>, <Right> | `<` or `>` |
`ignore_groups` | CTRL-G | `ig\[.*\]` | `g:easy_align_ignore_groups`
`ignore_unmatched` | CTRL-U | `iu[01]` | `g:easy_align_ignore_unmatched`
`indentation` | CTRL-I | `i[ksdn]` | `g:easy_align_indentation`
`delimiter_align` | CTRL-D | `d[lrc]` | `g:easy_align_delimiter_align`
`align` | CTRL-A | `a[lrc*]*` |
-------------------+-----------------+-------------+--------------------------------
< Filtering lines >___________________________________________________________~
*easy-align-filtering-lines*
*easy-align-6-2*
With `filter` option, you can align lines that only match or do not match a
given pattern. There are several ways to set the pattern.
1. Press CTRL-F in interactive mode and type in `g/pat/` or `v/pat/`
2. In command-line, it can be written in dictionary format: `{'filter':
'g/pat/'}`
3. Or in shorthand notation: `g/pat/` or `v/pat/`
(You don't need to escape "/'s in the regular expression)
Examples~
*easy-align-6-2-1*
>
" Start interactive mode with filter option set to g/hello/
EasyAlign g/hello/
" Start live interactive mode with filter option set to v/goodbye/
LiveEasyAlign v/goodbye/
" Align the lines with 'hi' around the first colons
EasyAlign:g/hi/
<
< Ignoring delimiters in comments or strings >________________________________~
*easy-align-ignoring-delimiters-in-comments-or-strings*
*easy-align-6-3*
EasyAlign can be configured to ignore delimiters in certain syntax highlight
groups, such as code comments or strings. By default, delimiters that are
highlighted as code comments or strings are ignored.
>
" Default:
" If a delimiter is in a highlight group whose name matches
" any of the followings, it will be ignored.
let g:easy_align_ignore_groups = ['Comment', 'String']
<
For example, the following paragraph
>
{
# Quantity of apples: 1
apple: 1,
# Quantity of bananas: 2
bananas: 2,
# Quantity of grape:fruits: 3
'grape:fruits': 3
}
<
becomes as follows on <Enter>: (or `:EasyAlign:`)
>
{
# Quantity of apples: 1
apple: 1,
# Quantity of bananas: 2
bananas: 2,
# Quantity of grape:fruits: 3
'grape:fruits': 3
}
<
Naturally, this feature only works when syntax highlighting is enabled.
You can change the default rule by using one of these 4 methods.
1. Press CTRL-G in interactive mode to switch groups
2. Define global `g:easy_align_ignore_groups` list
3. Define a custom rule in `g:easy_align_delimiters` with `ignore_groups` option
4. Provide `ignore_groups` option to `:EasyAlign` command. e.g. `:EasyAlign:ig[]`
For example if you set `ignore_groups` option to be an empty list, you get
>
{
# Quantity of apples: 1
apple: 1,
# Quantity of bananas: 2
bananas: 2,
# Quantity of grape: fruits: 3
'grape: fruits': 3
}
<
If a pattern in `ignore_groups` is prepended by a `!`, it will have the
opposite meaning. For instance, if `ignore_groups` is given as `['!Comment']`,
delimiters that are not highlighted as Comment will be ignored during the
alignment.
< Ignoring unmatched lines >__________________________________________________~
*easy-align-ignoring-unmatched-lines*
*easy-align-6-4*
`ignore_unmatched` option determines how EasyAlign command processes lines
that do not have N-th delimiter.
1. In left-alignment mode, they are ignored
2. In right or center-alignment mode, they are not ignored, and the last tokens
from those lines are aligned as well as if there is an invisible trailing
delimiter at the end of each line
3. If `ignore_unmatched` is 1, they are ignored regardless of the alignment mode
4. If `ignore_unmatched` is 0, they are not ignored regardless of the mode
Let's take an example. When we align the following code block around the (1st)
colons,
>
{
apple: proc {
this_line_does_not_have_a_colon
},
bananas: 2,
grapefruits: 3
}
<
this is usually what we want.
>
{
apple: proc {
this_line_does_not_have_a_colon
},
bananas: 2,
grapefruits: 3
}
<
However, we can override this default behavior by setting `ignore_unmatched`
option to zero using one of the following methods.
1. Press CTRL-U in interactive mode to toggle `ignore_unmatched` option
2. Set the global `g:easy_align_ignore_unmatched` variable to 0
3. Define a custom alignment rule with `ignore_unmatched` option set to 0
4. Provide `ignore_unmatched` option to `:EasyAlign` command. e.g.
`:EasyAlign:iu0`
Then we get,
>
{
apple: proc {
this_line_does_not_have_a_colon
},
bananas: 2,
grapefruits: 3
}
<
< Aligning delimiters of different lengths >__________________________________~
*easy-align-aligning-delimiters-of-different-lengths*
*easy-align-6-5*
Global `g:easy_align_delimiter_align` option and rule-wise/command-wise
`delimiter_align` option determines how matched delimiters of different
lengths are aligned.
>
apple = 1
banana += apple
cake ||= banana
<
By default, delimiters are right-aligned as follows.
>
apple = 1
banana += apple
cake ||= banana
<
However, with `:EasyAlign=dl`, delimiters are left-aligned.
>
apple = 1
banana += apple
cake ||= banana
<
And on `:EasyAlign=dc`, center-aligned.
>
apple = 1
banana += apple
cake ||= banana
<
In interactive mode, you can change the option value with CTRL-D key.
< Adjusting indentation >_____________________________________________________~
*easy-align-adjusting-indentation*
*easy-align-6-6*
By default :EasyAlign command keeps the original indentation of the lines. But
then again we have `indentation` option. See the following example.
>
# Lines with different indentation
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Default: _k_eep the original indentation
# :EasyAlign=
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Use the _s_hallowest indentation among the lines
# :EasyAlign=is
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Use the _d_eepest indentation among the lines
# :EasyAlign=id
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
# Indentation: _n_one
# :EasyAlign=in
apple = 1
banana = 2
cake = 3
daisy = 4
eggplant = 5
<
In interactive mode, you can change the option value with CTRL-I key.
< Alignments over multiple occurrences of delimiters >________________________~
*easy-align-alignments-over-multiple-occurrences-of-delimiters*
*easy-align-6-7*
As stated above, "N-th" parameter is used to target specific occurrences of
the delimiter when it appears multiple times in each line.
To recap:
>
" Left-alignment around the FIRST occurrences of delimiters
:EasyAlign =
" Left-alignment around the SECOND occurrences of delimiters
:EasyAlign 2=
" Left-alignment around the LAST occurrences of delimiters
:EasyAlign -=
" Left-alignment around ALL occurrences of delimiters
:EasyAlign *=
" Left-right ALTERNATING alignment around all occurrences of delimiters
:EasyAlign **=
" Right-left ALTERNATING alignment around all occurrences of delimiters
:EasyAlign! **=
<
In addition to these, you can fine-tune alignments over multiple occurrences
of the delimiters with "align' option. (The option can also be set in
interactive mode with the special key CTRL-A)
>
" Left alignment over the first two occurrences of delimiters
:EasyAlign = { 'align': 'll' }
" Right, left, center alignment over the 1st to 3rd occurrences of delimiters
:EasyAlign = { 'a': 'rlc' }
" Using shorthand notation
:EasyAlign = arlc
" Right, left, center alignment over the 2nd to 4th occurrences of delimiters
:EasyAlign 2=arlc
" (*) Repeating alignments (default: l, r, or c)
" Right, left, center, center, center, center, ...
:EasyAlign *=arlc
" (**) Alternating alignments (default: lr or rl)
" Right, left, center, right, left, center, ...
:EasyAlign **=arlc
" Right, left, center, center, center, ... repeating alignment
" over the 3rd to the last occurrences of delimiters
:EasyAlign 3=arlc*
" Right, left, center, right, left, center, ... alternating alignment
" over the 3rd to the last occurrences of delimiters
:EasyAlign 3=arlc**
<
< Extending alignment rules >_________________________________________________~
*easy-align-extending-alignment-rules*
*easy-align-6-8*
Although the default rules should cover the most of the use cases, you can
extend the rules by setting a dictionary named `g:easy_align_delimiters`.
You may refer to the definitions of the default alignment rules {here}{7}.
{7} https://github.com/junegunn/vim-easy-align/blob/2.9.6/autoload/easy_align.vim#L32-L46
Examples~
*easy-align-6-8-1*
>
let g:easy_align_delimiters = {
\ '>': { 'pattern': '>>\|=>\|>' },
\ '/': {
\ 'pattern': '//\+\|/\*\|\*/',
\ 'delimiter_align': 'l',
\ 'ignore_groups': ['!Comment'] },
\ ']': {
\ 'pattern': '[[\]]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0
\ },
\ ')': {
\ 'pattern': '[()]',
\ 'left_margin': 0,
\ 'right_margin': 0,
\ 'stick_to_left': 0
\ },
\ 'd': {
\ 'pattern': ' \(\S\+\s*[;=]\)\@=',
\ 'left_margin': 0,
\ 'right_margin': 0
\ }
\ }
<
*easy-align-7*
OTHER OPTIONS *easy-align-other-options*
==============================================================================
< Disabling &foldmethod during alignment >____________________________________~
*easy-align-disabling-foldmethod-during-alignment*
*easy-align-7-1*
*g:easy_align_bypass_fold*
{It is reported}{8} that 'foldmethod' value of `expr` or `syntax` can
significantly slow down the alignment when editing a large, complex file with
many folds. To alleviate this issue, EasyAlign provides an option to
temporarily set 'foldmethod' to `manual` during the alignment task. In order
to enable this feature, set `g:easy_align_bypass_fold` switch to 1.
>
let g:easy_align_bypass_fold = 1
<
{8} https://github.com/junegunn/vim-easy-align/issues/14
< Left/right/center mode switch in interactive mode >_________________________~
*easy-align-left-right-center-mode-switch-in-interactive-mode*
*easy-align-7-2*
In interactive mode, you can choose the alignment mode you want by pressing
enter keys. The non-bang command, `:EasyAlign` starts in left-alignment mode
and changes to right and center mode as you press enter keys, while the bang
version first starts in right-alignment mode.
- `:EasyAlign`
- Left, Right, Center
- `:EasyAlign!`
- Right, Left, Center
If you do not prefer this default mode transition, you can define your own
settings as follows.
*g:easy_align_interactive_modes* *g:easy_align_bang_interactive_modes*
>
let g:easy_align_interactive_modes = ['l', 'r']
let g:easy_align_bang_interactive_modes = ['c', 'r']
<
*easy-align-8*
ADVANCED EXAMPLES AND USE CASES *easy-align-advanced-examples-and-use-cases*
==============================================================================
See {EXAMPLES.md}{9} for more examples.
{9} https://github.com/junegunn/vim-easy-align/blob/master/EXAMPLES.md
*easy-align-9*
RELATED WORK *easy-align-related-work*
==============================================================================
- {DrChip's Alignment Tool for Vim}{10}
- {Tabular}{11}
{10} http://www.drchip.org/astronaut/vim/align.html
{11} https://github.com/godlygeek/tabular
*easy-align-10*
AUTHOR *easy-align-author*
==============================================================================
{Junegunn Choi}{12}
{12} https://github.com/junegunn
*easy-align-11*
LICENSE *easy-align-license*
==============================================================================
MIT
==============================================================================
vim:tw=78:sw=2:ts=2:ft=help:norl:nowrap:

View File

@ -0,0 +1,84 @@
:EasyAlign easy_align.txt /*:EasyAlign*
:LiveEasyAlign easy_align.txt /*:LiveEasyAlign*
<Plug>(EasyAlign) easy_align.txt /*<Plug>(EasyAlign)*
<Plug>(LiveEasyAlign) easy_align.txt /*<Plug>(LiveEasyAlign)*
easy-align easy_align.txt /*easy-align*
easy-align-1 easy_align.txt /*easy-align-1*
easy-align-1-using-plug-mappings easy_align.txt /*easy-align-1-using-plug-mappings*
easy-align-10 easy_align.txt /*easy-align-10*
easy-align-11 easy_align.txt /*easy-align-11*
easy-align-2 easy_align.txt /*easy-align-2*
easy-align-2-using-easyalign-command easy_align.txt /*easy-align-2-using-easyalign-command*
easy-align-3 easy_align.txt /*easy-align-3*
easy-align-4 easy_align.txt /*easy-align-4*
easy-align-5 easy_align.txt /*easy-align-5*
easy-align-5-1 easy_align.txt /*easy-align-5-1*
easy-align-5-2 easy_align.txt /*easy-align-5-2*
easy-align-5-2-1 easy_align.txt /*easy-align-5-2-1*
easy-align-5-2-2 easy_align.txt /*easy-align-5-2-2*
easy-align-5-3 easy_align.txt /*easy-align-5-3*
easy-align-5-3-1 easy_align.txt /*easy-align-5-3-1*
easy-align-5-3-2 easy_align.txt /*easy-align-5-3-2*
easy-align-5-3-3 easy_align.txt /*easy-align-5-3-3*
easy-align-5-3-4 easy_align.txt /*easy-align-5-3-4*
easy-align-5-4 easy_align.txt /*easy-align-5-4*
easy-align-5-5 easy_align.txt /*easy-align-5-5*
easy-align-5-6 easy_align.txt /*easy-align-5-6*
easy-align-6 easy_align.txt /*easy-align-6*
easy-align-6-1 easy_align.txt /*easy-align-6-1*
easy-align-6-2 easy_align.txt /*easy-align-6-2*
easy-align-6-2-1 easy_align.txt /*easy-align-6-2-1*
easy-align-6-3 easy_align.txt /*easy-align-6-3*
easy-align-6-4 easy_align.txt /*easy-align-6-4*
easy-align-6-5 easy_align.txt /*easy-align-6-5*
easy-align-6-6 easy_align.txt /*easy-align-6-6*
easy-align-6-7 easy_align.txt /*easy-align-6-7*
easy-align-6-8 easy_align.txt /*easy-align-6-8*
easy-align-6-8-1 easy_align.txt /*easy-align-6-8-1*
easy-align-7 easy_align.txt /*easy-align-7*
easy-align-7-1 easy_align.txt /*easy-align-7-1*
easy-align-7-2 easy_align.txt /*easy-align-7-2*
easy-align-8 easy_align.txt /*easy-align-8*
easy-align-9 easy_align.txt /*easy-align-9*
easy-align-adjusting-indentation easy_align.txt /*easy-align-adjusting-indentation*
easy-align-advanced-examples-and-use-cases easy_align.txt /*easy-align-advanced-examples-and-use-cases*
easy-align-aligning-delimiters-of-different-lengths easy_align.txt /*easy-align-aligning-delimiters-of-different-lengths*
easy-align-alignment-options easy_align.txt /*easy-align-alignment-options*
easy-align-alignment-options-in-interactive-mode easy_align.txt /*easy-align-alignment-options-in-interactive-mode*
easy-align-alignments-over-multiple-occurrences-of-delimiters easy_align.txt /*easy-align-alignments-over-multiple-occurrences-of-delimiters*
easy-align-author easy_align.txt /*easy-align-author*
easy-align-concept-of-alignment-rule easy_align.txt /*easy-align-concept-of-alignment-rule*
easy-align-demo easy_align.txt /*easy-align-demo*
easy-align-disabling-foldmethod-during-alignment easy_align.txt /*easy-align-disabling-foldmethod-during-alignment*
easy-align-examples easy_align.txt /*easy-align-examples*
easy-align-execution-models easy_align.txt /*easy-align-execution-models*
easy-align-extending-alignment-rules easy_align.txt /*easy-align-extending-alignment-rules*
easy-align-features easy_align.txt /*easy-align-features*
easy-align-filtering-lines easy_align.txt /*easy-align-filtering-lines*
easy-align-ignoring-delimiters-in-comments-or-strings easy_align.txt /*easy-align-ignoring-delimiters-in-comments-or-strings*
easy-align-ignoring-unmatched-lines easy_align.txt /*easy-align-ignoring-unmatched-lines*
easy-align-installation easy_align.txt /*easy-align-installation*
easy-align-interactive-mode easy_align.txt /*easy-align-interactive-mode*
easy-align-left-right-center-mode-switch-in-interactive-mode easy_align.txt /*easy-align-left-right-center-mode-switch-in-interactive-mode*
easy-align-license easy_align.txt /*easy-align-license*
easy-align-list-of-options easy_align.txt /*easy-align-list-of-options*
easy-align-live-interactive-mode easy_align.txt /*easy-align-live-interactive-mode*
easy-align-non-interactive-mode easy_align.txt /*easy-align-non-interactive-mode*
easy-align-other-options easy_align.txt /*easy-align-other-options*
easy-align-partial-alignment-in-blockwise-visual-mode easy_align.txt /*easy-align-partial-alignment-in-blockwise-visual-mode*
easy-align-predefined-alignment-rules easy_align.txt /*easy-align-predefined-alignment-rules*
easy-align-related-work easy_align.txt /*easy-align-related-work*
easy-align-tldr-one-minute-guide easy_align.txt /*easy-align-tldr-one-minute-guide*
easy-align-toc easy_align.txt /*easy-align-toc*
easy-align-usage easy_align.txt /*easy-align-usage*
easy-align-using-regular-expressions easy_align.txt /*easy-align-using-regular-expressions*
easyalign easy_align.txt /*easyalign*
g:easy_align_bang_interactive_modes easy_align.txt /*g:easy_align_bang_interactive_modes*
g:easy_align_bypass_fold easy_align.txt /*g:easy_align_bypass_fold*
g:easy_align_delimiter_align easy_align.txt /*g:easy_align_delimiter_align*
g:easy_align_delimiters easy_align.txt /*g:easy_align_delimiters*
g:easy_align_ignore_groups easy_align.txt /*g:easy_align_ignore_groups*
g:easy_align_ignore_unmatched easy_align.txt /*g:easy_align_ignore_unmatched*
g:easy_align_indentation easy_align.txt /*g:easy_align_indentation*
g:easy_align_interactive_modes easy_align.txt /*g:easy_align_interactive_modes*
vim-easy-align easy_align.txt /*vim-easy-align*

View File

@ -0,0 +1,142 @@
" Copyright (c) 2014 Junegunn Choi
"
" MIT License
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the
" "Software"), to deal in the Software without restriction, including
" without limitation the rights to use, copy, modify, merge, publish,
" distribute, sublicense, and/or sell copies of the Software, and to
" permit persons to whom the Software is furnished to do so, subject to
" the following conditions:
"
" The above copyright notice and this permission notice shall be
" included in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
if exists("g:loaded_easy_align_plugin")
finish
endif
let g:loaded_easy_align_plugin = 1
command! -nargs=* -range -bang EasyAlign <line1>,<line2>call easy_align#align(<bang>0, 0, 'command', <q-args>)
command! -nargs=* -range -bang LiveEasyAlign <line1>,<line2>call easy_align#align(<bang>0, 1, 'command', <q-args>)
let s:last_command = 'EasyAlign'
function! s:abs(v)
return a:v >= 0 ? a:v : - a:v
endfunction
function! s:remember_visual(mode)
let s:last_visual = [a:mode, s:abs(line("'>") - line("'<")), s:abs(col("'>") - col("'<"))]
endfunction
function! s:repeat_visual()
let [mode, ldiff, cdiff] = s:last_visual
let cmd = 'normal! '.mode
if ldiff > 0
let cmd .= ldiff . 'j'
endif
let ve_save = &virtualedit
try
if mode == "\<C-V>"
if cdiff > 0
let cmd .= cdiff . 'l'
endif
set virtualedit+=block
endif
execute cmd.":\<C-r>=g:easy_align_last_command\<Enter>\<Enter>"
call s:set_repeat()
finally
if ve_save != &virtualedit
let &virtualedit = ve_save
endif
endtry
endfunction
function! s:repeat_in_visual()
if exists('g:easy_align_last_command')
call s:remember_visual(visualmode())
call s:repeat_visual()
endif
endfunction
function! s:set_repeat()
silent! call repeat#set("\<Plug>(EasyAlignRepeat)")
endfunction
function! s:generic_easy_align_op(type, vmode, live)
if !&modifiable
if a:vmode
normal! gv
endif
return
endif
let sel_save = &selection
let &selection = "inclusive"
if a:vmode
let vmode = a:type
let [l1, l2] = ["'<", "'>"]
call s:remember_visual(vmode)
else
let vmode = ''
let [l1, l2] = [line("'["), line("']")]
unlet! s:last_visual
endif
try
let range = l1.','.l2
if get(g:, 'easy_align_need_repeat', 0)
execute range . g:easy_align_last_command
else
execute range . "call easy_align#align(0, a:live, vmode, '')"
end
call s:set_repeat()
finally
let &selection = sel_save
endtry
endfunction
function! s:easy_align_op(type, ...)
call s:generic_easy_align_op(a:type, a:0, 0)
endfunction
function! s:live_easy_align_op(type, ...)
call s:generic_easy_align_op(a:type, a:0, 1)
endfunction
function! s:easy_align_repeat()
if exists('s:last_visual')
call s:repeat_visual()
else
try
let g:easy_align_need_repeat = 1
normal! .
finally
unlet! g:easy_align_need_repeat
endtry
endif
endfunction
nnoremap <silent> <Plug>(EasyAlign) :set opfunc=<SID>easy_align_op<Enter>g@
vnoremap <silent> <Plug>(EasyAlign) :<C-U>call <SID>easy_align_op(visualmode(), 1)<Enter>
nnoremap <silent> <Plug>(LiveEasyAlign) :set opfunc=<SID>live_easy_align_op<Enter>g@
vnoremap <silent> <Plug>(LiveEasyAlign) :<C-U>call <SID>live_easy_align_op(visualmode(), 1)<Enter>
" vim-repeat support
nnoremap <silent> <Plug>(EasyAlignRepeat) :call <SID>easy_align_repeat()<Enter>
vnoremap <silent> <Plug>(EasyAlignRepeat) :<C-U>call <SID>repeat_in_visual()<Enter>
" Backward-compatibility (deprecated)
nnoremap <silent> <Plug>(EasyAlignOperator) :set opfunc=<SID>easy_align_op<Enter>g@

View File

@ -0,0 +1,605 @@
*fswitch.txt* For Vim version 7.2 and above Last change: 2009 Mar 23
---------------
File Switcher
---------------
Author: Derek Wyatt (derek at myfirstnamemylastname dot org)
*fswitch-copyright*
Copyright: The VIM LICENSE applies to fswitch.vim, and fswitch.txt
(see |copyright|) except use "fswitch" instead of "Vim".
No warranty, express or implied.
Use At-Your-Own-Risk!
==============================================================================
*fswitch* *fswitch-contents*
1. Contents~
1. Contents .............................: |fswitch-contents|
2. About ................................: |fswitch-about|
3. Features .............................: |fswitch-features|
4. Setup ................................: |fswitch-setup|
5. Configuration ........................: |fswitch-configure|
6. "Creating" the Alternate File ........: |fswitch-altcreate|
7. Useful Mappings ......................: |fswitch-mappings|
8. FSwitch() ............................: |fswitch-function|
9. FSReturnCompanionFilenameString().....: |fswitch-getcompanion|
10. FSReturnReadableCompanionFilename()...: |fswitch-getreadablecomp|
11. The Default Settings .................: |fswitch-defaults|
12. Examples .............................: |fswitch-examples|
13. Troubleshooting ......................: |fswitch-trouble|
A. Change History .......................: |fswitch-changes|
==============================================================================
*fswitch-about*
2. About~
FSwitch is designed to allow you to switch between companion files of source
code (e.g. "cpp" files and their corresponding "h" files). The source for
this came from a home-grown script that was influenced later by the
"Alternate" (a.vim) script.
The original intention was to modify the existing a.vim script to do what the
home-grown version could do (choose to open the other file in an existing
window) but it was a rather complex script and modification looked difficult
so the choice was made to simply move the home-grown script forward a couple
of notches and produce a new plugin. This doc file is twice the length of the
actual code at this point :)
==============================================================================
*fswitch-features*
3. Features~
FSwitch has the following features:
- Switches between a file and its companion file
- Ability to create a new file using a preferential location
- Simple configuration using buffer-local variables
- It's got a really long doc file (... seriously, why is this thing so
bloody long?)
- Umm... other stuff?
==============================================================================
*fswitch-setup*
4. Setup~
Most of the behaviour of FSwitch is customized via buffer-local variables.
You set up the variables with auto commands:
>
au! BufEnter *.cpp let b:fswitchdst = 'hpp,h' | let b:fswitchlocs = '../inc'
<
That |:autocmd| will set the 'fswitchdst' and 'fswitchlocs' variables when the
|BufEnter| event takes place on a file whose name matches {*.cpp} (e.g. when
you enter the buffer containing the {MyFile.cpp} file).
The variables above state that the alternate file to {MyFile.cpp} are
{MyFile.hpp} and {MyFile.h} preferred in that order, and located in the {inc}
directory at the same level as the current directory.
That should get you there but there's more capability here if you want. To
get that move on to |fswitch-configure|.
==============================================================================
*fswitch-configure*
5. Configuration~
*'fswitchdst'*
'fswitchdst' string (default depends on file in current buffer)
local to buffer
The 'fswitchdst' variable denotes the file extension that is the
target extension of the current file's companion file. For example:
>
:let b:fswitchdst = 'cpp,cxx,C'
<
The above specifies that the current buffer's file has a companion
filename which can be found by replacing the current extension with
{cpp}, {cxx} or {C}. The extensions will be tried in this order and
the first match wins.
'fswitchdst' is taken relative to directories that are found in the
'fswitchlocs' variable.
*'fswitchlocs'*
'fswitchlocs' string (default depends on file in current buffer)
local to buffer
The 'fswitchlocs' variable contains a set of directives that indicate
directory names that should be formulated when trying to find the
alternate file. For example:
>
" Create the destination path by substituting any
" 'include' string from the pathname with 'src'
:let b:fswitchlocs = 'reg:/include/src/'
" First try adding the relative path '../src' to the path
" in which the file in the buffer exists and if that fails
" then try using 'source' instead
:let b:fswitchlocs = 'rel:../src,source'
" Same as above but leaving off the optional 'rel:'
:let b:fswitchlocs = '../src,../source'
<
The following types of directives are understood:
*fswitch_reg*
reg:~
A regular expression. The regular expression takes the form:
>
{delim}{pat}{delim}{globsub}{delim}
<
Where:
{delim} is something that doesn't appear in {pat} or
{globsub} used to delimit the {pat} and {globsub}
{pat} is a standard pattern to search on
{globsub} is a substitution string that will be run through
the |glob()| function.
*fswitch_rel*
rel:~
A relative path. The {rel:} is actually optional. If you
leave this off, then FSwitch will assume that the string is
denoting a relative path.
*fswitch_ifrel*
ifrel:~
Takes the same form as {:reg} but the {globsub} part of the
directive is a relative path. The relative path is only used
if the {pat} matches the existing path of the buffer.
*fswitch_abs*
abs:~
An absolute path. I have no idea why you'd ever want to do
this, but it's there if you want it.
*fswitch_ifabs*
ifabs:~
Takes the same form as {:reg} but the {globsub} part of the
directive is an absolute path. The absolute path is only used
if the {pat} matches the existing path of the buffer.
Why use the "if" variants?
Here's the situation: You've got the following file:
>
~/code/MyFile.h
<
And you've set the following locations:
>
For .h -> reg:/include/src/,../src,./
For .cpp -> reg:/src/include/,../include,./
<
Here's what happens when run the following commands:
>
FSwitch('%')
# Creates a new file ~/src/MyFile.cpp due to the first
# relative path in the list for .h
FSwitch('%')
# Creates a new file ~/include/MyFile.h due to the first
# regular expression in the list for .cpp
<
The problem is that you've unconditionally said you want to use
{../src} for the alternate file but in reality you probably wanted to
use {./}. If you use {:ifrel} instead then you can say that you only
want to use {../src} if the path to the current buffer contains
{/include/} or something like that. If you did this FSwitch would not
have taken {../src} for the new file but would have chosen {./}
So the "right" setup is:
>
For .h -> reg:/include/src/,ifrel:|/include/|../src|,./
For .cpp -> reg:/src/include/,ifrel:|/src/|../include|,./
<
*'fswitchdisablegloc'*
'fsdisablegloc'
string (default off)
local to buffer
Disables the appending of the default global locations to the local
buffer definition. Normally when processing alternate file locations
FSwitch will append some default values to the list of locations. If
you define this variable then this will not happen.
The default locations are currently set to "./" or ".\" depending on
what slash your configuration evaluates to.
*'fswitchfnames'*
'fswitchfnames' string (default depends on file in current buffer)
local to buffer
The 'fswitchfnames' variable contains a comma-separated list
of possible substitution patterns over the base filename (without path
and extension) that should be formulated when trying to find the
alternate file. The format of the substitution pattern is the same
as |fswitch-reg|.
This may be useful when the companion file may can be formulated by
adding a suffix to the base filename. For instance, when the companion
of MyClass.java is MyClassTest.java.
For example:
>
" Create the destination filename by appending 'Test'
" to the filename
:let b:fswitchfnames = '/$/Test/'
" Create the destination filename by removing 'Test'
" from the end of the filename.
:let b:fswitchfnames = '/Test$//'
<
*'fswitchnonewfiles'*
'fsnonewfiles'
string (default off)
local to buffer and global
This variable is both global and local. If you want to disable the
creation of the alternate file when it doesn't already exist you can
choose to do this on a per-extension basis or globally. Set the
global one to shut it off all the time and use the buffer version to
shut it off locally.
*'fsneednomatch'*
'fsneednomatch'
string (default off)
local to buffer and global
Normally when doing a regular expression alteration of the path (see
{reg:} in 'fswitchdst' the pattern you're going to substitute the
value with must actually match in the string. When it doesn't matter
whether or not that the match actually takes place, you can set this
value.
If you do set this then the failure to match actually results in
nothing happening at all. So if the right filename exists in the same
directory as the one you're switching from then that's the one that
will be switched to.
Example:
>
If the b:fswitchlocs is set to
reg:/src/include/,include
and
# This is the file we're editing
~/code/program/myfile.c
# These choices exist for the header file
~/code/program/myfile.h
~/code/program/include/myfile.h
<
Then the first substitution will result in the first header file being
chosen, not the second.
==============================================================================
*fswitch-altcreate*
6. "Creating" the Alternate File~
If the file being switched to does not exist, and 'fsnonewfiles' has not been
set, then it will be created as a new, unwritten buffer. If there are
multiple possibilities here, FSwitch prefers the first possible match. For
example if the current buffer has a filename called {/code/src/a/b/MyFile.cpp}
and has the following set:
>
let b:fswitchdst = 'h,hpp'
let b:fswitchlocs = 'reg:/src/include/,../include,../inc'
<
then the created filename will be {/code/include/a/b/MyFile.cpp}.
As stated, this file hasn't actually been written to yet so you could easily
delete the buffer and there's no harm done but you also may not be able to
write the buffer very easily if the directory hierarchy doesn't yet exist. In
this case, it's quite helpful to define a mapping for easily creating the
directory for you:
>
nmap <Leader>md :!mkdir -p %:p:h<cr>
<
Then it's pretty easy to create the directory before writing the file.
==============================================================================
*fswitch-mappings*
7. Useful Mappings~
I didn't bother putting mappings into the script directly as this might have
caused conflicts and I don't know how to avoid those. I use the following
mappings myself:
- Switch to the file and load it into the current window >
nmap <silent> <Leader>of :FSHere<cr>
<
- Switch to the file and load it into the window on the right >
nmap <silent> <Leader>ol :FSRight<cr>
<
- Switch to the file and load it into a new window split on the right >
nmap <silent> <Leader>oL :FSSplitRight<cr>
<
- Switch to the file and load it into the window on the left >
nmap <silent> <Leader>oh :FSLeft<cr>
<
- Switch to the file and load it into a new window split on the left >
nmap <silent> <Leader>oH :FSSplitLeft<cr>
<
- Switch to the file and load it into the window above >
nmap <silent> <Leader>ok :FSAbove<cr>
<
- Switch to the file and load it into a new window split above >
nmap <silent> <Leader>oK :FSSplitAbove<cr>
<
- Switch to the file and load it into the window below >
nmap <silent> <Leader>oj :FSBelow<cr>
<
- Switch to the file and load it into a new window split below >
nmap <silent> <Leader>oJ :FSSplitBelow<cr>
<
==============================================================================
*FSwitch()*
8. FSwitch()~
The main work is done by the FSwitch() function. The reason it's documented
here is because you can use it to do something more interesting if you wish.
As it stands now, you get the "Split Above and Switch" functionality by
calling FSwitch() like this:
>
FSwitch('%', 'split \| wincmd k')
<
There's probably not much to stop anyone from doing something more interesting
in the second argument. If this string is non-empty then it will be run
through an |:execute| call.
==============================================================================
*fswitch-getcompanion* *FSReturnCompanionFilenameString()*
9. FSReturnCompanionFilenameString()~
This function is used by |FSwitch()| to return the pathname to the preferred
companion file. In this case, the file need not actually exist on the
filesystem but would be the one created if you chose to do so. As an
example:
>
let path = FSReturnCompanionFilenameString('%')
<
The resultant path string contains the preferred companion file or nothing if
no preferred file could be discovered.
==============================================================================
*fswitch-getreadablecomp* *FSReturnReadableCompanionFilename()*
10. FSReturnReadableCompanionFilename()~
This function returns the companion file, but the companion file must be
readable on the filesystem for it to be successfully returned.
>
let path = FSReturnReadableCompanionFilename('%')
<
The resultant path string contains the preferred companion file or nothing if
no preferred file could be found on the filesystem.
In order to see what created the need for this function, see
|fswitch-example3|.
==============================================================================
*fswitch-defaults*
11. The Default Settings~
By default FSwitch handles {c}, {cc}, {cpp}, {cxx} and {C}. Note that the
difference between {c} and {C} is only case sensitivity. This may mean that
weird stuff happens if your OS is case insensitive.
Also NOTE that when you use {cxx/hxx} or {C/H}, god kills a puppy.
Consider that next time you want to do such a silly thing.
For *.h files:
>
let b:fswitchdst = 'c,cpp'
let b:fswitchlocs = 'reg:/include/src/,reg:/include.*/src/,../src'
<
For *.hpp files:
>
let b:fswitchdst = 'cpp'
let b:fswitchlocs = 'reg:/include/src/,reg:/include.*/src/,../src'
<
For *.hxx files:
>
let b:fswitchdst = 'cxx'
let b:fswitchlocs = 'reg:/include/src/,reg:/include.*/src/,../src'
<
For *.H files:
>
let b:fswitchdst = 'C'
let b:fswitchlocs = 'reg:/include/src/,reg:/include.*/src/,../src'
<
For *.c
>
let b:fswitchdst = 'h'
let b:fswitchlocs = 'reg:/src/include/,reg:|src|include/**|,../include'
<
For *.cpp
>
let b:fswitchdst = 'hpp,h'
let b:fswitchlocs = 'reg:/src/include/,reg:|src|include/**|,../include'
<
For *.cxx
>
let b:fswitchdst = 'hxx'
let b:fswitchlocs = 'reg:/src/include/,reg:|src|include/**|,../include'
<
For *.C
>
let b:fswitchdst = 'H'
let b:fswitchlocs = 'reg:/src/include/,reg:|src|include/**|,../include'
<
==============================================================================
*fswitch-examples*
12. Examples~
*fswitch-example1*
Let's say you have a C++ codebase and it has the following properties (this
level of insanity is a bit high but versions that are only slightly saner
exist in real life):
- Source files with {.cpp}, {.cc} and {.C} extensions
- Header files with {.h} extensions
- Source files and header files in the same directory
- Source files in the {src} directory and include files in the
{include} directory
- Source files in the {src} directory and include files in the
{include/name/space} directory (i.e. subdirectories denoted by the
namespace).
- Source files in {src/name/space} and header files in
{include/name/space} (i.e. subdirectories denoted by the namespace).
As a final part to this, the "new" way of doing things in this source tree is
to put header files in a directory noted by namespace and to do the same with
source files and to name source files with a {cpp} extension.
In order to switch between files organized like this, you could specify the
following:
>
augroup mycppfiles
au!
au BufEnter *.h let b:fswitchdst = 'cpp,cc,C'
au BufEnter *.h let b:fswitchlocs = 'reg:/include/src/,reg:/include.*/src/'
augroup END
<
Here the setting of b:fswitchdst to {cpp,cc,C} handles the different C++
extensions, and prefers to use {cpp} and will create new files with that
extension.
The fswitchlocs setting allows for the following:
reg:/include/src/~
Take the pathname to the file in the current buffer and
substitute "src" for "include". This handles the following
possibilities:
- Files are in {include} and {src} respectively
- Files are in {include/name/space} and {src/name/space}
respectively
reg:/include.*/src/~
Take the pathname to the file in the current buffer and
substitute "src" for "include.*". This handles the following
possibility:
- Files are in {include/name/space} and {src} respectively
./~
This one's a hiddden option. The default location is the
current directory already so we don't explicitly have to state
this, but it is the last possibility:
- Files are in the same directory
*fswitch-example2*
Here we'll just show a quick example of making use of the globbing aspect of
the system. Let's say you're working on a {cpp} file and you want to find the
matching header file, and you have your destination and locations set to the
following:
>
let b:fswitchdst = 'h'
let b:fswitchlocs = 'reg:|src|include/**|'
>
then if you have the a file {src/MyFile.cpp} then this will find the file
{include/name/space/MyFile.h}.
*fswitch-example3*
At work I'm a Windows C++ programmer and at home I'm a OS X Objective-C
programmer. There's a problem with this... C++ and Objective-C both use the
same extension for header files ({.h}).
At home I want to be able to use the XCode command line builder in the
'makeprg' setting when I'm working on the code. I would like this to be set
when I am on a {.m} file or its companion {.h} file. This is done with the
following function:
>
function! SetMakeForXCode(filename)
let isObjCFile = 0
let ext = expand(a:filename . ":e")
if ext == 'm' || ext == 'mm'
let isObjCFile = 1
elseif ext == 'h'
" Find the companion file
let companionfile = FSReturnReadableCompanionFilename('%')
" For some reason expand() doesn't work on the next line
let companionext = substitute(companionfile, '.*\.', '', '')
if companionext == 'm' || companionext == 'mm'
let isObjCFile = 1
endif
endif
if isObjCFile == 1
setl makeprg=xcodebuild\ -configuration\ Debug
endif
endfunction
<
Yup, this could have been easier by using the 'filetype' or using some sort of
|grep| call but I wanted to use this particular hammer. :) I'll probably end
up switching it to use the 'filetype' instead in the end...
==============================================================================
*fswitch-trouble*
13. TroubleShooting~
*fswitch-empty*
You may get the following error:
>
Alternate has evaluated to nothing. See :h fswitch-empty for more info.
<
It can happen... This is probably due to the fact that you've got a nicely
strict set of rules for your locations. With |fswitch-reg| and
|fswitch-ifrel| and |fswitch-ifabs| you can get rather specific about whether
or not anything actually happens. If you aren't letting anything really
happen, it's not going to happen and you're going to end up with an empty
path.
==============================================================================
*fswitch-changes*
A. Change History~
0.9.5
- Modified the autocommands to handle the myriad different
formulations of C++ files per Hong Xu's request. See:
https://github.com/derekwyatt/vim-fswitch/pull/3
0.9.4
- Added fixes from Alexey Radkov to handle the 'sb' and 'spr' option
settings as well as the 'switchbuf' option. See:
https://github.com/derekwyatt/vim-fswitch/pull/2
- Made small fix to Alexey's fix to keep the 'sb' and 'spr' shadow
variable local to the buffer and unlet them at the end.
- I made a quick regression check on this update but did not test
Alexey's features directly - I trust that he did that :)
0.9.3
- Made sure that there's a check for 7.0 (Thanks Timon Kelter)
0.9.2
- Fix for the splitting commands (Thanks Michael Henry)
0.9.1
- Added :ifrel (|fswitch_ifrel|)
- Added :ifabs (|fswitch_ifabs|)
- Added |FSReturnReadableCompanionFilename()|
- Added |FSReturnCompanionFilenameString()|
- Changed default settings for .h to use :ifrel instead of :rel
- Changed default settings for .c and .cpp to use :ifrel instead of
:rel
0.9.0
- Initial release
vim:tw=78:sts=8:ts=8:sw=8:noet:ft=help:

View File

@ -0,0 +1,34 @@
'fsneednomatch' fswitch.txt /*'fsneednomatch'*
'fswitchdisablegloc' fswitch.txt /*'fswitchdisablegloc'*
'fswitchdst' fswitch.txt /*'fswitchdst'*
'fswitchfnames' fswitch.txt /*'fswitchfnames'*
'fswitchlocs' fswitch.txt /*'fswitchlocs'*
'fswitchnonewfiles' fswitch.txt /*'fswitchnonewfiles'*
FSReturnCompanionFilenameString() fswitch.txt /*FSReturnCompanionFilenameString()*
FSReturnReadableCompanionFilename() fswitch.txt /*FSReturnReadableCompanionFilename()*
FSwitch() fswitch.txt /*FSwitch()*
fswitch fswitch.txt /*fswitch*
fswitch-about fswitch.txt /*fswitch-about*
fswitch-altcreate fswitch.txt /*fswitch-altcreate*
fswitch-changes fswitch.txt /*fswitch-changes*
fswitch-configure fswitch.txt /*fswitch-configure*
fswitch-contents fswitch.txt /*fswitch-contents*
fswitch-copyright fswitch.txt /*fswitch-copyright*
fswitch-defaults fswitch.txt /*fswitch-defaults*
fswitch-empty fswitch.txt /*fswitch-empty*
fswitch-example1 fswitch.txt /*fswitch-example1*
fswitch-example2 fswitch.txt /*fswitch-example2*
fswitch-example3 fswitch.txt /*fswitch-example3*
fswitch-examples fswitch.txt /*fswitch-examples*
fswitch-features fswitch.txt /*fswitch-features*
fswitch-getcompanion fswitch.txt /*fswitch-getcompanion*
fswitch-getreadablecomp fswitch.txt /*fswitch-getreadablecomp*
fswitch-mappings fswitch.txt /*fswitch-mappings*
fswitch-setup fswitch.txt /*fswitch-setup*
fswitch-trouble fswitch.txt /*fswitch-trouble*
fswitch.txt fswitch.txt /*fswitch.txt*
fswitch_abs fswitch.txt /*fswitch_abs*
fswitch_ifabs fswitch.txt /*fswitch_ifabs*
fswitch_ifrel fswitch.txt /*fswitch_ifrel*
fswitch_reg fswitch.txt /*fswitch_reg*
fswitch_rel fswitch.txt /*fswitch_rel*

View File

@ -0,0 +1,364 @@
" ============================================================================
" File: fswitch.vim
"
" Description: Vim global plugin that provides decent companion source file
" switching
"
" Maintainer: Derek Wyatt <derek at myfirstnamemylastname dot org>
"
" Last Change: March 23rd 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:disable_fswitch")
finish
endif
if v:version < 700
echoerr "FSwitch requires Vim 7.0 or higher."
finish
endif
" Version
let s:fswitch_version = '0.9.5'
" Get the path separator right
let s:os_slash = &ssl == 0 && (has("win16") || has("win32") || has("win64")) ? '\' : '/'
" Default locations - appended to buffer locations unless otherwise specified
let s:fswitch_global_locs = '.' . s:os_slash
"
" s:SetVariables
"
" There are two variables that need to be set in the buffer in order for things
" to work correctly. Because we're using an autocmd to set things up we need to
" be sure that the user hasn't already set them for us explicitly so we have
" this function just to check and make sure. If the user's autocmd runs after
" ours then they will override the value anyway.
"
function! s:SetVariables(dst, locs)
if !exists("b:fswitchdst")
let b:fswitchdst = a:dst
endif
if !exists("b:fswitchlocs")
let b:fswitchlocs = a:locs
endif
endfunction
"
" s:FSGetLocations
"
" Return the list of possible locations
"
function! s:FSGetLocations()
let locations = []
if exists("b:fswitchlocs")
let locations = split(b:fswitchlocs, ',')
endif
if !exists("b:fsdisablegloc") || b:fsdisablegloc == 0
let locations += split(s:fswitch_global_locs, ',')
endif
return locations
endfunction
"
" s:FSGetExtensions
"
" Return the list of destination extensions
"
function! s:FSGetExtensions()
return split(b:fswitchdst, ',')
endfunction
"
" s:FSGetFilenameMutations
"
" Return the list of possible filename mutations
"
function! s:FSGetFilenameMutations()
if !exists("b:fswitchfnames")
" For backward-compatibility out default mutation is an identity.
return ['/^//']
else
return split(b:fswitchfnames, ',')
endif
endfunction
"
" s:FSGetMustMatch
"
" Return a boolean on whether or not the regex must match
"
function! s:FSGetMustMatch()
let mustmatch = 1
if exists("b:fsneednomatch") && b:fsneednomatch != 0
let mustmatch = 0
endif
return mustmatch
endfunction
"
" s:FSGetFullPathToDirectory
"
" Given the filename, return the fully qualified directory portion
"
function! s:FSGetFullPathToDirectory(filename)
return expand(a:filename . ':p:h')
endfunction
"
" s:FSGetFileExtension
"
" Given the filename, returns the extension
"
function! s:FSGetFileExtension(filename)
return expand(a:filename . ':e')
endfunction
"
" s:FSGetFileNameWithoutExtension
"
" Given the filename, returns just the file name without the path or extension
"
function! s:FSGetFileNameWithoutExtension(filename)
return expand(a:filename . ':t:r')
endfunction
"
" s:FSMutateFilename
"
" Takes a filename and a filename mutation directive and applies the mutation
" to it.
function! s:FSMutateFilename(filename, directive)
let separator = strpart(a:directive, 0, 1)
let dirparts = split(strpart(a:directive, 1), separator)
if len(dirparts) < 2 || len(dirparts) > 3
throw 'Bad mutation directive "' . a:directive . '".'
else
let flags = ''
if len(dirparts) == 3
let flags = dirparts[2]
endif
return substitute(a:filename, dirparts[0], dirparts[1], flags)
endif
endfunction
"
" s:FSGetAlternateFilename
"
" Takes the path, name and extension of the file in the current buffer and
" applies the location to it. If the location is a regular expression pattern
" then it will split that up and apply it accordingly. If the location pattern
" is actually an explicit relative path or an implicit one (default) then it
" will simply apply that to the file directly.
"
function! s:FSGetAlternateFilename(filepath, filename, newextension, location, mustmatch)
let parts = split(a:location, ':')
let cmd = 'rel'
let directive = parts[0]
if len(parts) == 2
let cmd = parts[0]
let directive = parts[1]
endif
if cmd == 'reg' || cmd == 'ifrel' || cmd == 'ifabs'
if strlen(directive) < 3
throw 'Bad directive "' . a:location . '".'
else
let separator = strpart(directive, 0, 1)
let dirparts = split(strpart(directive, 1), separator)
if len(dirparts) < 2 || len(dirparts) > 3
throw 'Bad directive "' . a:location . '".'
else
let part1 = dirparts[0]
let part2 = dirparts[1]
let flags = ''
if len(dirparts) == 3
let flags = dirparts[2]
endif
if cmd == 'reg'
if a:mustmatch == 1 && match(a:filepath, part1) == -1
let path = ""
else
let path = substitute(a:filepath, part1, part2, flags) . s:os_slash .
\ a:filename . '.' . a:newextension
endif
elseif cmd == 'ifrel'
if match(a:filepath, part1) == -1
let path = ""
else
let path = a:filepath . s:os_slash . part2 .
\ s:os_slash . a:filename . '.' . a:newextension
endif
elseif cmd == 'ifabs'
if match(a:filepath, part1) == -1
let path = ""
else
let path = part2 . s:os_slash . a:filename . '.' . a:newextension
endif
endif
endif
endif
elseif cmd == 'rel'
let path = a:filepath . s:os_slash . directive . s:os_slash . a:filename . '.' . a:newextension
elseif cmd == 'abs'
let path = directive . s:os_slash . a:filename . '.' . a:newextension
endif
return simplify(path)
endfunction
"
" s:FSReturnCompanionFilename
"
" This function will return a path that is the best candidate for the companion
" file to switch to. If mustBeReadable == 1 when then the companion file will
" only be returned if it is readable on the filesystem, otherwise it will be
" returned so long as it is non-empty.
"
function! s:FSReturnCompanionFilename(filename, mustBeReadable)
let fullpath = s:FSGetFullPathToDirectory(a:filename)
let ext = s:FSGetFileExtension(a:filename)
let justfile = s:FSGetFileNameWithoutExtension(a:filename)
let extensions = s:FSGetExtensions()
let filenameMutations = s:FSGetFilenameMutations()
let locations = s:FSGetLocations()
let mustmatch = s:FSGetMustMatch()
let newpath = ''
for currentExt in extensions
for loc in locations
for filenameMutation in filenameMutations
let mutatedFilename = s:FSMutateFilename(justfile, filenameMutation)
let newpath = s:FSGetAlternateFilename(fullpath, mutatedFilename, currentExt, loc, mustmatch)
if a:mustBeReadable == 0 && newpath != ''
return newpath
elseif a:mustBeReadable == 1
let newpath = glob(newpath)
if filereadable(newpath)
return newpath
endif
endif
endfor
endfor
endfor
return newpath
endfunction
"
" FSReturnReadableCompanionFilename
"
" This function will return a path that is the best candidate for the companion
" file to switch to, so long as that file actually exists on the filesystem and
" is readable.
"
function! FSReturnReadableCompanionFilename(filename)
return s:FSReturnCompanionFilename(a:filename, 1)
endfunction
"
" FSReturnCompanionFilenameString
"
" This function will return a path that is the best candidate for the companion
" file to switch to. The file does not need to actually exist on the
" filesystem in order to qualify as a proper companion.
"
function! FSReturnCompanionFilenameString(filename)
return s:FSReturnCompanionFilename(a:filename, 0)
endfunction
"
" FSwitch
"
" This is the only externally accessible function and is what we use to switch
" to the alternate file.
"
function! FSwitch(filename, precmd)
if !exists("b:fswitchdst") || strlen(b:fswitchdst) == 0
throw 'b:fswitchdst not set - read :help fswitch'
endif
if (!exists("b:fswitchlocs") || strlen(b:fswitchlocs) == 0) &&
\ (!exists("b:fsdisablegloc") || b:fsdisablegloc == 0)
throw "There are no locations defined (see :h fswitchlocs and :h fsdisablegloc)"
endif
let newpath = FSReturnReadableCompanionFilename(a:filename)
let openfile = 1
if !filereadable(newpath)
if exists("b:fsnonewfiles") || exists("g:fsnonewfiles")
let openfile = 0
else
let newpath = FSReturnCompanionFilenameString(a:filename)
endif
endif
if &switchbuf =~ "^use"
let i = 1
let bufnum = winbufnr(i)
while bufnum != -1
let filename = fnamemodify(bufname(bufnum), ':p')
if filename == newpath
execute ":sbuffer " . filename
return
endif
let i += 1
let bufnum = winbufnr(i)
endwhile
endif
if openfile == 1
if newpath != ''
if strlen(a:precmd) != 0
execute a:precmd
endif
let s:fname = fnameescape(newpath)
if (strlen(bufname(s:fname))) > 0
execute 'buffer ' . s:fname
else
execute 'edit ' . s:fname
endif
else
echoerr "Alternate has evaluated to nothing. See :h fswitch-empty for more info."
endif
else
echoerr "No alternate file found. 'fsnonewfiles' is set which denies creation."
endif
endfunction
"
" The autocmds we set up to set up the buffer variables for us.
"
augroup fswitch_au_group
au!
au BufEnter *.c call s:SetVariables('h', 'reg:/src/include/,reg:|src|include/**|,ifrel:|/src/|../include|')
au BufEnter *.cc call s:SetVariables('hh', 'reg:/src/include/,reg:|src|include/**|,ifrel:|/src/|../include|')
au BufEnter *.cpp call s:SetVariables('hpp,h', 'reg:/src/include/,reg:|src|include/**|,ifrel:|/src/|../include|')
au BufEnter *.cxx call s:SetVariables('hxx', 'reg:/src/include/,reg:|src|include/**|,ifrel:|/src/|../include|')
au BufEnter *.C call s:SetVariables('H', 'reg:/src/include/,reg:|src|include/**|,ifrel:|/src/|../include|')
au BufEnter *.m call s:SetVariables('h', 'reg:/src/include/,reg:|src|include/**|,ifrel:|/src/|../include|')
au BufEnter *.h call s:SetVariables('c,cpp,m', 'reg:/include/src/,reg:/include.*/src/,ifrel:|/include/|../src|')
au BufEnter *.hh call s:SetVariables('cc', 'reg:/include/src/,reg:/include.*/src/,ifrel:|/include/|../src|')
au BufEnter *.hpp call s:SetVariables('cpp', 'reg:/include/src/,reg:/include.*/src/,ifrel:|/include/|../src|')
au BufEnter *.hxx call s:SetVariables('cxx', 'reg:/include/src/,reg:/include.*/src/,ifrel:|/include/|../src|')
au BufEnter *.H call s:SetVariables('C', 'reg:/include/src/,reg:/include.*/src/,ifrel:|/include/|../src|')
augroup END
"
" The mappings used to do the good work
"
com! FSHere :call FSwitch('%', '')
com! FSRight :call FSwitch('%', 'wincmd l')
com! FSSplitRight :call FSwitch('%', 'let curspr=&spr | set nospr | vsplit | wincmd l | if curspr | set spr | endif')
com! FSLeft :call FSwitch('%', 'wincmd h')
com! FSSplitLeft :call FSwitch('%', 'let curspr=&spr | set nospr | vsplit | if curspr | set spr | endif')
com! FSAbove :call FSwitch('%', 'wincmd k')
com! FSSplitAbove :call FSwitch('%', 'let cursb=&sb | set nosb | split | if cursb | set sb | endif')
com! FSBelow :call FSwitch('%', 'wincmd j')
com! FSSplitBelow :call FSwitch('%', 'let cursb=&sb | set nosb | split | wincmd j | if cursb | set sb | endif')
com! FSTab :call FSwitch('%', 'tabedit')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
au BufNewFile,BufRead *.gph set ft=gph syn=gph

View File

@ -0,0 +1,104 @@
" Syntax colouring for gopher .gph files used by geomyidae
" Muddled about a bit by dive @ freenode / #gopherproject
" 2017-11-15
set shiftwidth=4
set tabstop=4
set expandtab
" modif by sdk
setl enc=utf-8
setl wrap
setl linebreak
setl nolist
setl textwidth=72
setl formatprg=par\ -w72qie
setl nojs
setl nosmartindent
"setl spell
setl nospell
setl formatoptions=troqwbj
" end
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
" Use default terminal colours
hi Normal ctermbg=NONE ctermfg=NONE guifg=NONE guibg=NONE
" Use italics for comments. If this fails and you get reverse video
" then you may want to comment it out.
hi Comment cterm=italic
" Err colour (not sure about this one. It's a bit bright).
hi Err cterm=bold ctermbg=NONE ctermfg=130 guibg=NONE guifg=red
hi def link gopherComment comment
hi def link gopherType preproc
hi def link gopherURL statement
hi def link gopherHtml statement
hi def link gopherLink statement
hi def link gopherServerPort statement
hi def link gopherBracket preproc
hi def link gopherPipe preproc
hi def link gopherCGI type
hi def link gopherCGI2 type
hi def link gopherQuery type
hi def link gopherErr err
hi def link SynError error
" Format of lines:
" [<type>|<desc>|<path>|<host>|<port>]
"<desc> = description of gopher item. Most printable characters should work.
"
"<path> = full path to gopher item (base value is "/" ). Use the "Err" path for
"items not intended to be served.
"
"<host> = hostname or IP hosting the gopher item. Must be resolvable for the
"intended clients. If this is set to "server" , the server's hostname is used.
"
"<port> = TCP port number (usually 70) If this is set to "port" , the default
"port of the server is used.
" Comments
syn region gopherComment start="<!--" end="-->"
" URLs
syn match gopherURL "http:"
syn region gopherLink start="http:"lc=5 end="|"me=e-1
syn match gopherURL "gopher:"
syn match gopherURL "URL:"
syn match gopherURL "URI:"
syn region gopherLink start="gopher:"lc=7 end="|"me=e-1
" Pipes
syn match gopherPipe "|" containedin=gopherServerPort
" Queries and CGI
syn match gopherQuery "^\[7"lc=1
syn match gopherCGI "|[^|]*\.cgi[^|]*"lc=1
syn match gopherCGI2 "|[^|]*\.dcgi[^|]*"lc=1
" Server|Port
syn match gopherServerPort "|[^|]*|[^|]*]"
" Start and end brackets
match gopherBracket "[\[\]]"
" Entity
syn region gopherType start="^\[[0123456789ghHmswITi\+:;<PcMd\*\.]"lc=1 end="|" oneline
" HTML and networking
syn match gopherHtml "^\[[hHw8]"lc=1
" Text comments beginning with 't'
syn match gopherComment "^t"
" Err
syn match gopherErr "Err"
syn match gopherErr "^\[3"lc=1

View File

@ -0,0 +1,13 @@
name: Reviewdog
on: [pull_request]
jobs:
vint:
name: vint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: vint
uses: reviewdog/action-vint@v1
with:
github_token: ${{ secrets.github_token }}
reporter: github-pr-review

View File

@ -0,0 +1,42 @@
name: Vader
on: [push, pull_request]
jobs:
vader:
name: vader
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
vimFlavor: ["vim", "nvim"]
ledgerFlavor: ["ledger", "hledger"]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Enable Universe package repository
run: |
sudo add-apt-repository universe
sudo apt-get update
- name: Install ${{ matrix.ledgerFlavor }}
run: |
sudo apt-get install ${{ matrix.ledgerFlavor }}
- name: Install ${{ matrix.vimFlavor }}
run: |
sudo apt-get install ${{ matrix.vimFlavor == 'nvim' && 'neovim' || 'vim' }}
- name: Review versions
run: |
${{ matrix.ledgerFlavor }} --version
${{ matrix.vimFlavor }} --version
- name: Fetch Vader
run: |
git clone --depth 1 https://github.com/junegunn/vader.vim.git
- name: Run test suite
run: |
${{ matrix.vimFlavor == 'nvim' && 'nvim --headless' || 'vim -N' }} \
-u <(cat << VIMRC
filetype off
set rtp+=vader.vim
set rtp+=.
filetype plugin indent on
syntax enable
VIMRC
) "+Vader! spec/*"

View File

@ -0,0 +1,15 @@
name: Vint
on: [push]
jobs:
vint:
name: vint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
- name: Setup dependencies
run: pip install vim-vint
- name: Lint Vimscript
run: vint .

1
.vim/bundle/vim-ledger/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/doc/tags

View File

@ -0,0 +1,5 @@
cmdargs:
severity: style_problem
color: true
env:
neovim: false

View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,129 @@
# vim-ledger
[![Vint](https://github.com/ledger/vim-ledger/workflows/Vint/badge.svg)](https://github.com/ledger/vim-ledger/actions?workflow=Vint)
[![Vader](https://github.com/ledger/vim-ledger/workflows/Vader/badge.svg)](https://github.com/ledger/vim-ledger/actions?workflow=Vader)
Filetype detection, syntax highlighting, auto-formatting, auto-completion, and other tools for working with ledger files.
Compatible with both [`ledger`][ledgercli] and [`hledger`][hledger].
See [plaintextaccounting.org][pta] for background information and other useful links.
## Usage
Install as you would any other VIM plugin.
There are a variety of ways depending on your plugin manager.
For example with [Pathogen](https://github.com/tpope/vim-pathogen) you would clone this repository into your configuration directory.
With [vim-plug](https://github.com/junegunn/vim-plug) and many similar ones, you would declare it in your rc file like this, then run `:PlugInstall`:
```vimscript
Plug 'ledger/vim-ledger'
```
You can also manually copy the corresponding directories into your VIM plugins directory.
One installed this plugin will identify files ending with `.ldg`, `.ledger`, or `.journal` as ledger files automatically.
Alaternatively if you use a different extension you can add a modeline to each like this:
```ledger
; vim: filetype=ledger
```
## Tips and useful commands
* Try account-completion (as explained below)
* `:call ledger#transaction_date_set(line('.'), 'auxiliary')`
will set today's date as the auxiliary date of the current transaction.
You can use also `primary` or `unshift` in place of `auxiliary`.
When you pass "unshift" the old primary date will be set as the auxiliary date and today's date will be set as the new primary date.
To use a different date pass a date measured in seconds since 1st Jan 1970 as the third argument.
* `:call ledger#transaction_state_set(line('.'), '*')`
sets the state of the current transaction to '*'.
You can use this in custom mappings.
* `:call ledger#transaction_state_toggle(line('.'), ' *?!')`
will toggle through the provided transaction states.
You can map this to double-clicking for example:
noremap <silent><buffer> <2-LeftMouse>\
:call ledger#transaction_state_toggle(line('.'), ' *?!')<CR>
* Align commodities at the decimal point. See `help ledger-tips`.
* `:call ledger#entry()`
will replace the text on the current line with a new transaction based on the replaced text.
## Configuration
Include the following let-statements somewhere in your `.vimrc` to modify the behaviour of the ledger filetype.
* Number of columns that will be used to display the foldtext.
Set this when you think that the amount is too far off to the right.
let g:ledger_maxwidth = 80
* String that will be used to fill the space between account name and amount in the foldtext.
Set this to get some kind of lines or visual aid.
let g:ledger_fillstring = ' -'
* If you want the account completion to be sorted by level of detail/depth instead of alphabetical, include the following line:
let g:ledger_detailed_first = 1
* By default vim will fold ledger transactions, leaving surrounding blank lines unfolded.
You can use `g:ledger_fold_blanks` to hide blank lines following a transaction.
let g:ledger_fold_blanks = 0
A value of 0 will disable folding of blank lines, 1 will allow folding of a single blank line between transactions; any larger value will enable folding undconditionally.
Note that only lines containing no trailing spaces are considered for folding.
You can take advantage of this to disable this feature on a case-by-case basis.
## Completion
Omni completion is implemented for transactions descriptions and posting account names.
### Accounts
Account names are matched by the start of every sub-level.
When you insert an account name like this:
Asse<C-X><C-O>
You will get a list of top-level accounts that start like this.
Go ahead and try something like:
As:Ban:Che<C-X><C-O>
When you have an account like this, 'Assets:Bank:Checking' should show up.
When you want to complete on a virtual transaction, it's currently best to keep the cursor in front of the closing bracket.
Of course you can insert the closing bracket after calling the completion, too.
## License
Copyright 20192021 Caleb Maclennan
Copyright 20092017 Johann Klähn
Copyright 2009 Stefan Karrmann
Copyright 2005 Wolfgang Oertl
This program is free software:
you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program.
If not, see <https://www.gnu.org/licenses/>.
[hledger]: https://hledger.org/
[ledgercli]: https://www.ledger-cli.org/
[pta]: https://plaintextaccounting.org/

View File

@ -0,0 +1,820 @@
scriptencoding utf-8
" vim:ts=2:sw=2:sts=2:foldmethod=marker
function! ledger#transaction_state_toggle(lnum, ...) abort
if a:0 == 1
let chars = a:1
else
let chars = ' *'
endif
let trans = s:transaction.from_lnum(a:lnum)
if empty(trans) || has_key(trans, 'expr')
return
endif
let old = has_key(trans, 'state') ? trans['state'] : ' '
let i = stridx(chars, old) + 1
let new = chars[i >= len(chars) ? 0 : i]
call trans.set_state(new)
call setline(trans['head'], trans.format_head())
endf
function! ledger#transaction_state_set(lnum, char) abort
" modifies or sets the state of the transaction at the cursor,
" removing the state altogether if a:char is empty
let trans = s:transaction.from_lnum(a:lnum)
if empty(trans) || has_key(trans, 'expr')
return
endif
call trans.set_state(a:char)
call setline(trans['head'], trans.format_head())
endf
function! ledger#transaction_date_set(lnum, type, ...) abort
let time = a:0 == 1 ? a:1 : localtime()
let trans = s:transaction.from_lnum(a:lnum)
if empty(trans) || has_key(trans, 'expr')
return
endif
let formatted = strftime(g:ledger_date_format, time)
if has_key(trans, 'date') && ! empty(trans['date'])
let date = split(trans['date'], '=')
else
let date = [formatted]
endif
if a:type =~? 'effective\|actual'
echoerr 'actual/effective arguments were replaced by primary/auxiliary'
return
endif
if a:type ==? 'primary'
let date[0] = formatted
elseif a:type ==? 'auxiliary'
if time < 0
" remove auxiliary date
let date = [date[0]]
else
" set auxiliary date
if len(date) >= 2
let date[1] = formatted
else
call add(date, formatted)
endif
endif
elseif a:type ==? 'unshift'
let date = [formatted, date[0]]
endif
let trans['date'] = join(date[0:1], '=')
call setline(trans['head'], trans.format_head())
endf
function! ledger#transaction_post_state_get(lnum) abort
" safe view / position
let view = winsaveview()
call cursor(a:lnum, 0)
let line = getline('.')
if line[0] !~# '[ \t]'
" not a post
let state = ''
else
let m = matchlist(line, '^[ \t]\+\([*?!]\)')
if len(m) > 1
let state = m[1]
else
let state = ' '
endif
endif
call winrestview(view)
return state
endf
function! ledger#transaction_post_state_toggle(lnum, ...) abort
if a:0 == 1
let chars = a:1
else
let chars = ' *'
endif
let old = ledger#transaction_post_state_get(a:lnum)
if old ==# ''
" not a post, probably at the first line of transaction
call ledger#transaction_state_toggle(a:lnum, chars)
return
endif
let i = stridx(chars, old) + 1
let new = chars[i >= len(chars) ? 0 : i]
call ledger#transaction_post_state_set(a:lnum, new)
endf
function! ledger#transaction_post_state_set(lnum, char) abort
let state = ledger#transaction_post_state_get(a:lnum)
if state ==# ''
" not a post, probably at the first line of transaction
call ledger#transaction_state_set(a:lnum, a:char)
return
elseif state == a:char || (state ==# ' ' && a:char ==# '')
return
endif
let line = getline('.')
if a:char =~# '^\s*$'
let newline = substitute(line, '\V' . state . '\m[ \t]', '', '')
elseif state ==# ' '
let m = matchlist(line, '^\([ \t]\+\)\(.*\)')
let newline = m[1] . a:char . ' ' . m[2]
else
let newline = substitute(line, '\V' . state, a:char, '')
endif
call setline(a:lnum, newline)
endf
" == get transactions ==
function! ledger#transaction_from_lnum(lnum) abort
return s:transaction.from_lnum(a:lnum)
endf
function! ledger#transactions(...) abort
if a:0 == 2
let lnum = a:1
let end = a:2
elseif a:0 == 0
let lnum = 1
let end = line('$')
else
throw 'wrong number of arguments for get_transactions()'
return []
endif
" safe view / position
let view = winsaveview()
let fe = &foldenable
set nofoldenable
let transactions = []
call cursor(lnum, 0)
while lnum && lnum < end
let trans = s:transaction.from_lnum(lnum)
if ! empty(trans)
call add(transactions, trans)
call cursor(trans['tail'], 0)
endif
let lnum = search('^[~=[:digit:]]', 'cW')
endw
" restore view / position
let &foldenable = fe
call winrestview(view)
return transactions
endf
" == transaction object implementation ==
let s:transaction = {} "{{{1
function! s:transaction.new() abort dict
return copy(s:transaction)
endf
function! s:transaction.from_lnum(lnum) abort dict "{{{2
let [head, tail] = s:get_transaction_extents(a:lnum)
if ! head
return {}
endif
let trans = copy(s:transaction)
let trans['head'] = head
let trans['tail'] = tail
" split off eventual comments at the end of line
let line = split(getline(head), '\ze\s*\%(\t\| \);', 1)
if len(line) > 1
let trans['appendix'] = join(line[1:], '')
endif
" parse rest of line
" FIXME (minor): will not preserve spacing (see 'join(parts)')
let parts = split(line[0], '\s\+')
if parts[0] ==# '~'
let trans['expr'] = join(parts[1:])
return trans
elseif parts[0] ==# '='
let trans['auto'] = join(parts[1:])
return trans
elseif parts[0] !~# '^\d'
" this case is avoided in s:get_transaction_extents(),
" but we'll check anyway.
return {}
endif
for part in parts
if ! has_key(trans, 'date') && part =~# '^\d'
let trans['date'] = part
elseif ! has_key(trans, 'code') && part =~# '^([^)]*)$'
let trans['code'] = part[1:-2]
elseif ! has_key(trans, 'state') && part =~# '^[[:punct:]]$'
" the first character by itself is assumed to be the state of the transaction.
let trans['state'] = part
else
" everything after date/code or state belongs to the description
break
endif
call remove(parts, 0)
endfor
let trans['description'] = join(parts)
return trans
endf "}}}
function! s:transaction.set_state(char) abort dict "{{{2
if a:char =~# '^\s*$'
if has_key(self, 'state')
call remove(self, 'state')
endif
else
let self['state'] = a:char
endif
endf "}}}
function! s:transaction.parse_body(...) abort dict "{{{2
if a:0 == 2
let head = a:1
let tail = a:2
elseif a:0 == 0
let head = self['head']
let tail = self['tail']
else
throw 'wrong number of arguments for parse_body()'
return []
endif
if ! head || tail <= head
return []
endif
let lnum = head
let tags = {}
let postings = []
while lnum <= tail
let line = split(getline(lnum), '\s*\%(\t\| \);', 1)
if line[0] =~# '^\s\+[^[:blank:];]'
" posting
let [state, rest] = matchlist(line[0], '^\s\+\([*!]\?\)\s*\(.*\)$')[1:2]
if rest =~# '\t\| '
let [account, amount] = matchlist(rest, '^\(.\{-}\)\%(\t\| \)\s*\(.\{-}\)\s*$')[1:2]
else
let amount = ''
let account = matchstr(rest, '^\s*\zs.\{-}\ze\s*$')
endif
call add(postings, {'account': account, 'amount': amount, 'state': state})
end
" where are tags to be stored?
if empty(postings)
" they belong to the transaction
let tag_container = tags
else
" they belong to last posting
if ! has_key(postings[-1], 'tags')
let postings[-1]['tags'] = {}
endif
let tag_container = postings[-1]['tags']
endif
let comment = join(line[1:], ' ;')
if comment =~# '^\s*:'
" tags without values
for t in s:findall(comment, ':\zs[^:[:blank:]]\([^:]*[^:[:blank:]]\)\?\ze:')
let tag_container[t] = ''
endfor
elseif comment =~# '^\s*[^:[:blank:]][^:]\+:'
" tag with value
let key = matchstr(comment, '^\s*\zs[^:]\+\ze:')
if ! empty(key)
let val = matchstr(comment, ':\s*\zs.*\ze\s*$')
let tag_container[key] = val
endif
endif
let lnum += 1
endw
return [tags, postings]
endf "}}}
function! s:transaction.format_head() abort dict "{{{2
if has_key(self, 'expr')
return '~ '.self['expr']
elseif has_key(self, 'auto')
return '= '.self['auto']
endif
let parts = []
if has_key(self, 'date') | call add(parts, self['date']) | endif
if has_key(self, 'state') | call add(parts, self['state']) | endif
if has_key(self, 'code') | call add(parts, '('.self['code'].')') | endif
if has_key(self, 'description') | call add(parts, self['description']) | endif
let line = join(parts)
if has_key(self, 'appendix') | let line .= self['appendix'] | endif
return line
endf "}}}
"}}}
" == helper functions ==
" get a list of declared accounts in the buffer
function! ledger#declared_accounts(...) abort
if a:0 == 2
let lnum = a:1
let lend = a:2
elseif a:0 == 0
let lnum = 1
let lend = line('$')
else
throw 'wrong number of arguments for ledger#declared_accounts()'
return []
endif
" save view / position
let view = winsaveview()
let fe = &foldenable
set nofoldenable
let accounts = []
call cursor(lnum, 0)
while 1
let lnum = search('^account\s', 'cW', lend)
if !lnum || lnum > lend
break
endif
" remove comments at the end and "account" at the front
let line = split(getline(lnum), '\s\+;')[0]
let line = matchlist(line, 'account\s\+\(.\+\)')[1]
if len(line) > 1
call add(accounts, line)
endif
call cursor(lnum+1,0)
endw
" restore view / position
let &foldenable = fe
call winrestview(view)
return accounts
endf
function! s:get_transaction_extents(lnum) abort
if ! (indent(a:lnum) || getline(a:lnum) =~# '^[~=[:digit:]]')
" only do something if lnum is in a transaction
return [0, 0]
endif
" safe view / position
let view = winsaveview()
let fe = &foldenable
set nofoldenable
call cursor(a:lnum, 0)
let head = search('^[~=[:digit:]]', 'bcnW')
let tail = search('^[^;[:blank:]]\S\+', 'nW')
let tail = tail > head ? tail - 1 : line('$')
" restore view / position
let &foldenable = fe
call winrestview(view)
return head ? [head, tail] : [0, 0]
endf
function! ledger#find_in_tree(tree, levels) abort
if empty(a:levels)
return []
endif
let results = []
let currentlvl = a:levels[0]
let nextlvls = a:levels[1:]
let branches = ledger#filter_items(keys(a:tree), currentlvl)
for branch in branches
let exact = empty(nextlvls)
call add(results, [branch, exact])
if ! empty(nextlvls)
for [result, exact] in ledger#find_in_tree(a:tree[branch], nextlvls)
call add(results, [branch.':'.result, exact])
endfor
endif
endfor
return results
endf
function! ledger#filter_items(list, keyword) abort
" return only those items that start with a specified keyword
return filter(copy(a:list), 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''')
endf
function! s:findall(text, rx) abort
" returns all the matches in a string,
" there will be overlapping matches according to :help match()
let matches = []
while 1
let m = matchstr(a:text, a:rx, 0, len(matches)+1)
if empty(m)
break
endif
call add(matches, m)
endw
return matches
endf
" Move the cursor to the specified column, filling the line with spaces if necessary.
" Ensure that at least min_spaces are added, and go to the end of the line if
" the line is already too long
function! s:goto_col(pos, min_spaces) abort
exec 'normal!' '$'
let diff = max([a:min_spaces, a:pos - virtcol('.')])
if diff > 0 | exec 'normal!' diff . 'a ' | endif
endf
" Return character position of decimal separator (multibyte safe)
function! s:decimalpos(expr) abort
let pos = match(a:expr, '\V' . g:ledger_decimal_sep)
if pos > 0
let pos = strchars(a:expr[:pos]) - 1
endif
return pos
endf
" Align the amount expression after an account name at the decimal point.
"
" This function moves the amount expression of a posting so that the decimal
" separator is aligned at the column specified by g:ledger_align_at.
"
" For example, after selecting:
"
" 2015/05/09 Some Payee
" Expenses:Other $120,23 ; Tags here
" Expenses:Something $-4,99
" Expenses:More ($12,34 + $16,32)
"
" :'<,'>call ledger#align_commodity() produces:
"
" 2015/05/09 Some Payee
" Expenses:Other $120,23 ; Tags here
" Expenses:Something $-4,99
" Expenses:More ($12,34 + $16,32)
"
function! ledger#align_commodity() abort
" Extract the part of the line after the account name (excluding spaces):
let l:line = getline('.')
let rhs = matchstr(l:line, '\m^\s\+[^;[:space:]].\{-}\(\t\| \)\s*\zs.*$')
if rhs !=# ''
" Remove everything after the account name (including spaces):
call setline('.', substitute(l:line, '\m^\s\+[^[:space:]].\{-}\zs\(\t\| \).*$', '', ''))
let pos = -1
if g:ledger_align_commodity == 1
let pos = 0
elseif g:ledger_decimal_sep !=# ''
" Find the position of the first decimal separator:
let pos = s:decimalpos(rhs)
endif
if pos < 0
" Find the position after the first digits
let pos = matchend(rhs, '\m\d[^[:space:]]*')
endif
" Go to the column that allows us to align the decimal separator at g:ledger_align_at:
if pos >= 0
call s:goto_col(g:ledger_align_at - pos - 1, 2)
else
call s:goto_col(g:ledger_align_at - strdisplaywidth(rhs) - 2, 2)
endif " Append the part of the line that was previously removed:
exe 'normal! a' . rhs
endif
endf
" Align the commodity on the entire buffer
function! ledger#align_commodity_buffer() abort
" Store the viewport position
let view = winsaveview()
" Call ledger#align_commodity for every line
%call ledger#align_commodity()
" Restore the viewport position
call winrestview(view)
unlet view
endf
" Align the amount under the cursor and append/prepend the default currency.
function! ledger#align_amount_at_cursor() abort
" Select and cut text:
normal! viWd
" Find the position of the decimal separator
let pos = s:decimalpos(@") " Returns zero when the separator is the empty string
if pos <= 0
let pos = len(@")
endif
" Paste text at the correct column and append/prepend default commodity:
if g:ledger_commodity_before
call s:goto_col(g:ledger_align_at - pos - len(g:ledger_default_commodity) - len(g:ledger_commodity_sep) - 1, 2)
exe 'normal! a' . g:ledger_default_commodity . g:ledger_commodity_sep
normal! p
else
call s:goto_col(g:ledger_align_at - pos - 1, 2)
exe 'normal! pa' . g:ledger_commodity_sep . g:ledger_default_commodity
endif
endf
" Report generation {{{1
" Helper functions and variables {{{2
" Position of report windows
let s:winpos_map = {
\ 'T': 'to new', 't': 'abo new', 'B': 'bo new', 'b': 'bel new',
\ 'L': 'to vnew', 'l': 'abo vnew', 'R': 'bo vnew', 'r': 'bel vnew'
\ }
function! s:error_message(msg) abort
redraw " See h:echo-redraw
echohl ErrorMsg
echo "\r"
echomsg a:msg
echohl NONE
endf
function! s:warning_message(msg) abort
redraw " See h:echo-redraw
echohl WarningMsg
echo "\r"
echomsg a:msg
echohl NONE
endf
" Open the quickfix/location window when it is not empty,
" closes it if it is empty.
"
" Optional parameters:
" a:1 Quickfix window title.
" a:2 Message to show when the window is empty.
"
" Returns 0 if the quickfix window is empty, 1 otherwise.
function! s:quickfix_toggle(...) abort
if g:ledger_use_location_list
let l:list = 'l'
let l:open = (len(getloclist(winnr())) > 0)
else
let l:list = 'c'
let l:open = (len(getqflist()) > 0)
endif
if l:open
execute (g:ledger_qf_vertical ? 'vert' : 'botright') l:list.'open' g:ledger_qf_size
" Set local mappings to quit the quickfix window or lose focus.
nnoremap <silent> <buffer> <tab> <c-w><c-w>
execute 'nnoremap <silent> <buffer> q :' l:list.'close<CR>'
" Note that the following settings do not persist (e.g., when you close and re-open the quickfix window).
" See: https://superuser.com/questions/356912/how-do-i-change-the-quickix-title-status-bar-in-vim
if g:ledger_qf_hide_file
setl conceallevel=2
setl concealcursor=nc
syntax match qfFile /^[^|]*/ transparent conceal
endif
if a:0 > 0
let w:quickfix_title = a:1
endif
return 1
endif
execute l:list.'close'
call s:warning_message((a:0 > 1) ? a:2 : 'No results')
return 0
endf
" Populate a quickfix/location window with data. The argument must be a String
" or a List.
function! s:quickfix_populate(data) abort
" Note that cexpr/lexpr always uses the global value of errorformat
let l:efm = &errorformat " Save global errorformat
set errorformat=%EWhile\ parsing\ file\ \"%f\"\\,\ line\ %l:,%ZError:\ %m,%-C%.%#
set errorformat+=%tarning:\ \"%f\"\\,\ line\ %l:\ %m
" Format to parse command-line errors:
set errorformat+=Error:\ %m
" Format to parse reports:
set errorformat+=%f:%l\ %m
set errorformat+=%-G%.%#
execute (g:ledger_use_location_list ? 'l' : 'c').'getexpr' 'a:data'
let &errorformat = l:efm " Restore global errorformat
return
endf
" Build a ledger command to process the given file.
function! s:ledger_cmd(file, args) abort
let l:options = g:ledger_extra_options
if len(g:ledger_date_format) > 0 && !g:ledger_is_hledger
let l:options = join([l:options, '--date-format', g:ledger_date_format,
\ '--input-date-format', g:ledger_date_format])
endif
return join([g:ledger_bin, l:options, '-f', shellescape(expand(a:file)), a:args])
endf
" }}}
function! ledger#autocomplete_and_align() abort
if pumvisible()
return "\<c-n>"
endif
" Align an amount only if there is a digit immediately before the cursor and
" such digit is preceded by at least one space (the latter condition is
" necessary to avoid situations where a date starting at the first column is
" confused with a commodity to be aligned).
if match(getline('.'), '\s.*\d\%'.col('.').'c') > -1
normal! h
call ledger#align_amount_at_cursor()
return "\<c-o>A"
endif
return "\<c-x>\<c-o>"
endf
" Use current line as input to ledger entry and replace with output. If there
" are errors, they are echoed instead.
function! ledger#entry() abort
let l:output = systemlist(s:ledger_cmd(g:ledger_main, join(['entry', getline('.')])))
" Filter out warnings
let l:output = filter(l:output, "v:val !~? '^Warning: '")
" Errors may occur
if v:shell_error
echomsg join(l:output)
return
endif
" Append output so we insert instead of overwrite, then delete line
call append('.', l:output)
normal! "_dd
endfunc
" Run an arbitrary ledger command and show the output in a new buffer. If
" there are errors, no new buffer is opened: the errors are displayed in a
" quickfix window instead.
"
" Parameters:
" file The file to be processed.
" args A string of Ledger command-line arguments.
"
" Returns:
" Ledger's output as a String.
function! ledger#report(file, args) abort
let l:output = systemlist(s:ledger_cmd(a:file, a:args))
if v:shell_error " If there are errors, show them in a quickfix/location list.
call s:quickfix_populate(l:output)
call s:quickfix_toggle('Errors', 'Unable to parse errors')
endif
return l:output
endf
" Open the output of a Ledger's command in a new buffer.
"
" Parameters:
" report A String containing the output of a Ledger's command.
"
" Returns:
" 1 if a new buffer is created; 0 otherwise.
function! ledger#output(report) abort
if empty(a:report)
call s:warning_message('No results')
return 0
endif
" Open a new buffer to show Ledger's output.
execute get(s:winpos_map, g:ledger_winpos, 'bo new')
setlocal buftype=nofile bufhidden=wipe modifiable nobuflisted noswapfile nowrap
call append(0, a:report)
setlocal nomodifiable
" Set local mappings to quit window or lose focus.
nnoremap <silent> <buffer> <tab> <c-w><c-p>
nnoremap <silent> <buffer> q <c-w><c-p>@=winnr('#')<cr><c-w>c
" Add some coloring to the report
syntax match LedgerNumber /-\@1<!\d\+\([,.]\d\+\)*/
syntax match LedgerNegativeNumber /-\d\+\([,.]\d\+\)*/
syntax match LedgerImproperPerc /\d\d\d\+%/
return 1
endf
" Show an arbitrary register report in a quickfix list.
"
" Parameters:
" file The file to be processed
" args A string of Ledger command-line arguments.
function! ledger#register(file, args) abort
let l:cmd = s:ledger_cmd(a:file, join([
\ 'register',
\ "--format='" . g:ledger_qf_register_format . "'",
\ "--prepend-format='%(filename):%(beg_line) '",
\ a:args
\ ]))
call s:quickfix_populate(systemlist(l:cmd))
call s:quickfix_toggle('Register report')
endf
" Reconcile the given account.
" This function accepts a file path as a third optional argument.
" The default is to use the value of g:ledger_main.
"
" Parameters:
" file The file to be processed
" account An account name (String)
" target_amount The target amount (Float)
function! ledger#reconcile(file, account, target_amount) abort
let l:cmd = s:ledger_cmd(a:file, join([
\ 'register',
\ '--uncleared',
\ "--format='" . g:ledger_qf_reconcile_format . "'",
\ "--prepend-format='%(filename):%(beg_line) %(pending ? \"P\" : \"U\") '",
\ shellescape(a:account)
\ ]))
let l:file = expand(a:file) " Needed for #show_balance() later
call s:quickfix_populate(systemlist(l:cmd))
if s:quickfix_toggle('Reconcile ' . a:account, 'Nothing to reconcile')
let g:ledger_target_amount = a:target_amount
" Show updated account balance upon saving, as long as the quickfix window is open
augroup reconcile
autocmd!
execute "autocmd BufWritePost *.ldg,*.ledger call ledger#show_balance('" . l:file . "','" . a:account . "')"
autocmd BufWipeout <buffer> call <sid>finish_reconciling()
augroup END
" Add refresh shortcut
execute "nnoremap <silent> <buffer> <c-l> :<c-u>call ledger#reconcile('"
\ . l:file . "','" . a:account . "'," . string(a:target_amount) . ')<cr>'
call ledger#show_balance(l:file, a:account)
endif
endf
function! s:finish_reconciling() abort
unlet g:ledger_target_amount
augroup reconcile
autocmd!
augroup END
augroup! reconcile
endf
" Show the pending/cleared balance of an account.
" This function has an optional parameter:
"
" a:1 An account name
"
" If no account if given, the account in the current line is used.
function! ledger#show_balance(file, ...) abort
let l:account = a:0 > 0 && !empty(a:1) ? a:1 : matchstr(getline('.'), '\m\( \|\t\)\zs\S.\{-}\ze\( \|\t\|$\)')
if empty(l:account)
call s:error_message('No account found')
return
endif
let l:cmd = s:ledger_cmd(a:file, join([
\ 'cleared',
\ shellescape(l:account),
\ '--empty',
\ '--collapse',
\ "--format='%(scrub(get_at(display_total, 0)))|%(scrub(get_at(display_total, 1)))|%(quantity(scrub(get_at(display_total, 1))))'",
\ (empty(g:ledger_default_commodity) ? '' : '-X ' . shellescape(g:ledger_default_commodity))
\ ]))
let l:output = systemlist(l:cmd)
" Errors may occur, for example, when the account has multiple commodities
" and g:ledger_default_commodity is empty.
if v:shell_error
call s:quickfix_populate(l:output)
call s:quickfix_toggle('Errors', 'Unable to parse errors')
return
endif
let l:amounts = split(l:output[-1], '|')
redraw " Necessary in some cases to overwrite previous messages. See :h echo-redraw
if len(l:amounts) < 3
call s:error_message('Could not determine balance. Did you use a valid account?')
return
endif
echo g:ledger_pending_string
echohl LedgerPending
echon l:amounts[0]
echohl NONE
echon ' ' g:ledger_cleared_string
echohl LedgerCleared
echon l:amounts[1]
echohl NONE
if exists('g:ledger_target_amount')
echon ' ' g:ledger_target_string
echohl LedgerTarget
echon printf('%.2f', (g:ledger_target_amount - str2float(l:amounts[2])))
echohl NONE
endif
endf
" }}}

View File

@ -0,0 +1,32 @@
" Vim Compiler File
" Compiler: ledger
" by Johann Klähn; Use according to the terms of the GPL>=2.
" vim:ts=2:sw=2:sts=2:foldmethod=marker
scriptencoding utf-8
if exists('current_compiler') || !exists('g:ledger_bin')
finish
endif
let current_compiler = g:ledger_bin
if exists(':CompilerSet') != 2
command -nargs=* CompilerSet setlocal <args>
endif
if !exists('g:ledger_main')
let g:ledger_main = '%'
endif
if !g:ledger_is_hledger
" Capture Ledger errors (%-C ignores all lines between "While parsing..." and "Error:..."):
CompilerSet errorformat=%EWhile\ parsing\ file\ \"%f\"\\,\ line\ %l:,%ZError:\ %m,%-C%.%#
" Capture Ledger warnings:
CompilerSet errorformat+=%tarning:\ \"%f\"\\,\ line\ %l:\ %m
" Skip all other lines:
CompilerSet errorformat+=%-G%.%#
exe 'CompilerSet makeprg='.substitute(g:ledger_bin, ' ', '\\ ', 'g').'\ -f\ ' . substitute(shellescape(expand(g:ledger_main)), ' ', '\\ ', 'g') . '\ '.substitute(g:ledger_extra_options, ' ', '\\ ', 'g').'\ source\ ' . shellescape(expand(g:ledger_main))
else
exe 'CompilerSet makeprg=('.substitute(g:ledger_bin, ' ', '\\ ', 'g').'\ -f\ ' . substitute(shellescape(expand(g:ledger_main)), ' ', '\\ ', 'g') . '\ print\ '.substitute(g:ledger_extra_options, ' ', '\\ ', 'g').'\ >\ /dev/null)'
endif

View File

@ -0,0 +1,464 @@
*ledger.txt* Plugin for the ledger filetype.
*ledger* *ledger-plugin*
Contents:
Commands............|ledger-invoking|
Source................|ledger-source|
Usage..................|ledger-usage|
Tips....................|ledger-tips|
Reports..............|ledger-reports|
Settings............|ledger-settings|
Completion........|ledger-completion|
License..............|ledger-license|
==============================================================================
USAGE *ledger-usage*
Copy each file to the corresponding directory in your ~/.vim directory or
install using Pathogen.
You can also use a modeline like this in every ledger file:
vim:filetype=ledger
==============================================================================
TIPS *ledger-tips*
Tips and useful commands
* vim-ledger can do syntax-sensitive folding when you set `foldmethod=syntax`
in the |modeline| of your ledger file. This way transactions can shrink down
to just one line.
* Try account-completion (as explained below). If you use YouCompleteMe, you
should disable it for Ledger files. Put this in your .vimrc:
if exists('g:ycm_filetype_blacklist')
call extend(g:ycm_filetype_blacklist, { 'ledger': 1 })
endif
* You may use `:make` for syntax checking. It may be convenient to define a
mapping for the following command:
:silent make | redraw! | cwindow
It is recommended to set the value of `g:ledger_extra_options` (see below)
as follows:
let g:ledger_extra_options = '--pedantic --explicit --check-payees'
to catch most potential problems in your source file.
* Remap vim paragraph motion to move by transaction.
In vim, the "{" and "}" keystrokes move the cursor up and down by whole
paragraphs. They can be redefined in ledger files to move by transaction
instead. Add these lines to .vimrc:
au FileType ledger noremap { ?^\d<CR>
au FileType ledger noremap } /^\d<CR>
The default definitions already work in ledger files that separate
transactions with blank lines.
* `:call ledger#transaction_date_set(line('.'), "auxiliary")`
will set today's date as the auxiliary date of the current transaction. You
can use also "primary" or "unshift" in place of "auxiliary". When you pass
"unshift" the old primary date will be set as the auxiliary date and today's
date will be set as the new primary date.
To use a different date pass a date measured in seconds since 1st Jan 1970
as the third argument.
* `:call ledger#transaction_state_set(line('.'), '*')`
sets the state of the current transaction to '*'. You can use this in custom
mappings.
* `:call ledger#transaction_state_toggle(line('.'), ' *?!')`
will toggle through the provided transaction states. You can map this to
double-clicking for example:
noremap <silent><buffer> <2-LeftMouse>\
:call ledger#transaction_state_toggle(line('.'), ' *?!')<CR>
* `:call ledger#transaction_post_state_set(line('.'), '*')`
is similar to ledger#transaction_state_set but can set state of individual
post.
* `:call ledger#transaction_post_state_toggle(line('.'), ' *?!')`
is similar to ledger#transaction_state_toggle but can toggle state of
individual post.
* `:LedgerAlign`
moves the amount expression of a posting so that the decimal separator is
aligned at the column specified by g:ledger_align_at. If an amount has no
decimal point, the imaginary decimal point to the right of the least
significant digit will align. The command acts on a range, with the default
being the current line.
The decimal separator can be set using `g:ledger_decimal_sep`. The default
value of `g:ledger_decimal_sep` is `'.'`.
See below for the recommended mappings.
* `:LedgerAlignBuffer`
This command aligns the commodity for each posting in the entire buffer,
similar to the command `:LedgerAlign`. It differs from manually specifying
the entire buffer as the range to `:LedgerAlign` or
`ledger#align_commodity()` by saving and restoring the cursor and window
position.
Due to performance concerns, it is not recommended to call this command
on large buffers.
* `:call ledger#align_amount_at_cursor()`
aligns the amount under the cursor and append/prepend the default currency.
The default currency can be set using `g:ledger_default_commodity`. Whether
the commodity should be inserted before the amount or appended to it can be
configured with the boolean flag `g:ledger_commodity_before` (the default
value is 1). A separator between the commodity and the amount may be set
using `g:ledger_commodity_sep`.
See below for the recommended mappings.
* `:call ledger#autocomplete_and_align()`
when the cursor is on a number or immediately after it, invokes
`ledger#align_amount_at_cursor()` to align it and add the default currency;
otherwise, performs autocompletion. If you define the following mappings in
your `.vimrc` then you may perform both autocompletion and alignment using
the <Tab> key:
au FileType ledger inoremap <silent> <Tab> \
<C-r>=ledger#autocomplete_and_align()<CR>
au FileType ledger vnoremap <silent> <Tab> :LedgerAlign<CR>
Alternatively, you may create a file `.vim/after/ftplugin/ledger.vim`
containing the following definitions:
inoremap <silent> <buffer> <Tab> \
<C-r>=ledger#autocomplete_and_align()<CR>
vnoremap <silent> <buffer> <Tab> :LedgerAlign<CR>
Now, you may type `asset:check<Tab><Space>123.45<Tab>`, and have the
account name autocompleted and `$123.45` properly aligned (assuming your
default commodity is set to `'$'`). Or you may press <Tab> in Visual mode
to align a number of transactions at once.
* `:call ledger#entry()`
enters a new transaction based on the text in the current line.
The text in the current line is replaced by the new transaction.
This is a front end to `ledger entry`.
==============================================================================
REPORTS *ledger-reports*
* `:Ledger`
Executes an arbitrary Ledger command and sends the output to a new buffer.
For example:
:Ledger bal ^assets ^liab
Errors are displayed in a quickfix window. The command offers account and
payee autocompletion (by pressing <Tab>): every name starting with `@` is
autocompleted as a payee; any other name is autocompleted as an account.
In a report buffer or in the quickfix window, you may press <Tab> to switch
back to your source file, and you may press `q` to dismiss the current window.
There are three highlight groups that are used to color the report:
* `LedgerNumber`
This is used to color nonnegative numbers.
* `LedgerNegativeNumber`
This is used to color negative numbers.
* `LedgerImproperPerc`
This is used to color improper percentages.
* `:Balance`
Show the pending and cleared balance of a given account below the status
line. For example:
:Balance checking:savings
The command offers payee and account autocompletion (see `:Ledger`). The
account argument is optional: if no argument is given, the first account
name found in the current line is used.
Two highlight groups can be used to customize the colors of the line:
* `LedgerCleared`
This is used to color the cleared balance.
* `LedgerPending`
This is used to color the pending balance.
* `:Register`
Opens an arbitrary register report in the quickfix window. For example:
:Register groceries -p 'this month'
The command offers account and payee autocompletion (see |:Ledger|). You
may use the standard quickfix commands to jump from an entry in the register
report to the corresponding location in the source file. If you use GUI Vim
or if your terminal has support for the mouse (e.g., iTerm2, or even
Terminal.app in OS X 10.11 or later), you may also double-click on a line
number in the quickfix window to jump to the corresponding posting.
It is strongly recommended that you add mappings for common quickfix
commands like `:cprev` and `:cnext`, or that you use T. Pope's Unimpaired
plugin.
* :`Reconcile`
Reconcile an account. For example:
:Reconcile checking
After you press Enter, you will be asked to enter a target amount (use
Vim's syntax for numbers, not your ledger's format). For example, for a
checking account, the target amount may be the balance of your latest bank
statement. The list of uncleared postings appears in the quickfix window.
The current balance of the account, together with the difference between the
target amount and the cleared balance, is shown at the bottom of the screen.
You may use standard quickfix commands to navigate through the postings. You
may use |ledger#transaction_state_set()| to update a transaction's state.
Every time you save your file, the balance and the difference from the
target amount are updated at the bottom of the screen. The goal, of course,
is to get such difference to zero. You may press `<C-l>` to refresh the
Reconcile buffer. To finish reconciling an account, simply close the
quickfix window.
There is a highlight group to customize the color of the difference from
target:
* `LedgerTarget`
This is used to color the difference between the target amount and the
cleared balance.
==============================================================================
SETTINGS *ledger-settings*
Configuration
Include the following let-statements somewhere in your `.vimrc` to modify the
behaviour of the ledger filetype.
* Path to the `ledger` executable:
let g:ledger_bin = 'ledger'
* Additional default options for the `ledger` executable:
let g:ledger_extra_options = ''
* To use a custom external system command to generate a list of account names
for completion, set the following. If g:ledger_bin is set, this will default
to running that command with arguments to parse the current file using the
accounts subcommand (works with ledger or hledger), otherwise it will parse
the postings in the current file itself.
let g:ledger_accounts_cmd = 'your_command args'
* To use a custom external system command to generate a list of descriptions
for completion, set the following. If g:ledger_bin is set, this will default
to running that command with arguments to parse the current file using the
descriptions subcommand (works with ledger or hledger), otherwise it will
parse the transactions in the current file itself.
let g:ledger_descriptions_cmd = 'your_command args'
* Number of columns that will be used to display the foldtext. Set this when
you think that the amount is too far off to the right.
let g:ledger_maxwidth = 80
* String that will be used to fill the space between account name and amount in
the foldtext. Set this to get some kind of lines or visual aid.
let g:ledger_fillstring = ' -'
* If you want the account completion to be sorted by level of detail/depth
instead of alphabetical, include the following line:
let g:ledger_detailed_first = 1
* By default vim will fold ledger transactions, leaving surrounding blank lines
unfolded. You can use 'g:ledger_fold_blanks' to hide blank lines following a
transaction.
let g:ledger_fold_blanks = 0
A value of 0 will disable folding of blank lines, 1 will allow folding of a
single blank line between transactions; any larger value will enable folding
unconditionally.
Note that only lines containing no trailing spaces are considered for
folding. You can take advantage of this to disable this feature on a
case-by-case basis.
* Decimal separator:
let g:ledger_decimal_sep = '.'
* Specify at which column decimal separators should be aligned:
let g:ledger_align_at = 60
* Default commodity used by `ledger#align_amount_at_cursor()`:
let g:ledger_default_commodity = ''
* Align on the commodity location instead of the amount
let g:ledger_align_commodity = 1
* Flag that tells whether the commodity should be prepended or appended to the
amount:
let g:ledger_commodity_before = 1
* String to be put between the commodity and the amount:
let g:ledger_commodity_sep = ''
* Flag that enable the spelling of the amount:
let g:ledger_commodity_spell = 1
* Format of transaction date:
let g:ledger_date_format = '%Y/%m/%d'
* The file to be used to generate reports:
let g:ledger_main = '%'
The default is to use the current file.
* Position of a report buffer:
let g:ledger_winpos = 'B'
Use `b` for bottom, `t` for top, `l` for left, `r` for right. Use uppercase letters
if you want the window to always occupy the full width or height.
* Format of quickfix register reports (see |:Register|):
let g:ledger_qf_register_format = \
'%(date) %-50(payee) %-30(account) %15(amount) %15(total)\n'
The format is specified using the standard Ledger syntax for --format.
* Format of the reconcile quickfix window (see |:Reconcile|):
let g:ledger_qf_reconcile_format = \
'%(date) %-4(code) %-50(payee) %-30(account) %15(amount)\n'
The format is specified using the standard Ledger syntax for --format.
* Flag that tells whether a location list or a quickfix list should be used:
let g:ledger_use_location_list = 0
The default is to use the quickfix window. Set to 1 to use a location list.
* Position of the quickfix/location list:
let g:ledger_qf_vertical = 0
Set to 1 to open the quickfix window in a vertical split.
* Size of the quickfix window:
let g:ledger_qf_size = 10
This is the number of lines of a horizontal quickfix window, or the number
of columns of a vertical quickfix window.
* Flag to show or hide filenames in the quickfix window:
let g:ledger_qf_hide_file = 1
Filenames in the quickfix window are hidden by default. Set this to 1 is
you want filenames to be visible.
* Text of the output of the |:Balance| command:
let g:ledger_cleared_string = 'Cleared: '
let g:ledger_pending_string = 'Cleared or pending: '
let g:ledger_target_string = 'Difference from target: '
==============================================================================
COMPLETION *ledger-completion*
Omni completion is currently implemented for account names only.
### Accounts
Account names are matched by the start of every sub-level. When you
insert an account name like this:
Asse<C-X><C-O>
You will get a list of top-level accounts that start like this.
Go ahead and try something like:
As:Ban:Che<C-X><C-O>
When you have an account like this, 'Assets:Bank:Checking' should show up.
When you want to complete on a virtual transaction, it's currently best
to keep the cursor in front of the closing bracket. Of course you can
insert the closing bracket after calling the completion, too.
==============================================================================
LICENSE *ledger-license*
https://github.com/ledger/vim-ledger
Copyright 2019 Caleb Maclennan
Copyright 20092017 Johann Klähn
Copyright 2009 Stefan Karrmann
Copyright 2005 Wolfgang Oertl
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>.
vim:ts=8 sw=8 noexpandtab tw=78 ft=help:

View File

@ -0,0 +1,2 @@
" vint: -ProhibitAutocmdWithNoGroup
autocmd BufNewFile,BufRead *.ldg,*.ledger,*.journal setfiletype ledger

View File

@ -0,0 +1,523 @@
" Vim filetype plugin file
" filetype: ledger
" by Johann Klähn; Use according to the terms of the GPL>=2.
" vim:ts=2:sw=2:sts=2:foldmethod=marker
scriptencoding utf-8
if exists('b:did_ftplugin')
finish
endif
let b:did_ftplugin = 1
let b:undo_ftplugin = 'setlocal '.
\ 'foldtext< '.
\ 'include< comments< commentstring< omnifunc< formatprg<'
setl foldtext=LedgerFoldText()
setl include=^!\\?include
setl comments=b:;
setl commentstring=;%s
setl omnifunc=LedgerComplete
if !exists('g:ledger_main')
let g:ledger_main = '%'
endif
if exists('g:ledger_no_bin') && g:ledger_no_bin
unlet! g:ledger_bin
elseif !exists('g:ledger_bin') || empty(g:ledger_bin)
if executable('hledger')
let g:ledger_bin = 'hledger'
elseif executable('ledger')
let g:ledger_bin = 'ledger'
else
unlet! g:ledger_bin
echohl WarningMsg
echomsg 'No ledger command detected, set g:ledger_bin to enable more vim-ledger features.'
echohl None
endif
elseif !executable(g:ledger_bin)
unlet! g:ledger_bin
echohl WarningMsg
echomsg 'Command set in g:ledger_bin is not executable, fix to to enable more vim-ledger features.'
echohl None
endif
if exists('g:ledger_bin') && !exists('g:ledger_is_hledger')
let g:ledger_is_hledger = g:ledger_bin =~# '.*hledger'
endif
if exists('g:ledger_bin')
exe 'setl formatprg='.substitute(g:ledger_bin, ' ', '\\ ', 'g').'\ -f\ -\ print'
endif
if !exists('g:ledger_extra_options')
let g:ledger_extra_options = ''
endif
if !exists('g:ledger_date_format')
let g:ledger_date_format = '%Y/%m/%d'
endif
" You can set a maximal number of columns the fold text (excluding amount)
" will use by overriding g:ledger_maxwidth in your .vimrc.
" When maxwidth is zero, the amount will be displayed at the far right side
" of the screen.
if !exists('g:ledger_maxwidth')
let g:ledger_maxwidth = 0
endif
if !exists('g:ledger_fillstring')
let g:ledger_fillstring = ' '
endif
if !exists('g:ledger_accounts_cmd')
if exists('g:ledger_bin')
let g:ledger_accounts_cmd = g:ledger_bin . ' -f ' . shellescape(expand(g:ledger_main)) . ' accounts'
endif
endif
if !exists('g:ledger_descriptions_cmd')
if exists('g:ledger_bin')
if g:ledger_is_hledger
let g:ledger_descriptions_cmd = g:ledger_bin . ' -f ' . shellescape(expand(g:ledger_main)) . ' descriptions'
else
let g:ledger_descriptions_cmd = g:ledger_bin . ' -f ' . shellescape(expand(g:ledger_main)) . ' payees'
endif
endif
endif
if !exists('g:ledger_decimal_sep')
let g:ledger_decimal_sep = '.'
endif
if !exists('g:ledger_align_at')
let g:ledger_align_at = 60
endif
if !exists('g:ledger_align_commodity')
let g:ledger_align_commodity = 0
endif
if !exists('g:ledger_default_commodity')
let g:ledger_default_commodity = ''
endif
if !exists('g:ledger_commodity_before')
let g:ledger_commodity_before = 1
endif
if !exists('g:ledger_commodity_sep')
let g:ledger_commodity_sep = ''
endif
" If enabled this will list the most detailed matches at the top {{{
" of the completion list.
" For example when you have some accounts like this:
" A:Ba:Bu
" A:Bu:Bu
" and you complete on A:B:B normal behaviour may be the following
" A:B:B
" A:Bu:Bu
" A:Bu
" A:Ba:Bu
" A:Ba
" A
" with this option turned on it will be
" A:B:B
" A:Bu:Bu
" A:Ba:Bu
" A:Bu
" A:Ba
" A
" }}}
if !exists('g:ledger_detailed_first')
let g:ledger_detailed_first = 1
endif
" only display exact matches (no parent accounts etc.)
if !exists('g:ledger_exact_only')
let g:ledger_exact_only = 0
endif
" display original text / account name as completion
if !exists('g:ledger_include_original')
let g:ledger_include_original = 0
endif
" Settings for Ledger reports {{{
if !exists('g:ledger_winpos')
let g:ledger_winpos = 'B' " Window position (see s:winpos_map)
endif
if !exists('g:ledger_use_location_list')
let g:ledger_use_location_list = 0 " Use quickfix list by default
endif
if !exists('g:ledger_cleared_string')
let g:ledger_cleared_string = 'Cleared: '
endif
if !exists('g:ledger_pending_string')
let g:ledger_pending_string = 'Cleared or pending: '
endif
if !exists('g:ledger_target_string')
let g:ledger_target_string = 'Difference from target: '
endif
" }}}
" Settings for the quickfix window {{{
if !exists('g:ledger_qf_register_format')
let g:ledger_qf_register_format =
\ '%(date) %(justify(payee, 50)) '.
\ '%(justify(account, 30)) %(justify(amount, 15, -1, true)) '.
\ '%(justify(total, 15, -1, true))\n'
endif
if !exists('g:ledger_qf_reconcile_format')
let g:ledger_qf_reconcile_format =
\ '%(date) %(justify(code, 4)) '.
\ '%(justify(payee, 50)) %(justify(account, 30)) '.
\ '%(justify(amount, 15, -1, true))\n'
endif
if !exists('g:ledger_qf_size')
let g:ledger_qf_size = 10 " Size of the quickfix window
endif
if !exists('g:ledger_qf_vertical')
let g:ledger_qf_vertical = 0
endif
if !exists('g:ledger_qf_hide_file')
let g:ledger_qf_hide_file = 1
endif
" }}}
if !exists('current_compiler')
compiler ledger
endif
" Highlight groups for Ledger reports {{{
hi link LedgerNumber Number
hi link LedgerNegativeNumber Special
hi link LedgerCleared Constant
hi link LedgerPending Todo
hi link LedgerTarget Statement
hi link LedgerImproperPerc Special
" }}}
let s:rx_amount = '\('.
\ '\%([0-9]\+\)'.
\ '\%([,.][0-9]\+\)*'.
\ '\|'.
\ '[,.][0-9]\+'.
\ '\)'.
\ '\s*\%([[:alpha:]¢$€£]\+\s*\)\?'.
\ '\%(\s*;.*\)\?$'
function! LedgerFoldText() "{{{1
" find amount
let amount = ''
let lnum = v:foldstart + 1
while lnum <= v:foldend
let line = getline(lnum)
" Skip metadata/leading comment
if line !~# '^\%(\s\+;\|\d\)'
" No comment, look for amount...
let groups = matchlist(line, s:rx_amount)
if ! empty(groups)
let amount = groups[1]
break
endif
endif
let lnum += 1
endwhile
" strip whitespace at beginning and end of line
let foldtext = substitute(getline(v:foldstart),
\ '\(^\s\+\|\s\+$\)', '', 'g')
" number of columns foldtext can use
let columns = s:get_columns()
if g:ledger_maxwidth
let columns = min([columns, g:ledger_maxwidth])
endif
let amount = printf(' %s ', amount)
" left cut-off if window is too narrow to display the amount
while columns < strdisplaywidth(amount)
let amount = substitute(amount, '^.', '', '')
endwhile
let columns -= strdisplaywidth(amount)
if columns <= 0
return amount
endif
" right cut-off if there is not sufficient space to display the description
while columns < strdisplaywidth(foldtext)
let foldtext = substitute(foldtext, '.$', '', '')
endwhile
let columns -= strdisplaywidth(foldtext)
if columns <= 0
return foldtext . amount
endif
" fill in the fillstring
if strlen(g:ledger_fillstring)
let fillstring = g:ledger_fillstring
else
let fillstring = ' '
endif
let fillstrlen = strdisplaywidth(fillstring)
let foldtext .= ' '
let columns -= 1
while columns >= fillstrlen
let foldtext .= fillstring
let columns -= fillstrlen
endwhile
while columns < strdisplaywidth(fillstring)
let fillstring = substitute(fillstring, '.$', '', '')
endwhile
let foldtext .= fillstring
return foldtext . amount
endfunction "}}}
function! LedgerComplete(findstart, base) "{{{1
if a:findstart
let lnum = line('.')
let line = getline('.')
let b:compl_context = ''
if line =~# '^\s\+[^[:blank:];]' "{{{2 (account)
" only allow completion when in or at end of account name
if matchend(line, '^\s\+\%(\S \S\|\S\)\+') >= col('.') - 1
" the start of the first non-blank character
" (excluding virtual-transaction and 'cleared' marks)
" is the beginning of the account name
let b:compl_context = 'account'
return matchend(line, '^\s\+[*!]\?\s*[\[(]\?')
endif
elseif line =~# '^\d' "{{{2 (description)
let pre = matchend(line, '^\d\S\+\%(([^)]*)\|[*?!]\|\s\)\+')
if pre < col('.') - 1
let b:compl_context = 'description'
return pre
endif
elseif line =~# '^$' "{{{2 (new line)
let b:compl_context = 'new'
endif "}}}
return -1
else
if ! exists('b:compl_cache')
let b:compl_cache = s:collect_completion_data()
let b:compl_cache['#'] = changenr()
endif
let update_cache = 0
let results = []
if b:compl_context ==# 'account' "{{{2 (account)
let hierarchy = split(a:base, ':')
if a:base =~# ':$'
call add(hierarchy, '')
endif
let results = ledger#find_in_tree(b:compl_cache.accounts, hierarchy)
let exacts = filter(copy(results), 'v:val[1]')
if len(exacts) < 1
" update cache if we have no exact matches
let update_cache = 1
endif
if g:ledger_exact_only
let results = exacts
endif
call map(results, 'v:val[0]')
if g:ledger_detailed_first
let results = reverse(sort(results, 's:sort_accounts_by_depth'))
else
let results = sort(results)
endif
elseif b:compl_context ==# 'description' "{{{2 (description)
let results = ledger#filter_items(b:compl_cache.descriptions, a:base)
if len(results) < 1
let update_cache = 1
endif
elseif b:compl_context ==# 'new' "{{{2 (new line)
return [strftime(g:ledger_date_format)]
endif "}}}
if g:ledger_include_original
call insert(results, a:base)
endif
" no completion (apart from a:base) found. update cache if file has changed
if update_cache && b:compl_cache['#'] != changenr()
unlet b:compl_cache
return LedgerComplete(a:findstart, a:base)
else
unlet! b:compl_context
return results
endif
endif
endf "}}}
" Deprecated functions {{{1
let s:deprecated = {
\ 'LedgerToggleTransactionState': 'ledger#transaction_state_toggle',
\ 'LedgerSetTransactionState': 'ledger#transaction_state_set',
\ 'LedgerSetDate': 'ledger#transaction_date_set'
\ }
for [s:old, s:new] in items(s:deprecated)
let s:fun = "function! {s:old}(...)\nechohl WarningMsg\necho '" . s:old .
\ ' is deprecated. Use '.s:new." instead!'\nechohl None\n" .
\ "call call('" . s:new . "', a:000)\nendf"
exe s:fun
endfor
unlet s:old s:new s:fun
" }}}1
function! s:collect_completion_data() "{{{1
let transactions = ledger#transactions()
let cache = {'descriptions': [], 'tags': {}, 'accounts': {}}
if exists('g:ledger_accounts_cmd')
let accounts = systemlist(g:ledger_accounts_cmd)
else
let accounts = ledger#declared_accounts()
endif
if exists('g:ledger_descriptions_cmd')
let cache.descriptions = systemlist(g:ledger_descriptions_cmd)
endif
for xact in transactions
if !exists('g:ledger_descriptions_cmd')
" collect descriptions
if has_key(xact, 'description') && index(cache.descriptions, xact['description']) < 0
call add(cache.descriptions, xact['description'])
endif
endif
let [t, postings] = xact.parse_body()
let tagdicts = [t]
" collect account names
if !exists('g:ledger_accounts_cmd')
for posting in postings
if has_key(posting, 'tags')
call add(tagdicts, posting.tags)
endif
" remove virtual-transaction-marks
let name = substitute(posting.account, '\%(^\s*[\[(]\?\|[\])]\?\s*$\)', '', 'g')
if index(accounts, name) < 0
call add(accounts, name)
endif
endfor
endif
" collect tags
for tags in tagdicts | for [tag, val] in items(tags)
let values = get(cache.tags, tag, [])
if index(values, val) < 0
call add(values, val)
endif
let cache.tags[tag] = values
endfor | endfor
endfor
for account in accounts
let last = cache.accounts
for part in split(account, ':')
let last[part] = get(last, part, {})
let last = last[part]
endfor
endfor
return cache
endf "}}}
" Helper functions {{{1
" return length of string with fix for multibyte characters
function! s:multibyte_strlen(text) "{{{2
return strlen(substitute(a:text, '.', 'x', 'g'))
endfunction "}}}
" get # of visible/usable columns in current window
function! s:get_columns() " {{{2
" As long as vim doesn't provide a command natively,
" we have to compute the available columns.
" see :help todo.txt -> /Add argument to winwidth()/
let columns = (winwidth(0) == 0 ? 80 : winwidth(0)) - &foldcolumn
if &number
" line('w$') is the line number of the last line
let columns -= max([len(line('w$'))+1, &numberwidth])
endif
" are there any signs/is the sign column displayed?
redir => signs
silent execute 'sign place buffer='.string(bufnr('%'))
redir END
if signs =~# 'id='
let columns -= 2
endif
return columns
endf "}}}
function! s:sort_accounts_by_depth(name1, name2) "{{{2
let depth1 = s:count_expression(a:name1, ':')
let depth2 = s:count_expression(a:name2, ':')
return depth1 == depth2 ? 0 : depth1 > depth2 ? 1 : -1
endf "}}}
function! s:count_expression(text, expression) "{{{2
return len(split(a:text, a:expression, 1))-1
endf "}}}
function! s:autocomplete_account_or_payee(argLead, cmdLine, cursorPos) "{{{2
return (a:argLead =~# '^@') ?
\ map(filter(systemlist(g:ledger_bin . ' -f ' . shellescape(expand(g:ledger_main)) . ' payees'),
\ "v:val =~? '" . strpart(a:argLead, 1) . "' && v:val !~? '^Warning: '"), '"@" . escape(v:val, " ")')
\ :
\ map(filter(systemlist(g:ledger_bin . ' -f ' . shellescape(expand(g:ledger_main)) . ' accounts'),
\ "v:val =~? '" . a:argLead . "' && v:val !~? '^Warning: '"), 'escape(v:val, " ")')
endf "}}}
function! s:reconcile(file, account) "{{{2
" call inputsave()
let l:amount = input('Target amount' . (empty(g:ledger_default_commodity) ? ': ' : ' (' . g:ledger_default_commodity . '): '))
" call inputrestore()
call ledger#reconcile(a:file, a:account, str2float(l:amount))
endf "}}}
" Commands {{{1
command! -buffer -nargs=? -complete=customlist,s:autocomplete_account_or_payee
\ Balance call ledger#show_balance(g:ledger_main, <q-args>)
command! -buffer -nargs=+ -complete=customlist,s:autocomplete_account_or_payee
\ Ledger call ledger#output(ledger#report(g:ledger_main, <q-args>))
command! -buffer -range LedgerAlign <line1>,<line2>call ledger#align_commodity()
command! -buffer LedgerAlignBuffer call ledger#align_commodity_buffer()
command! -buffer -nargs=1 -complete=customlist,s:autocomplete_account_or_payee
\ Reconcile call <sid>reconcile(g:ledger_main, <q-args>)
command! -buffer -complete=customlist,s:autocomplete_account_or_payee -nargs=*
\ Register call ledger#register(g:ledger_main, <q-args>)
" }}}

View File

@ -0,0 +1,48 @@
" Vim filetype indent file
" filetype: ledger
" by Johann Klähn; Use according to the terms of the GPL>=2.
" vim:ts=2:sw=2:sts=2:foldmethod=marker
scriptencoding utf-8
if exists('b:did_indent')
finish
endif
let b:did_indent = 1
setl autoindent
setl indentexpr=GetLedgerIndent()
if exists('*GetLedgerIndent')
finish
endif
function GetLedgerIndent(...)
" You can pass in a line number when calling this function manually.
let lnum = a:0 > 0 ? a:1 : v:lnum
" If this line is empty look at (the indentation of) the last line.
" Note that inside of a transaction no blank lines are allowed.
let line = getline(lnum)
let prev = getline(lnum - 1)
if line =~# '^\s\+\S'
" Lines that already are indented (→postings, sub-directives) keep their indentation.
return &shiftwidth
elseif line =~# '^\s*$'
" Current line is empty, try to guess its type based on the previous line.
if prev =~# '^\([[:digit:]~=]\|\s\+\S\)'
" This is very likely a posting or a sub-directive.
" While lines following the start of a transaction are automatically
" indented you will have to indent the first line following a
" pre-declaration manually. This makes it easier to type long lists of
" 'account' pre-declarations without sub-directives, for example.
return &shiftwidth
else
return 0
endif
else
" Everything else is not indented:
" start of transactions, pre-declarations, apply/end-lines
return 0
endif
endf

View File

@ -0,0 +1,31 @@
Given ledger:
1970-01-01 Person
Expenses $6.00
Cash
Execute (align buffer):
LedgerAlignBuffer
Expect ledger:
1970-01-01 Person
Expenses $6.00
Cash
Execute (align buffer on commodity):
let g:ledger_align_commodity = 1
LedgerAlignBuffer
Expect ledger:
1970-01-01 Person
Expenses $6.00
Cash
Execute (change default alignment):
let g:ledger_align_commodity = 0
let g:ledger_align_at = 40
LedgerAlignBuffer
Expect ledger:
1970-01-01 Person
Expenses $6.00
Cash

View File

@ -0,0 +1,8 @@
Execute:
file spec/ledger.ledger
Ledger accounts
Expect ledger:
Cash
Expenses

View File

@ -0,0 +1,3 @@
1970-01-01 Person
Expenses $6.00
Cash

View File

@ -0,0 +1,78 @@
Given ledger:
2020-03-06 Buy
Expenses $10.00
Cash
Execute (set state):
2
call ledger#transaction_post_state_set(line('.'), '*')
Expect ledger:
2020-03-06 Buy
* Expenses $10.00
Cash
Execute (clear state):
2
call ledger#transaction_post_state_set(line('.'), '*')
call ledger#transaction_post_state_set(line('.'), '')
Expect ledger:
2020-03-06 Buy
Expenses $10.00
Cash
Execute (clear already clear state):
2
call ledger#transaction_post_state_set(line('.'), '')
Expect ledger:
2020-03-06 Buy
Expenses $10.00
Cash
Execute (toggle state):
2
call ledger#transaction_post_state_toggle(line('.'), '!* ')
Expect ledger:
2020-03-06 Buy
! Expenses $10.00
Cash
Execute (toggle state x2):
2
call ledger#transaction_post_state_toggle(line('.'), '!* ')
call ledger#transaction_post_state_toggle(line('.'), '!* ')
Expect ledger:
2020-03-06 Buy
* Expenses $10.00
Cash
Execute (toggle state x3):
2
call ledger#transaction_post_state_toggle(line('.'), '!* ')
call ledger#transaction_post_state_toggle(line('.'), '!* ')
call ledger#transaction_post_state_toggle(line('.'), '!* ')
Expect ledger:
2020-03-06 Buy
Expenses $10.00
Cash
Execute (fallback to posting):
call ledger#transaction_post_state_toggle(line('.'), '!* ')
Expect ledger:
2020-03-06 ! Buy
Expenses $10.00
Cash
Execute (fallback to posting, clear):
call ledger#transaction_post_state_set(line('.'), ' ')
Expect ledger:
2020-03-06 Buy
Expenses $10.00
Cash

View File

@ -0,0 +1,132 @@
" Vim syntax file
" filetype: ledger
" by Johann Klähn; Use according to the terms of the GPL>=2.
" by Stefan Karrmann; Use according to the terms of the GPL>=2.
" by Wolfgang Oertl; Use according to the terms of the GPL>=2.
" vim:ts=2:sw=2:sts=2:foldmethod=marker
scriptencoding utf-8
if exists('b:current_syntax')
finish
endif
if !exists ('b:is_hledger')
if exists('g:ledger_is_hledger')
let b:is_hledger = 1
else
let b:is_hledger = 0
endif
endif
" Force old regex engine (:help two-engines)
let s:oe = '\%#=1'
let s:lb1 = '\@1<='
let s:line_comment_chars = b:is_hledger ? ';*#' : ';|*#%'
let s:fb = get(g:, 'ledger_fold_blanks', 0)
let s:skip = s:fb > 0 ? '\|^\n' : ''
if s:fb == 1
let s:skip .= '\n\@!'
endif
let s:ledgerAmount_contains = ''
if get(g:, 'ledger_commodity_spell', 0) == 0
let s:ledgerAmount_contains .= '@NoSpell'
endif
" for debugging
syntax clear
" DATE[=EDATE] [*|!] [(CODE)] DESC <-- first line of transaction
" ACCOUNT AMOUNT [; NOTE] <-- posting
exe 'syn region ledgerTransaction start=/^[[:digit:]~=]/ '.
\ 'skip=/^\s'. s:skip . '/ end=/^/ fold keepend transparent '.
\ 'contains=ledgerTransactionDate,ledgerTransactionMetadata,ledgerPosting,ledgerTransactionExpression'
syn match ledgerTransactionDate /^\d\S\+/ contained
syn match ledgerTransactionExpression /^[=~]\s\+\zs.*/ contained
syn match ledgerPosting /^\s\+[^[:blank:];].*/
\ contained transparent contains=ledgerAccount,ledgerAmount,ledgerValueExpression,ledgerPostingMetadata
" every space in an account name shall be surrounded by two non-spaces
" every account name ends with a tab, two spaces or the end of the line
exe 'syn match ledgerAccount '.
\ '/'.s:oe.'^\s\+\zs\%(\S'.s:lb1.' \S\|\S\)\+\ze\%( \|\t\|\s*$\)/ contained'
exe 'syn match ledgerAmount '.
\ '/'.s:oe.'\S'.s:lb1.'\%( \|\t\)\s*\zs\%([^();[:space:]]\|\s\+[^();[:space:]]\)\+/ contains='.s:ledgerAmount_contains.' contained'
exe 'syn match ledgerValueExpression '.
\ '/'.s:oe.'\S'.s:lb1.'\%( \|\t\)\s*\zs(\%([^;[:space:]]\|\s\+[^;[:space:]]\)\+)/ contains='.s:ledgerAmount_contains.' contained'
syn region ledgerPreDeclaration start=/^\(account\|payee\|commodity\|tag\)/ skip=/^\s/ end=/^/
\ keepend transparent
\ contains=ledgerPreDeclarationType,ledgerPreDeclarationName,ledgerPreDeclarationDirective
syn match ledgerPreDeclarationType /^\(account\|payee\|commodity\|tag\)/ contained
syn match ledgerPreDeclarationName /^\S\+\s\+\zs.*/ contained
syn match ledgerPreDeclarationDirective /^\s\+\zs\S\+/ contained
syn match ledgerDirective
\ /^\%(alias\|assert\|bucket\|capture\|check\|define\|expr\|fixed\|include\|year\)\s/
syn match ledgerOneCharDirective /^\%(P\|A\|Y\|N\|D\|C\)\s/
syn region ledgerBlockComment start=/^comment/ end=/^end comment/
syn region ledgerBlockTest start=/^test/ end=/^end test/
exe 'syn match ledgerComment /^['.s:line_comment_chars.'].*$/'
" comments at eol must be preceded by at least 2 spaces / 1 tab
if b:is_hledger
syn region ledgerTransactionMetadata start=/;/ end=/^/
\ keepend contained contains=ledgerTags,ledgerValueTag,ledgerTypedTag
else
syn region ledgerTransactionMetadata start=/\%(\s\s\|\t\|^\s\+\);/ end=/^/
\ keepend contained contains=ledgerTags,ledgerValueTag,ledgerTypedTag
endif
syn region ledgerPostingMetadata start=/;/ end=/^/
\ keepend contained contains=ledgerTags,ledgerValueTag,ledgerTypedTag
exe 'syn match ledgerTags '.
\ '/'.s:oe.'\%(\%(;\s*\|^tag\s\+\)\)\@<='.
\ ':[^:[:space:]][^:]*\%(::\?[^:[:space:]][^:]*\)*:\s*$/ '.
\ 'contained contains=ledgerTag'
syn match ledgerTag /:\zs[^:]\+\ze:/ contained
exe 'syn match ledgerValueTag '.
\ '/'.s:oe.'\%(\%(;\|^tag\)[^:]\+\)\@<=[^:]\+:\ze.\+$/ contained'
exe 'syn match ledgerTypedTag '.
\ '/'.s:oe.'\%(\%(;\|^tag\)[^:]\+\)\@<=[^:]\+::\ze.\+$/ contained'
syn region ledgerApply
\ matchgroup=ledgerStartApply start=/^apply\>/
\ matchgroup=ledgerEndApply end=/^end\s\+apply\>/
\ contains=ledgerApplyHead,ledgerApply,ledgerTransaction,ledgerComment
exe 'syn match ledgerApplyHead '.
\ '/'.s:oe.'\%(^apply\s\+\)\@<=\S.*$/ contained'
syntax keyword ledgerTodo FIXME TODO
\ contained containedin=ledgerComment,ledgerTransaction,ledgerTransactionMetadata,ledgerPostingMetadata
highlight default link ledgerComment Comment
highlight default link ledgerBlockComment Comment
highlight default link ledgerBlockTest Comment
highlight default link ledgerTransactionDate Constant
highlight default link ledgerTransactionExpression Statement
highlight default link ledgerTransactionMetadata Tag
highlight default link ledgerPostingMetadata Tag
highlight default link ledgerTypedTag Keyword
highlight default link ledgerValueTag Type
highlight default link ledgerTag Type
highlight default link ledgerStartApply Tag
highlight default link ledgerEndApply Tag
highlight default link ledgerApplyHead Type
highlight default link ledgerAccount Identifier
highlight default link ledgerAmount Number
highlight default link ledgerValueExpression Function
highlight default link ledgerPreDeclarationType Type
highlight default link ledgerPreDeclarationName Identifier
highlight default link ledgerPreDeclarationDirective Type
highlight default link ledgerDirective Type
highlight default link ledgerOneCharDirective Type
highlight default link ledgerTodo Todo
" syncinc is easy: search for the first transaction.
syn sync clear
syn sync match ledgerSync grouphere ledgerTransaction "^[[:digit:]~=]"
let b:current_syntax = b:is_hledger ? 'hledger' : 'ledger'

View File

@ -0,0 +1,2 @@
au BufNewFile,BufRead */luakit/**/*.lua set ft=luakit
au BufNewFile,BufRead */luakit/*.lua set ft=luakit

View File

@ -0,0 +1,69 @@
" Vim filetype plugin
" Language: luakit configuration
" Maintainer: Gregor Uhlenheuer <kongo2002@googlemail.com>
" Last Change: Tue 14 Sep 2010 01:18:20 PM CEST
" Custom configuration:
"
" Set 'g:luakit_prefix' to the path prefix where the system-wide
" luakit configuration files are installed to. The default is set to
" something like '/etc/xdg' or '/usr/share/xdg'.
" If this variable is not defined the path is tried to determine via the
" environment variable $XDG_CONFIG_DIRS
"
" let g:luakit_prefix = '/etc/xdg'
"
" Defined mappings (buffer-local):
"
" <Leader>ld Diff current config file with its system-wide counterpart
if exists('b:did_luakit')
finish
endif
let b:did_luakit = 1
if !exists('g:luakit_prefix')
let g:luakit_prefix = '/etc/xdg'
endif
function! s:GetFile()
let fcomponents = []
if $XDG_CONFIG_DIRS != ''
call add(fcomponents, $XDG_CONFIG_DIRS)
else
call add(fcomponents, g:luakit_prefix)
endif
call add(fcomponents, "luakit")
call add(fcomponents, expand('%:t'))
let config_file = join(fcomponents, '/')
if filereadable(config_file)
return config_file
endif
return ''
endfunction
if !exists('*CompareLuakitFile')
function! CompareLuakitFile()
let file = <SID>GetFile()
if file != ''
if file != expand('%:p')
exe 'vert diffsplit' file
wincmd p
else
echohl WarningMsg
echom 'You cannot compare the file with itself'
echohl None
endif
else
echohl WarningMsg
echom 'Could not find system-wide luakit '''.expand('%:t').''' file'
echom 'Please define ''g:luakit_prefix'''
echohl None
endif
endfunction
endif
com! -buffer LuakitDiff call CompareLuakitFile()
nmap <buffer> <Leader>ld :LuakitDiff<CR>
runtime! ftplugin/lua.vim

View File

@ -0,0 +1,10 @@
" Vim indent file
" Language: luakit configuration
" Maintainer: Gregor Uhlenheuer <kongo2002@googlemail.com>
" Last Change: Fri 27 Aug 2010 09:49:20 PM CEST
if exists('b:did_indent')
finish
endif
runtime! indent/lua.vim

View File

@ -0,0 +1,33 @@
" Vim syntax file
" Language: luakit configuration
" Maintainer: Gregor Uhlenheuer <kongo2002@googlemail.com>
" Last Change: Fri 27 Aug 2010 09:46:46 PM CEST
if exists('b:current_syntax')
finish
endif
runtime! syntax/lua.vim
" Javascript between [=[ & ]=] regions
unlet b:current_syntax
syntax include @JAVASCRIPT syntax/javascript.vim
try | syntax include @JAVASCRIPT after/syntax/javascript.vim | catch | endtry
syntax region jsBLOCK matchgroup=jsBLOCKMATCH start=/\[=\[/ end=/\]=\]/ contains=@JAVASCRIPT
hi link jsBLOCKMATCH SpecialComment
" HTML between [==[ & ]==] regions
unlet b:current_syntax
syntax include @HTML syntax/html.vim
try | syntax include @HTML after/syntax/html.vim | catch | endtry
syntax region htmlBLOCK matchgroup=htmlBLOCKMATCH start=/\[==\[/ end=/\]==\]/ contains=@HTML
hi link htmlBLOCKMATCH SpecialComment
" CSS between [===[ & ]===] regions
unlet b:current_syntax
syntax include @CSS syntax/css.vim
try | syntax include @CSS after/syntax/css.vim | catch | endtry
syntax region cssBLOCK matchgroup=cssBLOCKMATCH start=/\[===\[/ end=/\]===\]/ contains=@CSS
hi link cssBLOCKMATCH SpecialComment
let b:current_syntax = 'luakit'

View File

@ -0,0 +1,38 @@
setl wrap " softwrap the text
setl linebreak " don't break in the middle of the word
setl nolist " list disables linebreak
setl textwidth=72
setl formatprg=par\ -B+.,\\-\\!\\?\\\"\\\'\\*\\<\ -w72qie
setl enc=utf-8
setl nojs
setl nosmartindent
setl spell
setl comments=n:>
setl formatoptions=
setl fo+=r " Insert the current comment leader after hitting <Enter> in Insert mode.
setl fo+=o " Insert the current comment leader after hitting 'o' or 'O' in Normal mode.
setl fo+=q " Allow formatting of comments with "gq".
setl fo+=w " Trailing white space indicates a paragraph continues in the next line.
setl fo+=b " Like 'v', but only auto-wrap if you enter a blank at or before the wrap margin.
setl fo+=j " Where it makes sense, remove a comment leader when joining lines.
match ErrorMsg '\s\s\+$'
syn match quote0 "^>"
syn match quote1 "^> *>"
syn match quote2 "^> *> *>"
syn match quote3 "^> *> *> *>"
syn match quote4 "^> *> *> *> *>"
syn match quote5 "^> *> *> *> *> *>"
syn match quote6 "^> *> *> *> *> *> *>"
syn match quote7 "^> *> *> *> *> *> *> *>"
hi quote0 ctermfg=magenta
hi quote1 ctermfg=cyan
hi quote2 ctermfg=blue
hi quote3 ctermfg=yellow
hi quote4 ctermfg=magenta
hi quote5 ctermfg=cyan
hi quote6 ctermfg=blue
hi quote7 ctermfg=yellow

View File

@ -0,0 +1,35 @@
" These are the mappings for snipMate.vim. Putting it here ensures that it
" will be mapped after other plugins such as supertab.vim.
if !exists('loaded_snips') || exists('s:did_snips_mappings')
finish
endif
let s:did_snips_mappings = 1
ino <silent> <tab> <c-r>=TriggerSnippet()<cr>
snor <silent> <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
ino <silent> <s-tab> <c-r>=BackwardsSnippet()<cr>
snor <silent> <s-tab> <esc>i<right><c-r>=BackwardsSnippet()<cr>
ino <silent> <c-r><tab> <c-r>=ShowAvailableSnips()<cr>
" The default mappings for these are annoying & sometimes break snipMate.
" You can change them back if you want, I've put them here for convenience.
snor <bs> b<bs>
snor <right> <esc>a
snor <left> <esc>bi
snor ' b<bs>'
snor ` b<bs>`
snor % b<bs>%
snor U b<bs>U
snor ^ b<bs>^
snor \ b<bs>\
snor <c-x> b<bs><c-x>
" By default load snippets in snippets_dir
if empty(snippets_dir)
finish
endif
call GetSnippets(snippets_dir, '_') " Get global snippets
au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif
" vim:noet:sw=4:ts=4:ft=vim

View File

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

View File

@ -0,0 +1,286 @@
*snipMate.txt* Plugin for using TextMate-style snippets in Vim.
snipMate *snippet* *snippets* *snipMate*
Last Change: July 13, 2009
|snipMate-description| Description
|snipMate-syntax| Snippet syntax
|snipMate-usage| Usage
|snipMate-settings| Settings
|snipMate-features| Features
|snipMate-disadvantages| Disadvantages to TextMate
|snipMate-contact| Contact
For Vim version 7.0 or later.
This plugin only works if 'compatible' is not set.
{Vi does not have any of these features.}
==============================================================================
DESCRIPTION *snipMate-description*
snipMate.vim implements some of TextMate's snippets features in Vim. A
snippet is a piece of often-typed text that you can insert into your
document using a trigger word followed by a <tab>.
For instance, in a C file using the default installation of snipMate.vim, if
you type "for<tab>" in insert mode, it will expand a typical for loop in C: >
for (i = 0; i < count; i++) {
}
To go to the next item in the loop, simply <tab> over to it; if there is
repeated code, such as the "i" variable in this example, you can simply
start typing once it's highlighted and all the matches specified in the
snippet will be updated. To go in reverse, use <shift-tab>.
==============================================================================
SYNTAX *snippet-syntax*
Snippets can be defined in two ways. They can be in their own file, named
after their trigger in 'snippets/<filetype>/<trigger>.snippet', or they can be
defined together in a 'snippets/<filetype>.snippets' file. Note that dotted
'filetype' syntax is supported -- e.g., you can use >
:set ft=html.eruby
to activate snippets for both HTML and eRuby for the current file.
The syntax for snippets in *.snippets files is the following: >
snippet trigger
expanded text
more expanded text
Note that the first hard tab after the snippet trigger is required, and not
expanded in the actual snippet. The syntax for *.snippet files is the same,
only without the trigger declaration and starting indentation.
Also note that snippets must be defined using hard tabs. They can be expanded
to spaces later if desired (see |snipMate-indenting|).
"#" is used as a line-comment character in *.snippets files; however, they can
only be used outside of a snippet declaration. E.g.: >
# this is a correct comment
snippet trigger
expanded text
snippet another_trigger
# this isn't a comment!
expanded text
<
This should hopefully be obvious with the included syntax highlighting.
*snipMate-${#}*
Tab stops ~
By default, the cursor is placed at the end of a snippet. To specify where the
cursor is to be placed next, use "${#}", where the # is the number of the tab
stop. E.g., to place the cursor first on the id of a <div> tag, and then allow
the user to press <tab> to go to the middle of it:
>
snippet div
<div id="${1}">
${2}
</div>
<
*snipMate-placeholders* *snipMate-${#:}* *snipMate-$#*
Placeholders ~
Placeholder text can be supplied using "${#:text}", where # is the number of
the tab stop. This text then can be copied throughout the snippet using "$#",
given # is the same number as used before. So, to make a C for loop: >
snippet for
for (${2:i}; $2 < ${1:count}; $1++) {
${4}
}
This will cause "count" to first be selected and change if the user starts
typing. When <tab> is pressed, the "i" in ${2}'s position will be selected;
all $2 variables will default to "i" and automatically be updated if the user
starts typing.
NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate.
Variables within variables are also possible. For instance: >
snippet opt
<option value="${1:option}">${2:$1}</option>
Will, as usual, cause "option" to first be selected and update all the $1
variables if the user starts typing. Since one of these variables is inside of
${2}, this text will then be used as a placeholder for the next tab stop,
allowing the user to change it if he wishes.
To copy a value throughout a snippet without supplying default text, simply
use the "${#:}" construct without the text; e.g.: >
snippet foo
${1:}bar$1
< *snipMate-commands*
Interpolated Vim Script ~
Snippets can also contain Vim script commands that are executed (via |eval()|)
when the snippet is inserted. Commands are given inside backticks (`...`); for
TextMates's functionality, use the |system()| function. E.g.: >
snippet date
`system("date +%Y-%m-%d")`
will insert the current date, assuming you are on a Unix system. Note that you
can also (and should) use |strftime()| for this example.
Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()*
Since the current filename is used often in snippets, a default function
has been defined for it in snipMate.vim, appropriately called Filename().
With no arguments, the default filename without an extension is returned;
the first argument specifies what to place before or after the filename,
and the second argument supplies the default text to be used if the file
has not been named. "$1" in the first argument is replaced with the filename;
if you only want the filename to be returned, the first argument can be left
blank. Examples: >
snippet filename
`Filename()`
snippet filename_with_default
`Filename('', 'name')`
snippet filename_foo
`filename('$1_foo')`
The first example returns the filename if it the file has been named, and an
empty string if it hasn't. The second returns the filename if it's been named,
and "name" if it hasn't. The third returns the filename followed by "_foo" if
it has been named, and an empty string if it hasn't.
*multi_snip*
To specify that a snippet can have multiple matches in a *.snippets file, use
this syntax: >
snippet trigger A description of snippet #1
expand this text
snippet trigger A description of snippet #2
expand THIS text!
In this example, when "trigger<tab>" is typed, a numbered menu containing all
of the descriptions of the "trigger" will be shown; when the user presses the
corresponding number, that snippet will then be expanded.
To create a snippet with multiple matches using *.snippet files,
simply place all the snippets in a subdirectory with the trigger name:
'snippets/<filetype>/<trigger>/<name>.snippet'.
==============================================================================
USAGE *snipMate-usage*
*'snippets'* *g:snippets_dir*
Snippets are by default looked for any 'snippets' directory in your
'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or
'$HOME\vimfiles\snippets\' on Windows. To change that location or add another
one, change the g:snippets_dir variable in your |.vimrc| to your preferred
directory, or use the |ExtractSnips()|function. This will be used by the
|globpath()| function, and so accepts the same syntax as it (e.g.,
comma-separated paths).
ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets*
ExtractSnipsFile() extracts the specified *.snippets file for the given
filetype. A .snippets file contains multiple snippet declarations for the
filetype. It is further explained above, in |snippet-syntax|.
ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet*
ExtractSnips() extracts *.snippet files from the specified directory and
defines them as snippets for the given filetype. The directory tree should
look like this: 'snippets/<filetype>/<trigger>.snippet'. If the snippet has
multiple matches, it should look like this:
'snippets/<filetype>/<trigger>/<name>.snippet' (see |multi_snip|).
*ResetSnippets()*
The ResetSnippets() function removes all snippets from memory. This is useful
to put at the top of a snippet setup file for if you would like to |:source|
it multiple times.
*list-snippets* *i_CTRL-R_<Tab>*
If you would like to see what snippets are available, simply type <c-r><tab>
in the current buffer to show a list via |popupmenu-completion|.
==============================================================================
SETTINGS *snipMate-settings* *g:snips_author*
The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set
to your name; it can then be used in snippets to automatically add it. E.g.: >
let g:snips_author = 'Hubert Farnsworth'
snippet name
`g:snips_author`
<
*snipMate-expandtab* *snipMate-indenting*
If you would like your snippets to be expanded using spaces instead of tabs,
just enable 'expandtab' and set 'softtabstop' to your preferred amount of
spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead.
*snipMate-remap*
snipMate does not come with a setting to customize the trigger key, but you
can remap it easily in the two lines it's defined in the 'after' directory
under 'plugin/snipMate.vim'. For instance, to change the trigger key
to CTRL-J, just change this: >
ino <tab> <c-r>=TriggerSnippet()<cr>
snor <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
to this: >
ino <c-j> <c-r>=TriggerSnippet()<cr>
snor <c-j> <esc>i<right><c-r>=TriggerSnippet()<cr>
==============================================================================
FEATURES *snipMate-features*
snipMate.vim has the following features among others:
- The syntax of snippets is very similar to TextMate's, allowing
easy conversion.
- The position of the snippet is kept transparently (i.e. it does not use
markers/placeholders written to the buffer), which allows you to escape
out of an incomplete snippet, something particularly useful in Vim.
- Variables in snippets are updated as-you-type.
- Snippets can have multiple matches.
- Snippets can be out of order. For instance, in a do...while loop, the
condition can be added before the code.
- [New] File-based snippets are supported.
- [New] Triggers after non-word delimiters are expanded, e.g. "foo"
in "bar.foo".
- [New] <shift-tab> can now be used to jump tab stops in reverse order.
==============================================================================
DISADVANTAGES *snipMate-disadvantages*
snipMate.vim currently has the following disadvantages to TextMate's snippets:
- There is no $0; the order of tab stops must be explicitly stated.
- Placeholders within placeholders are not possible. E.g.: >
'<div${1: id="${2:some_id}}">${3}</div>'
<
In TextMate this would first highlight ' id="some_id"', and if
you hit delete it would automatically skip ${2} and go to ${3}
on the next <tab>, but if you didn't delete it it would highlight
"some_id" first. You cannot do this in snipMate.vim.
- Regex cannot be performed on variables, such as "${1/.*/\U&}"
- Placeholders cannot span multiple lines.
- Activating snippets in different scopes of the same file is
not possible.
Perhaps some of these features will be added in a later release.
==============================================================================
CONTACT *snipMate-contact* *snipMate-author*
To contact the author (Michael Sanders), please email:
msanders42+snipmate <at> gmail <dot> com
I greatly appreciate any suggestions or improvements offered for the script.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:

View File

@ -0,0 +1,33 @@
'snippets' snipMate.txt /*'snippets'*
.snippet snipMate.txt /*.snippet*
.snippets snipMate.txt /*.snippets*
ExtractSnips() snipMate.txt /*ExtractSnips()*
ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()*
Filename() snipMate.txt /*Filename()*
ResetSnippets() snipMate.txt /*ResetSnippets()*
g:snippets_dir snipMate.txt /*g:snippets_dir*
g:snips_author snipMate.txt /*g:snips_author*
i_CTRL-R_<Tab> snipMate.txt /*i_CTRL-R_<Tab>*
list-snippets snipMate.txt /*list-snippets*
multi_snip snipMate.txt /*multi_snip*
snipMate snipMate.txt /*snipMate*
snipMate-$# snipMate.txt /*snipMate-$#*
snipMate-${#:} snipMate.txt /*snipMate-${#:}*
snipMate-${#} snipMate.txt /*snipMate-${#}*
snipMate-author snipMate.txt /*snipMate-author*
snipMate-commands snipMate.txt /*snipMate-commands*
snipMate-contact snipMate.txt /*snipMate-contact*
snipMate-description snipMate.txt /*snipMate-description*
snipMate-disadvantages snipMate.txt /*snipMate-disadvantages*
snipMate-expandtab snipMate.txt /*snipMate-expandtab*
snipMate-features snipMate.txt /*snipMate-features*
snipMate-filename snipMate.txt /*snipMate-filename*
snipMate-indenting snipMate.txt /*snipMate-indenting*
snipMate-placeholders snipMate.txt /*snipMate-placeholders*
snipMate-remap snipMate.txt /*snipMate-remap*
snipMate-settings snipMate.txt /*snipMate-settings*
snipMate-usage snipMate.txt /*snipMate-usage*
snipMate.txt snipMate.txt /*snipMate.txt*
snippet snipMate.txt /*snippet*
snippet-syntax snipMate.txt /*snippet-syntax*
snippets snipMate.txt /*snippets*

View File

@ -0,0 +1,10 @@
" Helper function for (x)html snippets
if exists('s:did_snip_helper') || &cp || !exists('loaded_snips')
finish
endif
let s:did_snip_helper = 1
" Automatically closes tag if in xhtml
fun! Close()
return stridx(&ft, 'xhtml') == -1 ? '' : ' /'
endf

View File

@ -0,0 +1,247 @@
" File: snipMate.vim
" Author: Michael Sanders
" Last Updated: July 13, 2009
" Version: 0.83
" Description: snipMate.vim implements some of TextMate's snippets features in
" Vim. A snippet is a piece of often-typed text that you can
" insert into your document using a trigger word followed by a "<tab>".
"
" For more help see snipMate.txt; you can do this by using:
" :helptags ~/.vim/doc
" :h snipMate.txt
if exists('loaded_snips') || &cp || version < 700
finish
endif
let loaded_snips = 1
if !exists('snips_author') | let snips_author = 'Me' | endif
au BufRead,BufNewFile *.snippets\= set ft=snippet
au FileType snippet setl noet fdm=indent
let s:snippets = {} | let s:multi_snips = {}
if !exists('snippets_dir')
let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g')
endif
fun! MakeSnip(scope, trigger, content, ...)
let multisnip = a:0 && a:1 != ''
let var = multisnip ? 's:multi_snips' : 's:snippets'
if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif
if !has_key({var}[a:scope], a:trigger)
let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content
elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]]
else
echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.'
\ .' See :h multi_snip for help on snippets with multiple matches.'
endif
endf
fun! ExtractSnips(dir, ft)
for path in split(globpath(a:dir, '*'), "\n")
if isdirectory(path)
let pathname = fnamemodify(path, ':t')
for snipFile in split(globpath(path, '*.snippet'), "\n")
call s:ProcessFile(snipFile, a:ft, pathname)
endfor
elseif fnamemodify(path, ':e') == 'snippet'
call s:ProcessFile(path, a:ft)
endif
endfor
endf
" Processes a single-snippet file; optionally add the name of the parent
" directory for a snippet with multiple matches.
fun s:ProcessFile(file, ft, ...)
let keyword = fnamemodify(a:file, ':t:r')
if keyword == '' | return | endif
try
let text = join(readfile(a:file), "\n")
catch /E484/
echom "Error in snipMate.vim: couldn't read file: ".a:file
endtry
return a:0 ? MakeSnip(a:ft, a:1, text, keyword)
\ : MakeSnip(a:ft, keyword, text)
endf
fun! ExtractSnipsFile(file, ft)
if !filereadable(a:file) | return | endif
let text = readfile(a:file)
let inSnip = 0
for line in text + ["\n"]
if inSnip && (line[0] == "\t" || line == '')
let content .= strpart(line, 1)."\n"
continue
elseif inSnip
call MakeSnip(a:ft, trigger, content[:-2], name)
let inSnip = 0
endif
if line[:6] == 'snippet'
let inSnip = 1
let trigger = strpart(line, 8)
let name = ''
let space = stridx(trigger, ' ') + 1
if space " Process multi snip
let name = strpart(trigger, space)
let trigger = strpart(trigger, 0, space - 1)
endif
let content = ''
endif
endfor
endf
fun! ResetSnippets()
let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {}
endf
let g:did_ft = {}
fun! GetSnippets(dir, filetypes)
for ft in split(a:filetypes, '\.')
if has_key(g:did_ft, ft) | continue | endif
call s:DefineSnips(a:dir, ft, ft)
if ft == 'objc' || ft == 'cpp' || ft == 'cs'
call s:DefineSnips(a:dir, 'c', ft)
elseif ft == 'xhtml'
call s:DefineSnips(a:dir, 'html', 'xhtml')
endif
let g:did_ft[ft] = 1
endfor
endf
" Define "aliasft" snippets for the filetype "realft".
fun s:DefineSnips(dir, aliasft, realft)
for path in split(globpath(a:dir, a:aliasft.'/')."\n".
\ globpath(a:dir, a:aliasft.'-*/'), "\n")
call ExtractSnips(path, a:realft)
endfor
for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n".
\ globpath(a:dir, a:aliasft.'-*.snippets'), "\n")
call ExtractSnipsFile(path, a:realft)
endfor
endf
fun! TriggerSnippet()
if exists('g:SuperTabMappingForward')
if g:SuperTabMappingForward == "<tab>"
let SuperTabKey = "\<c-n>"
elseif g:SuperTabMappingBackward == "<tab>"
let SuperTabKey = "\<c-p>"
endif
endif
if pumvisible() " Update snippet if completion is used, or deal with supertab
if exists('SuperTabKey')
call feedkeys(SuperTabKey) | return ''
endif
call feedkeys("\<esc>a", 'n') " Close completion menu
call feedkeys("\<tab>") | return ''
endif
if exists('g:snipPos') | return snipMate#jumpTabStop(0) | endif
let word = matchstr(getline('.'), '\S\+\%'.col('.').'c')
for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
let [trigger, snippet] = s:GetSnippet(word, scope)
" If word is a trigger for a snippet, delete the trigger & expand
" the snippet.
if snippet != ''
let col = col('.') - len(trigger)
sil exe 's/\V'.escape(trigger, '/.').'\%#//'
return snipMate#expandSnip(snippet, col)
endif
endfor
if exists('SuperTabKey')
call feedkeys(SuperTabKey)
return ''
endif
return "\<tab>"
endf
fun! BackwardsSnippet()
if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif
if exists('g:SuperTabMappingForward')
if g:SuperTabMappingBackward == "<s-tab>"
let SuperTabKey = "\<c-p>"
elseif g:SuperTabMappingForward == "<s-tab>"
let SuperTabKey = "\<c-n>"
endif
endif
if exists('SuperTabKey')
call feedkeys(SuperTabKey)
return ''
endif
return "\<s-tab>"
endf
" Check if word under cursor is snippet trigger; if it isn't, try checking if
" the text after non-word characters is (e.g. check for "foo" in "bar.foo")
fun s:GetSnippet(word, scope)
let word = a:word | let snippet = ''
while snippet == ''
if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]')
let snippet = s:snippets[a:scope][word]
elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]')
let snippet = s:ChooseSnippet(a:scope, word)
if snippet == '' | break | endif
else
if match(word, '\W') == -1 | break | endif
let word = substitute(word, '.\{-}\W', '', '')
endif
endw
if word == '' && a:word != '.' && stridx(a:word, '.') != -1
let [word, snippet] = s:GetSnippet('.', a:scope)
endif
return [word, snippet]
endf
fun s:ChooseSnippet(scope, trigger)
let snippet = []
let i = 1
for snip in s:multi_snips[a:scope][a:trigger]
let snippet += [i.'. '.snip[0]]
let i += 1
endfor
if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif
let num = inputlist(snippet) - 1
return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1]
endf
fun! ShowAvailableSnips()
let line = getline('.')
let col = col('.')
let word = matchstr(getline('.'), '\S\+\%'.col.'c')
let words = [word]
if stridx(word, '.')
let words += split(word, '\.', 1)
endif
let matchlen = 0
let matches = []
for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : []
if has_key(s:multi_snips, scope)
let triggers += keys(s:multi_snips[scope])
endif
for trigger in triggers
for word in words
if word == ''
let matches += [trigger] " Show all matches if word is empty
elseif trigger =~ '^'.word
let matches += [trigger]
let len = len(word)
if len > matchlen | let matchlen = len | endif
endif
endfor
endfor
endfor
" This is to avoid a bug with Vim when using complete(col - matchlen, matches)
" (Issue#46 on the Google Code snipMate issue tracker).
call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', ''))
call complete(col, matches)
return ''
endf
" vim:noet:sw=4:ts=4:ft=vim

View File

@ -0,0 +1,35 @@
# Global snippets
# (c) holds no legal value ;)
snippet c)
`&enc[:2] == "utf" ? "©" : "(c)"` Copyright `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2}
snippet date
`strftime("%Y-%m-%d")`
snippet mfg
Mit freundlichen Grüßen,
Stefan Hagen
snippet mailf
Sehr geehrte Frau ${1:Name},
${2:Text}
Mit freundlichen Grüßen,
Stefan Hagen
snippet mailh
Sehr geehrter Herr ${1:Name},
${2:Text}
Mit freundlichen Grüßen,
Stefan Hagen
snippet sig
--
Stefan Hagen
T: +49 (0)176 64292517
M: sh@codevoid.de
snippet je
`strftime("%A %d.%m.%d %H:%M")`:
snippet tel
017664292517
snippet worktel
015162345601

View File

@ -0,0 +1,110 @@
# main()
snippet main
int main(int argc, const char *argv[])
{
${1}
return 0;
}
# #include <...>
snippet inc
#include <${1:stdio}.h>${2}
# #include "..."
snippet Inc
#include "${1:`Filename("$1.h")`}"${2}
# #ifndef ... #define ... #endif
snippet Def
#ifndef $1
#define ${1:SYMBOL} ${2:value}
#endif${3}
snippet def
#define
snippet ifdef
#ifdef ${1:FOO}
${2:#define }
#endif
snippet #if
#if ${1:FOO}
${2}
#endif
# Header Include-Guard
# (the randomizer code is taken directly from TextMate; it could probably be
# cleaner, I don't know how to do it in vim script)
snippet once
#ifndef ${1:`toupper(Filename('', 'UNTITLED').'_'.system("/usr/bin/ruby -e 'print (rand * 2821109907455).round.to_s(36)'"))`}
#define $1
${2}
#endif /* end of include guard: $1 */
# If Condition
snippet if
if (${1:/* condition */}) {
${2:/* code */}
}
snippet el
else {
${1}
}
# Tertiary conditional
snippet t
${1:/* condition */} ? ${2:a} : ${3:b}
# Do While Loop
snippet do
do {
${2:/* code */}
} while (${1:/* condition */});
# While Loop
snippet wh
while (${1:/* condition */}) {
${2:/* code */}
}
# For Loop
snippet for
for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) {
${4:/* code */}
}
# Custom For Loop
snippet forr
for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) {
${5:/* code */}
}
# Function
snippet fun
${1:void} ${2:function_name}(${3})
{
${4:/* code */}
}
# Function Declaration
snippet fund
${1:void} ${2:function_name}(${3});${4}
# Typedef
snippet td
typedef ${1:int} ${2:MyCustomType};${3}
# Struct
snippet st
struct ${1:`Filename('$1_t', 'name')`} {
${2:/* data */}
}${3: /* optional variable list */};${4}
# Typedef struct
snippet tds
typedef struct ${2:_$1 }{
${3:/* data */}
} ${1:`Filename('$1_t', 'name')`};
# Typdef enum
snippet tde
typedef enum {
${1:/* data */}
} ${2:foo};
# printf
# unfortunately version this isn't as nice as TextMates's, given the lack of a
# dynamic `...`
snippet pr
printf("${1:%s}\n"${2});${3}
# fprintf (again, this isn't as nice as TextMate's version, but it works)
snippet fpr
fprintf(${1:stderr}, "${2:%s}\n"${3});${4}
snippet .
[${1}]${2}
snippet un
unsigned

View File

@ -0,0 +1,30 @@
# Read File Into Vector
snippet readfile
std::vector<char> v;
if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) {
char buf[1024];
while (size_t len = fread(buf, 1, sizeof(buf), $2))
v.insert(v.end(), buf, buf + len);
fclose($2);
}${3}
# std::map
snippet map
std::map<${1:key}, ${2:value}> map${3};
# std::vector
snippet vector
std::vector<${1:char}> v${2};
# Namespace
snippet ns
namespace ${1:`Filename('', 'my')`} {
${2}
} /* $1 */
# Class
snippet cl
class ${1:`Filename('$1_t', 'name')`} {
public:
$1 (${2:arguments});
virtual ~$1 ();
private:
${3:/* data */}
};

View File

@ -0,0 +1,190 @@
# Some useful Unicode entities
# Non-Breaking Space
snippet nbs
&nbsp;
# ←
snippet left
&#x2190;
# →
snippet right
&#x2192;
# ↑
snippet up
&#x2191;
# ↓
snippet down
&#x2193;
# ↩
snippet return
&#x21A9;
# ⇤
snippet backtab
&#x21E4;
# ⇥
snippet tab
&#x21E5;
# ⇧
snippet shift
&#x21E7;
# ⌃
snippet control
&#x2303;
# ⌅
snippet enter
&#x2305;
# ⌘
snippet command
&#x2318;
# ⌥
snippet option
&#x2325;
# ⌦
snippet delete
&#x2326;
# ⌫
snippet backspace
&#x232B;
# ⎋
snippet escape
&#x238B;
# Generic Doctype
snippet doctype HTML 4.01 Strict
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
"http://www.w3.org/TR/html4/strict.dtd">
snippet doctype HTML 4.01 Transitional
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
"http://www.w3.org/TR/html4/loose.dtd">
snippet doctype HTML 5
<!DOCTYPE HTML>
snippet doctype XHTML 1.0 Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
snippet doctype XHTML 1.0 Strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
snippet doctype XHTML 1.0 Transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
snippet doctype XHTML 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
# HTML Doctype 4.01 Strict
snippet docts
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
"http://www.w3.org/TR/html4/strict.dtd">
# HTML Doctype 4.01 Transitional
snippet doct
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
"http://www.w3.org/TR/html4/loose.dtd">
# HTML Doctype 5
snippet doct5
<!DOCTYPE HTML>
# XHTML Doctype 1.0 Frameset
snippet docxf
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
# XHTML Doctype 1.0 Strict
snippet docxs
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
# XHTML Doctype 1.0 Transitional
snippet docxt
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
# XHTML Doctype 1.1
snippet docx
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
snippet html
<html>
${1}
</html>
snippet xhtml
<html xmlns="http://www.w3.org/1999/xhtml">
${1}
</html>
snippet body
<body>
${1}
</body>
snippet head
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"`Close()`>
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>
${2}
</head>
snippet title
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>${2}
snippet script
<script type="text/javascript" charset="utf-8">
${1}
</script>${2}
snippet scriptsrc
<script src="${1}.js" type="text/javascript" charset="utf-8"></script>${2}
snippet style
<style type="text/css" media="${1:screen}">
${2}
</style>${3}
snippet base
<base href="${1}" target="${2}"`Close()`>
snippet r
<br`Close()[1:]`>
snippet div
<div id="${1:name}">
${2}
</div>
# Embed QT Movie
snippet movie
<object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab">
<param name="src" value="$1"`Close()`>
<param name="controller" value="$4"`Close()`>
<param name="autoplay" value="$5"`Close()`>
<embed src="${1:movie.mov}"
width="${2:320}" height="${3:240}"
controller="${4:true}" autoplay="${5:true}"
scale="tofit" cache="true"
pluginspage="http://www.apple.com/quicktime/download/"
`Close()[1:]`>
</object>${6}
snippet fieldset
<fieldset id="$1">
<legend>${1:name}</legend>
${3}
</fieldset>
snippet form
<form action="${1:`Filename('$1_submit')`}" method="${2:get}" accept-charset="utf-8">
${3}
<p><input type="submit" value="Continue &rarr;"`Close()`></p>
</form>
snippet h1
<h1 id="${1:heading}">${2:$1}</h1>
snippet input
<input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="${3}"`Close()`>${4}
snippet label
<label for="${2:$1}">${1:name}</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="${5}" id="${6:$2}"`Close()`>${7}
snippet link
<link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" charset="utf-8"`Close()`>${4}
snippet mailto
<a href="mailto:${1:joe@example.com}?subject=${2:feedback}">${3:email me}</a>
snippet meta
<meta name="${1:name}" content="${2:content}"`Close()`>${3}
snippet opt
<option value="${1:option}">${2:$1}</option>${3}
snippet optt
<option>${1:option}</option>${2}
snippet select
<select name="${1:some_name}" id="${2:$1}">
<option value="${3:option}">${4:$3}</option>
</select>${5}
snippet table
<table border="${1:0}">
<tr><th>${2:Header}</th></tr>
<tr><th>${3:Data}</th></tr>
</table>${4}
snippet textarea
<textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">${4}</textarea>${5}

View File

@ -0,0 +1,78 @@
snippet main
public static void main (String [] args)
{
${1:/* code */}
}
snippet pu
public
snippet po
protected
snippet pr
private
snippet st
static
snippet fi
final
snippet ab
abstract
snippet re
return
snippet br
break;
snippet de
default:
${1}
snippet ca
catch(${1:Exception} ${2:e}) ${3}
snippet th
throw
snippet sy
synchronized
snippet im
import
snippet j.u
java.util
snippet j.i
java.io.
snippet j.b
java.beans.
snippet j.n
java.net.
snippet j.m
java.math.
snippet if
if (${1}) ${2}
snippet el
else
snippet elif
else if (${1}) ${2}
snippet wh
while (${1}) ${2}
snippet for
for (${1}; ${2}; ${3}) ${4}
snippet fore
for (${1} : ${2}) ${3}
snippet sw
switch (${1}) ${2}
snippet cs
case ${1}:
${2}
${3}
snippet tc
public class ${1:`Filename()`} extends ${2:TestCase}
snippet t
public void test${1:Name}() throws Exception ${2}
snippet cl
class ${1:`Filename("", "untitled")`} ${2}
snippet in
interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3}
snippet m
${1:void} ${2:method}(${3}) ${4:throws }${5}
snippet v
${1:String} ${2:var}${3: = null}${4};${5}
snippet co
static public final ${1:String} ${2:var} = ${3};${4}
snippet cos
static public final String ${1:var} = "${2}";${3}
snippet as
assert ${1:test} : "${2:Failure message}";${3}

View File

@ -0,0 +1,74 @@
# Prototype
snippet proto
${1:class_name}.prototype.${2:method_name} =
function(${3:first_argument}) {
${4:// body...}
};
# Function
snippet fun
function ${1:function_name} (${2:argument}) {
${3:// body...}
}
# Anonymous Function
snippet f
function(${1}) {${2}};
# if
snippet if
if (${1:true}) {${2}};
# if ... else
snippet ife
if (${1:true}) {${2}}
else{${3}};
# tertiary conditional
snippet t
${1:/* condition */} ? ${2:a} : ${3:b}
# switch
snippet switch
switch(${1:expression}) {
case '${3:case}':
${4:// code}
break;
${5}
default:
${2:// code}
}
# case
snippet case
case '${1:case}':
${2:// code}
break;
${3}
# for (...) {...}
snippet for
for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) {
${4:$1[$2]}
};
# for (...) {...} (Improved Native For-Loop)
snippet forr
for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) {
${4:$1[$2]}
};
# while (...) {...}
snippet wh
while (${1:/* condition */}) {
${2:/* code */}
}
# do...while
snippet do
do {
${2:/* code */}
} while (${1:/* condition */});
# Object Method
snippet :f
${1:method_name}: function(${2:attribute}) {
${4}
}${3:,}
# setTimeout function
snippet timeout
setTimeout(function() {${3}}${2}, ${1:10};
# Get Elements
snippet get
getElementsBy${1:TagName}('${2}')${3}
# Get Element
snippet gett
getElementBy${1:Id}('${2}')${3}

View File

@ -0,0 +1,91 @@
# #!/usr/bin/perl
snippet #!
#!/usr/bin/perl
# Hash Pointer
snippet .
=>
# Function
snippet sub
sub ${1:function_name} {
${2:#body ...}
}
# Conditional
snippet if
if (${1}) {
${2:# body...}
}
# Conditional if..else
snippet ife
if (${1}) {
${2:# body...}
} else {
${3:# else...}
}
# Conditional if..elsif..else
snippet ifee
if (${1}) {
${2:# body...}
} elsif (${3}) {
${4:# elsif...}
} else {
${5:# else...}
}
# Conditional One-line
snippet xif
${1:expression} if ${2:condition};${3}
# Unless conditional
snippet unless
unless (${1}) {
${2:# body...}
}
# Unless conditional One-line
snippet xunless
${1:expression} unless ${2:condition};${3}
# Try/Except
snippet eval
eval {
${1:# do something risky...}
};
if ($@) {
${2:# handle failure...}
}
# While Loop
snippet wh
while (${1}) {
${2:# body...}
}
# While Loop One-line
snippet xwh
${1:expression} while ${2:condition};${3}
# For Loop
snippet for
for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) {
${4:# body...}
}
# Foreach Loop
snippet fore
foreach my $${1:x} (@${2:array}) {
${3:# body...}
}
# Foreach Loop One-line
snippet xfore
${1:expression} foreach @${2:array};${3}
# Package
snippet cl
package ${1:ClassName};
use base qw(${2:ParentClass});
sub new {
my $class = shift;
$class = ref $class if ref $class;
my $self = bless {}, $class;
$self;
}
1;${3}
# Read File
snippet slurp
my $${1:var};
{ local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = <FILE>; close FILE }${3}

View File

@ -0,0 +1,216 @@
snippet php
<?php
${1}
?>
snippet ec
echo "${1:string}"${2};
snippet inc
include '${1:file}';${2}
snippet inc1
include_once '${1:file}';${2}
snippet req
require '${1:file}';${2}
snippet req1
require_once '${1:file}';${2}
# $GLOBALS['...']
snippet globals
$GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5}
snippet $_ COOKIE['...']
$_COOKIE['${1:variable}']${2}
snippet $_ ENV['...']
$_ENV['${1:variable}']${2}
snippet $_ FILES['...']
$_FILES['${1:variable}']${2}
snippet $_ Get['...']
$_GET['${1:variable}']${2}
snippet $_ POST['...']
$_POST['${1:variable}']${2}
snippet $_ REQUEST['...']
$_REQUEST['${1:variable}']${2}
snippet $_ SERVER['...']
$_SERVER['${1:variable}']${2}
snippet $_ SESSION['...']
$_SESSION['${1:variable}']${2}
# Start Docblock
snippet /*
/**
* ${1}
**/
# Class - post doc
snippet doc_cp
/**
* ${1:undocumented class}
*
* @package ${2:default}
* @author ${3:`g:snips_author`}
**/${4}
# Class Variable - post doc
snippet doc_vp
/**
* ${1:undocumented class variable}
*
* @var ${2:string}
**/${3}
# Class Variable
snippet doc_v
/**
* ${3:undocumented class variable}
*
* @var ${4:string}
**/
${1:var} $${2};${5}
# Class
snippet doc_c
/**
* ${3:undocumented class}
*
* @packaged ${4:default}
* @author ${5:`g:snips_author`}
**/
${1:}class ${2:}
{${6}
} // END $1class $2
# Constant Definition - post doc
snippet doc_dp
/**
* ${1:undocumented constant}
**/${2}
# Constant Definition
snippet doc_d
/**
* ${3:undocumented constant}
**/
define(${1}, ${2});${4}
# Function - post doc
snippet doc_fp
/**
* ${1:undocumented function}
*
* @return ${2:void}
* @author ${3:`g:snips_author`}
**/${4}
# Function signature
snippet doc_s
/**
* ${4:undocumented function}
*
* @return ${5:void}
* @author ${6:`g:snips_author`}
**/
${1}function ${2}(${3});${7}
# Function
snippet doc_f
/**
* ${4:undocumented function}
*
* @return ${5:void}
* @author ${6:`g:snips_author`}
**/
${1}function ${2}(${3})
{${7}
}
# Header
snippet doc_h
/**
* ${1}
*
* @author ${2:`g:snips_author`}
* @version ${3:$Id$}
* @copyright ${4:$2}, `strftime('%d %B, %Y')`
* @package ${5:default}
**/
/**
* Define DocBlock
*//
# Interface
snippet doc_i
/**
* ${2:undocumented class}
*
* @package ${3:default}
* @author ${4:`g:snips_author`}
**/
interface ${1:}
{${5}
} // END interface $1
# class ...
snippet class
/**
* ${1}
**/
class ${2:ClassName}
{
${3}
function ${4:__construct}(${5:argument})
{
${6:// code...}
}
}
# define(...)
snippet def
define('${1}'${2});${3}
# defined(...)
snippet def?
${1}defined('${2}')${3}
snippet wh
while (${1:/* condition */}) {
${2:// code...}
}
# do ... while
snippet do
do {
${2:// code... }
} while (${1:/* condition */});
snippet if
if (${1:/* condition */}) {
${2:// code...}
}
snippet ife
if (${1:/* condition */}) {
${2:// code...}
} else {
${3:// code...}
}
${4}
snippet else
else {
${1:// code...}
}
snippet elseif
elseif (${1:/* condition */}) {
${2:// code...}
}
# Tertiary conditional
snippet t
$${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5}
snippet switch
switch ($${1:variable}) {
case '${2:value}':
${3:// code...}
break;
${5}
default:
${4:// code...}
break;
}
snippet case
case '${1:value}':
${2:// code...}
break;${3}
snippet for
for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {
${4: // code...}
}
snippet foreach
foreach ($${1:variable} as $${2:key}) {
${3:// code...}
}
snippet fun
${1:public }function ${2:FunctionName}(${3})
{
${4:// code...}
}
# $... = array (...)
snippet array
$${1:arrayName} = array('${2}' => ${3});${4}

View File

@ -0,0 +1,86 @@
snippet #!
#!/usr/bin/python
snippet imp
import ${1:module}
# Module Docstring
snippet docs
'''
File: ${1:`Filename('$1.py', 'foo.py')`}
Author: ${2:`g:snips_author`}
Description: ${3}
'''
snippet wh
while ${1:condition}:
${2:# code...}
snippet for
for ${1:needle} in ${2:haystack}:
${3:# code...}
# New Class
snippet cl
class ${1:ClassName}(${2:object}):
"""${3:docstring for $1}"""
def __init__(self, ${4:arg}):
${5:super($1, self).__init__()}
self.$4 = $4
${6}
# New Function
snippet def
def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
"""${3:docstring for $1}"""
${4:pass}
snippet deff
def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
${3}
# New Method
snippet defs
def ${1:mname}(self, ${2:arg}):
${3:pass}
# New Property
snippet property
def ${1:foo}():
doc = "${2:The $1 property.}"
def fget(self):
${3:return self._$1}
def fset(self, value):
${4:self._$1 = value}
# Lambda
snippet ld
${1:var} = lambda ${2:vars} : ${3:action}
snippet .
self.
snippet try Try/Except
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
snippet try Try/Except/Else
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
else:
${5:pass}
snippet try Try/Except/Finally
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
finally:
${5:pass}
snippet try Try/Except/Else/Finally
try:
${1:pass}
except ${2:Exception}, ${3:e}:
${4:raise $3}
else:
${5:pass}
finally:
${6:pass}
# if __name__ == '__main__':
snippet ifmain
if __name__ == '__main__':
${1:main()}
# __magic__
snippet _
__${1:init}__${2}

View File

@ -0,0 +1,420 @@
# #!/usr/bin/ruby
snippet #!
#!/usr/bin/ruby
# New Block
snippet =b
=begin rdoc
${1}
=end
snippet y
:yields: ${1:arguments}
snippet rb
#!/usr/bin/env ruby -wKU
snippet req
require "${1}"${2}
snippet #
# =>
snippet end
__END__
snippet case
case ${1:object}
when ${2:condition}
${3}
end
snippet when
when ${1:condition}
${2}
snippet def
def ${1:method_name}
${2}
end
snippet deft
def test_${1:case_name}
${2}
end
snippet if
if ${1:condition}
${2}
end
snippet ife
if ${1:condition}
${2}
else
${3}
end
snippet elsif
elsif ${1:condition}
${2}
snippet unless
unless ${1:condition}
${2}
end
snippet while
while ${1:condition}
${2}
end
snippet until
until ${1:condition}
${2}
end
snippet cla class .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`}
${2}
end
snippet cla class .. initialize .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`}
def initialize(${2:args})
${3}
end
end
snippet cla class .. < ParentClass .. initialize .. end
class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass}
def initialize(${3:args})
${4}
end
end
snippet cla ClassName = Struct .. do .. end
${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do
def ${3:method_name}
${4}
end
end
snippet cla class BlankSlate .. initialize .. end
class ${1:BlankSlate}
instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ }
snippet cla class << self .. end
class << ${1:self}
${2}
end
# class .. < DelegateClass .. initialize .. end
snippet cla-
class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass})
def initialize(${3:args})
super(${4:del_obj})
${5}
end
end
snippet mod module .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
${2}
end
snippet mod module .. module_function .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
module_function
${2}
end
snippet mod module .. ClassMethods .. end
module ${1:`substitute(Filename(), '^.', '\u&', '')`}
module ClassMethods
${2}
end
module InstanceMethods
end
def self.included(receiver)
receiver.extend ClassMethods
receiver.send :include, InstanceMethods
end
end
# attr_reader
snippet r
attr_reader :${1:attr_names}
# attr_writer
snippet w
attr_writer :${1:attr_names}
# attr_accessor
snippet rw
attr_accessor :${1:attr_names}
# include Enumerable
snippet Enum
include Enumerable
def each(&block)
${1}
end
# include Comparable
snippet Comp
include Comparable
def <=>(other)
${1}
end
# extend Forwardable
snippet Forw-
extend Forwardable
# def self
snippet defs
def self.${1:class_method_name}
${2}
end
# def method_missing
snippet defmm
def method_missing(meth, *args, &blk)
${1}
end
snippet defd
def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name}
snippet defds
def_delegators :${1:@del_obj}, :${2:del_methods}
snippet am
alias_method :${1:new_name}, :${2:old_name}
snippet app
if __FILE__ == $PROGRAM_NAME
${1}
end
# usage_if()
snippet usai
if ARGV.${1}
abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
end
# usage_unless()
snippet usau
unless ARGV.${1}
abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
end
snippet array
Array.new(${1:10}) { |${2:i}| ${3} }
snippet hash
Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} }
snippet file File.foreach() { |line| .. }
File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} }
snippet file File.read()
File.read(${1:"path/to/file"})${2}
snippet Dir Dir.global() { |file| .. }
Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} }
snippet Dir Dir[".."]
Dir[${1:"glob/**/*.rb"}]${2}
snippet dir
Filename.dirname(__FILE__)
snippet deli
delete_if { |${1:e}| ${2} }
snippet fil
fill(${1:range}) { |${2:i}| ${3} }
# flatten_once()
snippet flao
inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3}
snippet zip
zip(${1:enums}) { |${2:row}| ${3} }
# downto(0) { |n| .. }
snippet dow
downto(${1:0}) { |${2:n}| ${3} }
snippet ste
step(${1:2}) { |${2:n}| ${3} }
snippet tim
times { |${1:n}| ${2} }
snippet upt
upto(${1:1.0/0.0}) { |${2:n}| ${3} }
snippet loo
loop { ${1} }
snippet ea
each { |${1:e}| ${2} }
snippet eab
each_byte { |${1:byte}| ${2} }
snippet eac- each_char { |chr| .. }
each_char { |${1:chr}| ${2} }
snippet eac- each_cons(..) { |group| .. }
each_cons(${1:2}) { |${2:group}| ${3} }
snippet eai
each_index { |${1:i}| ${2} }
snippet eak
each_key { |${1:key}| ${2} }
snippet eal
each_line { |${1:line}| ${2} }
snippet eap
each_pair { |${1:name}, ${2:val}| ${3} }
snippet eas-
each_slice(${1:2}) { |${2:group}| ${3} }
snippet eav
each_value { |${1:val}| ${2} }
snippet eawi
each_with_index { |${1:e}, ${2:i}| ${3} }
snippet reve
reverse_each { |${1:e}| ${2} }
snippet inj
inject(${1:init}) { |${2:mem}, ${3:var}| ${4} }
snippet map
map { |${1:e}| ${2} }
snippet mapwi-
enum_with_index.map { |${1:e}, ${2:i}| ${3} }
snippet sor
sort { |a, b| ${1} }
snippet sorb
sort_by { |${1:e}| ${2} }
snippet ran
sort_by { rand }
snippet all
all? { |${1:e}| ${2} }
snippet any
any? { |${1:e}| ${2} }
snippet cl
classify { |${1:e}| ${2} }
snippet col
collect { |${1:e}| ${2} }
snippet det
detect { |${1:e}| ${2} }
snippet fet
fetch(${1:name}) { |${2:key}| ${3} }
snippet fin
find { |${1:e}| ${2} }
snippet fina
find_all { |${1:e}| ${2} }
snippet gre
grep(${1:/pattern/}) { |${2:match}| ${3} }
snippet sub
${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} }
snippet sca
scan(${1:/pattern/}) { |${2:match}| ${3} }
snippet max
max { |a, b|, ${1} }
snippet min
min { |a, b|, ${1} }
snippet par
partition { |${1:e}|, ${2} }
snippet rej
reject { |${1:e}|, ${2} }
snippet sel
select { |${1:e}|, ${2} }
snippet lam
lambda { |${1:args}| ${2} }
snippet do
do |${1:variable}|
${2}
end
snippet :
:${1:key} => ${2:"value"}${3}
snippet ope
open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} }
# path_from_here()
snippet patfh
File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2}
# unix_filter {}
snippet unif
ARGF.each_line${1} do |${2:line}|
${3}
end
# option_parse {}
snippet optp
require "optparse"
options = {${1:default => "args"}}
ARGV.options do |opts|
opts.banner = "Usage: #{File.basename($PROGRAM_NAME)}
snippet opt
opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String},
"${4:Option description.}") do |${5:opt}|
${6}
end
snippet tc
require "test/unit"
require "${1:library_file_name}"
class Test${2:$1} < Test::Unit::TestCase
def test_${3:case_name}
${4}
end
end
snippet ts
require "test/unit"
require "tc_${1:test_case_file}"
require "tc_${2:test_case_file}"${3}
snippet as
assert(${1:test}, "${2:Failure message.}")${3}
snippet ase
assert_equal(${1:expected}, ${2:actual})${3}
snippet asne
assert_not_equal(${1:unexpected}, ${2:actual})${3}
snippet asid
assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4}
snippet asio
assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3}
snippet asko
assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3}
snippet asn
assert_nil(${1:instance})${2}
snippet asnn
assert_not_nil(${1:instance})${2}
snippet asm
assert_match(/${1:expected_pattern}/, ${2:actual_string})${3}
snippet asnm
assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3}
snippet aso
assert_operator(${1:left}, :${2:operator}, ${3:right})${4}
snippet asr
assert_raise(${1:Exception}) { ${2} }
snippet asnr
assert_nothing_raised(${1:Exception}) { ${2} }
snippet asrt
assert_respond_to(${1:object}, :${2:method})${3}
snippet ass assert_same(..)
assert_same(${1:expected}, ${2:actual})${3}
snippet ass assert_send(..)
assert_send([${1:object}, :${2:message}, ${3:args}])${4}
snippet asns
assert_not_same(${1:unexpected}, ${2:actual})${3}
snippet ast
assert_throws(:${1:expected}) { ${2} }
snippet asnt
assert_nothing_thrown { ${1} }
snippet fl
flunk("${1:Failure message.}")${2}
# Benchmark.bmbm do .. end
snippet bm-
TESTS = ${1:10_000}
Benchmark.bmbm do |results|
${2}
end
snippet rep
results.report("${1:name}:") { TESTS.times { ${2} }}
# Marshal.dump(.., file)
snippet Md
File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4}
# Mashal.load(obj)
snippet Ml
File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3}
# deep_copy(..)
snippet deec
Marshal.load(Marshal.dump(${1:obj_to_copy}))${2}
snippet Pn-
PStore.new(${1:"file_name.pstore"})${2}
snippet tra
transaction(${1:true}) { ${2} }
# xmlread(..)
snippet xml-
REXML::Document.new(File.read(${1:"path/to/file"}))${2}
# xpath(..) { .. }
snippet xpa
elements.each(${1:"//Xpath"}) do |${2:node}|
${3}
end
# class_from_name()
snippet clafn
split("::").inject(Object) { |par, const| par.const_get(const) }
# singleton_class()
snippet sinc
class << self; self end
snippet nam
namespace :${1:`Filename()`} do
${2}
end
snippet tas
desc "${1:Task description\}"
task :${2:task_name => [:dependent, :tasks]} do
${3}
end

View File

@ -0,0 +1,39 @@
# #!/bin/sh
snippet #!
#!/bin/sh
snippet if
if [[ ${1:condition} ]]; then
${2:#statements}
fi
snippet elif
elif [[ ${1:condition} ]]; then
${2:#statements}
snippet for
for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
${3:#statements}
done
snippet wh
while [[ ${1:condition} ]]; do
${2:#statements}
done
snippet until
until [[ ${1:condition} ]]; do
${2:#statements}
done
snippet case
case ${1:word} in
${2:pattern})
${3};;
esac
snippet getopt
while getopts ao: name
do
case $name in
a) flag=1 ;;
o) oarg=$OPTARG ;;
?) echo "Usage: ..."; exit 2 ;;
esac
done
shift $(($OPTIND - 1))
echo "Non-option arguments: " "$@"

View File

@ -0,0 +1,7 @@
# snippets for making snippets :)
snippet snip
snippet ${1:trigger}
${2}
snippet msnip
snippet ${1:trigger} ${2:description}
${3}

View File

@ -0,0 +1,92 @@
# #!/usr/bin/tclsh
snippet #!
#!/usr/bin/tclsh
# Process
snippet pro
proc ${1:function_name} {${2:args}} {
${3:#body ...}
}
#xif
snippet xif
${1:expr}? ${2:true} : ${3:false}
# Conditional
snippet if
if {${1}} {
${2:# body...}
}
# Conditional if..else
snippet ife
if {${1}} {
${2:# body...}
} else {
${3:# else...}
}
# Conditional if..elsif..else
snippet ifee
if {${1}} {
${2:# body...}
} elseif {${3}} {
${4:# elsif...}
} else {
${5:# else...}
}
# If catch then
snippet ifc
if { [catch {${1:#do something...}} ${2:err}] } {
${3:# handle failure...}
}
# Catch
snippet catch
catch {${1}} ${2:err} ${3:options}
# While Loop
snippet wh
while {${1}} {
${2:# body...}
}
# For Loop
snippet for
for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} {
${4:# body...}
}
# Foreach Loop
snippet fore
foreach ${1:x} {${2:#list}} {
${3:# body...}
}
# after ms script...
snippet af
after ${1:ms} ${2:#do something}
# after cancel id
snippet afc
after cancel ${1:id or script}
# after idle
snippet afi
after idle ${1:script}
# after info id
snippet afin
after info ${1:id}
# Expr
snippet exp
expr {${1:#expression here}}
# Switch
snippet sw
switch ${1:var} {
${3:pattern 1} {
${4:#do something}
}
default {
${2:#do something}
}
}
# Case
snippet ca
${1:pattern} {
${2:#do something}
}${3}
# Namespace eval
snippet ns
namespace eval ${1:path} {${2:#script...}}
# Namespace current
snippet nsc
namespace current

View File

@ -0,0 +1,115 @@
# \begin{}...\end{}
snippet begin
\begin{${1:env}}
${2}
\end{$1}
# Tabular
snippet tab
\begin{${1:tabular}}{${2:c}}
${3}
\end{$1}
# Align(ed)
snippet ali
\begin{align${1:ed}}
${2}
\end{align$1}
# Gather(ed)
snippet gat
\begin{gather${1:ed}}
${2}
\end{gather$1}
# Equation
snippet eq
\begin{equation}
${1}
\end{equation}
# Unnumbered Equation
snippet \
\\[
${1}
\\]
# Enumerate
snippet enum
\begin{enumerate}
\item ${1}
\end{enumerate}
# Itemize
snippet item
\begin{itemize}
\item ${1}
\end{itemize}
# Description
snippet desc
\begin{description}
\item[${1}] ${2}
\end{description}
# Matrix
snippet mat
\begin{${1:p/b/v/V/B/small}matrix}
${2}
\end{$1matrix}
# Cases
snippet cas
\begin{cases}
${1:equation}, &\text{ if }${2:case}\\
${3}
\end{cases}
# Split
snippet spl
\begin{split}
${1}
\end{split}
# Part
snippet part
\part{${1:part name}} % (fold)
\label{prt:${2:$1}}
${3}
% part $2 (end)
# Chapter
snippet cha
\chapter{${1:chapter name}} % (fold)
\label{cha:${2:$1}}
${3}
% chapter $2 (end)
# Section
snippet sec
\section{${1:section name}} % (fold)
\label{sec:${2:$1}}
${3}
% section $2 (end)
# Sub Section
snippet sub
\subsection{${1:subsection name}} % (fold)
\label{sub:${2:$1}}
${3}
% subsection $2 (end)
# Sub Sub Section
snippet subs
\subsubsection{${1:subsubsection name}} % (fold)
\label{ssub:${2:$1}}
${3}
% subsubsection $2 (end)
# Paragraph
snippet par
\paragraph{${1:paragraph name}} % (fold)
\label{par:${2:$1}}
${3}
% paragraph $2 (end)
# Sub Paragraph
snippet subp
\subparagraph{${1:subparagraph name}} % (fold)
\label{subp:${2:$1}}
${3}
% subparagraph $2 (end)
snippet itd
\item[${1:description}] ${2:item}
snippet figure
${1:Figure}~\ref{${2:fig:}}${3}
snippet table
${1:Table}~\ref{${2:tab:}}${3}
snippet listing
${1:Listing}~\ref{${2:list}}${3}
snippet section
${1:Section}~\ref{${2:sec:}}${3}
snippet page
${1:page}~\pageref{${2}}${3}

View File

@ -0,0 +1,32 @@
snippet header
" File: ${1:`expand('%:t')`}
" Author: ${2:`g:snips_author`}
" Description: ${3}
${4:" Last Modified: `strftime("%B %d, %Y")`}
snippet guard
if exists('${1:did_`Filename()`}') || &cp${2: || version < 700}
finish
endif
let $1 = 1${3}
snippet f
fun ${1:function_name}(${2})
${3:" code}
endf
snippet for
for ${1:needle} in ${2:haystack}
${3:" code}
endfor
snippet wh
while ${1:condition}
${2:" code}
endw
snippet if
if ${1:condition}
${2:" code}
endif
snippet ife
if ${1:condition}
${2}
else
${3}
endif

View File

@ -0,0 +1,19 @@
" Syntax highlighting for snippet files (used for snipMate.vim)
" Hopefully this should make snippets a bit nicer to write!
syn match snipComment '^#.*'
syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand
syn match tabStop '\$\d\+'
syn match snipCommand '`.\{-}`'
syn match snippet '^snippet.*' transparent contains=multiSnipText,snipKeyword
syn match multiSnipText '\S\+ \zs.*' contained
syn match snipKeyword '^snippet'me=s+8 contained
syn match snipError "^[^#s\t].*$"
hi link snipComment Comment
hi link multiSnipText String
hi link snipKeyword Keyword
hi link snipComment Comment
hi link placeHolder Special
hi link tabStop Special
hi link snipCommand String
hi link snipError Error

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
function! tagbar#debug#start_debug(...) abort
let filename = a:0 > 0 ? a:1 : ''
if empty(filename)
let s:debug_file = 'tagbardebug.log'
else
let s:debug_file = filename
endif
" Clear log file and start it with version info
exe 'redir! > ' . s:debug_file
silent version
redir END
" Check whether the log file could be created
if !filewritable(s:debug_file)
echomsg 'Tagbar: Unable to create log file ' . s:debug_file
let s:debug_file = ''
return
endif
let s:debug_enabled = 1
endfunction
function! tagbar#debug#stop_debug() abort
let s:debug_enabled = 0
let s:debug_file = ''
endfunction
function! tagbar#debug#log(msg) abort
if s:debug_enabled
execute 'redir >> ' . s:debug_file
silent echon s:gettime() . ': ' . a:msg . "\n"
redir END
endif
endfunction
function! tagbar#debug#log_ctags_output(output) abort
if s:debug_enabled
exe 'redir! > ' . s:debug_file . '.ctags_out'
silent echon a:output
redir END
endif
endfunction
function! tagbar#debug#enabled() abort
return s:debug_enabled
endfunction
if has('reltime')
function! s:gettime() abort
let time = split(reltimestr(reltime()), '\.')
return strftime('%Y-%m-%d %H:%M:%S.', time[0]) . time[1]
endfunction
else
function! s:gettime() abort
return strftime('%Y-%m-%d %H:%M:%S')
endfunction
endif
let s:debug_enabled = 0
let s:debug_file = ''

View File

@ -0,0 +1,237 @@
let s:visibility_symbols = {
\ 'public' : '+',
\ 'protected' : '#',
\ 'private' : '-'
\ }
function! tagbar#prototypes#basetag#new(name) abort
let newobj = {}
let newobj.name = a:name
let newobj.fields = {}
let newobj.fields.line = 0
let newobj.fields.column = 0
let newobj.prototype = ''
let newobj.path = ''
let newobj.fullpath = a:name
let newobj.depth = 0
let newobj.parent = {}
let newobj.tline = -1
let newobj.fileinfo = {}
let newobj.typeinfo = {}
let newobj._childlist = []
let newobj._childdict = {}
let newobj.isNormalTag = function(s:add_snr('s:isNormalTag'))
let newobj.isPseudoTag = function(s:add_snr('s:isPseudoTag'))
let newobj.isSplitTag = function(s:add_snr('s:isSplitTag'))
let newobj.isKindheader = function(s:add_snr('s:isKindheader'))
let newobj.getPrototype = function(s:add_snr('s:getPrototype'))
let newobj._getPrefix = function(s:add_snr('s:_getPrefix'))
let newobj.initFoldState = function(s:add_snr('s:initFoldState'))
let newobj.getClosedParentTline = function(s:add_snr('s:getClosedParentTline'))
let newobj.isFoldable = function(s:add_snr('s:isFoldable'))
let newobj.isFolded = function(s:add_snr('s:isFolded'))
let newobj.openFold = function(s:add_snr('s:openFold'))
let newobj.closeFold = function(s:add_snr('s:closeFold'))
let newobj.setFolded = function(s:add_snr('s:setFolded'))
let newobj.openParents = function(s:add_snr('s:openParents'))
let newobj.addChild = function(s:add_snr('s:addChild'))
let newobj.getChildren = function(s:add_snr('s:getChildren'))
let newobj.getChildrenByName = function(s:add_snr('s:getChildrenByName'))
let newobj.removeChild = function(s:add_snr('s:removeChild'))
return newobj
endfunction
" s:isNormalTag() {{{1
function! s:isNormalTag() abort dict
return 0
endfunction
" s:isPseudoTag() {{{1
function! s:isPseudoTag() abort dict
return 0
endfunction
" s:isSplitTag {{{1
function! s:isSplitTag() abort dict
return 0
endfunction
" s:isKindheader() {{{1
function! s:isKindheader() abort dict
return 0
endfunction
" s:getPrototype() {{{1
function! s:getPrototype(short) abort dict
return self.prototype
endfunction
" s:_getPrefix() {{{1
function! s:_getPrefix() abort dict
let fileinfo = self.fileinfo
if !empty(self._childlist)
if fileinfo.tagfolds[self.fields.kind][self.fullpath]
let prefix = g:tagbar#icon_closed
else
let prefix = g:tagbar#icon_open
endif
else
let prefix = ' '
endif
" Visibility is called 'access' in the ctags output
if g:tagbar_show_visibility
if has_key(self.fields, 'access')
let prefix .= get(s:visibility_symbols, self.fields.access, ' ')
elseif has_key(self.fields, 'file')
let prefix .= s:visibility_symbols.private
else
let prefix .= ' '
endif
endif
return prefix
endfunction
" s:initFoldState() {{{1
function! s:initFoldState(known_files) abort dict
let fileinfo = self.fileinfo
if a:known_files.has(fileinfo.fpath) &&
\ has_key(fileinfo, '_tagfolds_old') &&
\ has_key(fileinfo._tagfolds_old[self.fields.kind], self.fullpath)
" The file has been updated and the tag was there before, so copy its
" old fold state
let fileinfo.tagfolds[self.fields.kind][self.fullpath] =
\ fileinfo._tagfolds_old[self.fields.kind][self.fullpath]
elseif self.depth >= fileinfo.foldlevel
let fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1
else
let fileinfo.tagfolds[self.fields.kind][self.fullpath] =
\ fileinfo.kindfolds[self.fields.kind]
endif
endfunction
" s:getClosedParentTline() {{{1
function! s:getClosedParentTline() abort dict
let tagline = self.tline
" Find the first closed parent, starting from the top of the hierarchy.
let parents = []
let curparent = self.parent
while !empty(curparent)
call add(parents, curparent)
let curparent = curparent.parent
endwhile
for parent in reverse(parents)
if parent.isFolded()
let tagline = parent.tline
break
endif
endfor
return tagline
endfunction
" s:isFoldable() {{{1
function! s:isFoldable() abort dict
return !empty(self._childlist)
endfunction
" s:isFolded() {{{1
function! s:isFolded() abort dict
return self.fileinfo.tagfolds[self.fields.kind][self.fullpath]
endfunction
" s:openFold() {{{1
function! s:openFold() abort dict
if self.isFoldable()
let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 0
endif
endfunction
" s:closeFold() {{{1
function! s:closeFold() abort dict
let newline = line('.')
if !empty(self.parent) && self.parent.isKindheader()
" Tag is child of generic 'kind'
call self.parent.closeFold()
let newline = self.parent.tline
elseif self.isFoldable() && !self.isFolded()
" Tag is parent of a scope and is not folded
let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = 1
let newline = self.tline
elseif !empty(self.parent)
" Tag is normal child, so close parent
let parent = self.parent
let self.fileinfo.tagfolds[parent.fields.kind][parent.fullpath] = 1
let newline = parent.tline
endif
return newline
endfunction
" s:setFolded() {{{1
function! s:setFolded(folded) abort dict
let self.fileinfo.tagfolds[self.fields.kind][self.fullpath] = a:folded
endfunction
" s:openParents() {{{1
function! s:openParents() abort dict
let parent = self.parent
while !empty(parent)
call parent.openFold()
let parent = parent.parent
endwhile
endfunction
" s:addChild() {{{1
function! s:addChild(tag) abort dict
call add(self._childlist, a:tag)
if has_key(self._childdict, a:tag.name)
call add(self._childdict[a:tag.name], a:tag)
else
let self._childdict[a:tag.name] = [a:tag]
endif
endfunction
" s:getChildren() {{{1
function! s:getChildren() dict abort
return self._childlist
endfunction
" s:getChildrenByName() {{{1
function! s:getChildrenByName(tagname) dict abort
return get(self._childdict, a:tagname, [])
endfunction
" s:removeChild() {{{1
function! s:removeChild(tag) dict abort
let idx = index(self._childlist, a:tag)
if idx >= 0
call remove(self._childlist, idx)
endif
let namelist = get(self._childdict, a:tag.name, [])
let idx = index(namelist, a:tag)
if idx >= 0
call remove(namelist, idx)
endif
endfunction
" s:add_snr() {{{1
function! s:add_snr(funcname) abort
if !exists('s:snr')
let s:snr = matchstr(expand('<sfile>'), '<SNR>\d\+_\zeget_snr$')
endif
return s:snr . a:funcname
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,146 @@
function! tagbar#prototypes#fileinfo#new(fname, ftype, typeinfo) abort
let newobj = {}
" The complete file path
let newobj.fpath = a:fname
let newobj.bufnr = bufnr(a:fname)
" File modification time
let newobj.mtime = getftime(a:fname)
" The vim file type
let newobj.ftype = a:ftype
" List of the tags that are present in the file, sorted according to the
" value of 'g:tagbar_sort'
let newobj._taglist = []
let newobj._tagdict = {}
" Dictionary of the tags, indexed by line number in the file
let newobj.fline = {}
" Dictionary of the tags, indexed by line number in the tagbar
let newobj.tline = {}
" Dictionary of the folding state of 'kind's, indexed by short name
let newobj.kindfolds = {}
let newobj.typeinfo = a:typeinfo
" copy the default fold state from the type info
for kind in a:typeinfo.kinds
let newobj.kindfolds[kind.short] =
\ g:tagbar_foldlevel == 0 ? 1 : kind.fold
endfor
" Dictionary of dictionaries of the folding state of individual tags,
" indexed by kind and full path
let newobj.tagfolds = {}
for kind in a:typeinfo.kinds
let newobj.tagfolds[kind.short] = {}
endfor
" The current foldlevel of the file
let newobj.foldlevel = g:tagbar_foldlevel
let newobj.addTag = function(s:add_snr('s:addTag'))
let newobj.getTags = function(s:add_snr('s:getTags'))
let newobj.getTagsByName = function(s:add_snr('s:getTagsByName'))
let newobj.removeTag = function(s:add_snr('s:removeTag'))
let newobj.reset = function(s:add_snr('s:reset'))
let newobj.clearOldFolds = function(s:add_snr('s:clearOldFolds'))
let newobj.sortTags = function(s:add_snr('s:sortTags'))
let newobj.openKindFold = function(s:add_snr('s:openKindFold'))
let newobj.closeKindFold = function(s:add_snr('s:closeKindFold'))
return newobj
endfunction
" s:addTag() {{{1
function! s:addTag(tag) abort dict
call add(self._taglist, a:tag)
if has_key(self._tagdict, a:tag.name)
call add(self._tagdict[a:tag.name], a:tag)
else
let self._tagdict[a:tag.name] = [a:tag]
endif
endfunction
" s:getTags() {{{1
function! s:getTags() dict abort
return self._taglist
endfunction
" s:getTagsByName() {{{1
function! s:getTagsByName(tagname) dict abort
return get(self._tagdict, a:tagname, [])
endfunction
" s:removeTag() {{{1
function! s:removeTag(tag) dict abort
let idx = index(self._taglist, a:tag)
if idx >= 0
call remove(self._taglist, idx)
endif
let namelist = get(self._tagdict, a:tag.name, [])
let idx = index(namelist, a:tag)
if idx >= 0
call remove(namelist, idx)
endif
endfunction
" s:reset() {{{1
" Reset stuff that gets regenerated while processing a file and save the old
" tag folds
function! s:reset() abort dict
let self.mtime = getftime(self.fpath)
let self._taglist = []
let self._tagdict = {}
let self.fline = {}
let self.tline = {}
let self._tagfolds_old = self.tagfolds
let self.tagfolds = {}
for kind in self.typeinfo.kinds
let self.tagfolds[kind.short] = {}
endfor
endfunction
" s:clearOldFolds() {{{1
function! s:clearOldFolds() abort dict
if exists('self._tagfolds_old')
unlet self._tagfolds_old
endif
endfunction
" s:sortTags() {{{1
function! s:sortTags(compare_typeinfo) abort dict
if get(a:compare_typeinfo, 'sort', g:tagbar_sort)
call tagbar#sorting#sort(self._taglist, 'kind', a:compare_typeinfo)
else
call tagbar#sorting#sort(self._taglist, 'line', a:compare_typeinfo)
endif
endfunction
" s:openKindFold() {{{1
function! s:openKindFold(kind) abort dict
let self.kindfolds[a:kind.short] = 0
endfunction
" s:closeKindFold() {{{1
function! s:closeKindFold(kind) abort dict
let self.kindfolds[a:kind.short] = 1
endfunction
" s:add_snr() {{{1
function! s:add_snr(funcname) abort
if !exists('s:snr')
let s:snr = matchstr(expand('<sfile>'), '<SNR>\d\+_\zeget_snr$')
endif
return s:snr . a:funcname
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,61 @@
function! tagbar#prototypes#kindheadertag#new(name) abort
let newobj = tagbar#prototypes#basetag#new(a:name)
let newobj.isKindheader = function(s:add_snr('s:isKindheader'))
let newobj.getPrototype = function(s:add_snr('s:getPrototype'))
let newobj.isFoldable = function(s:add_snr('s:isFoldable'))
let newobj.isFolded = function(s:add_snr('s:isFolded'))
let newobj.openFold = function(s:add_snr('s:openFold'))
let newobj.closeFold = function(s:add_snr('s:closeFold'))
let newobj.toggleFold = function(s:add_snr('s:toggleFold'))
return newobj
endfunction
" s:isKindheader() {{{1
function! s:isKindheader() abort dict
return 1
endfunction
" s:getPrototype() {{{1
function! s:getPrototype(short) abort dict
return self.name . ': ' .
\ self.numtags . ' ' . (self.numtags > 1 ? 'tags' : 'tag')
endfunction
" s:isFoldable() {{{1
function! s:isFoldable() abort dict
return 1
endfunction
" s:isFolded() {{{1
function! s:isFolded() abort dict
return self.fileinfo.kindfolds[self.short]
endfunction
" s:openFold() {{{1
function! s:openFold() abort dict
let self.fileinfo.kindfolds[self.short] = 0
endfunction
" s:closeFold() {{{1
function! s:closeFold() abort dict
let self.fileinfo.kindfolds[self.short] = 1
return line('.')
endfunction
" s:toggleFold() {{{1
function! s:toggleFold(fileinfo) abort dict
let a:fileinfo.kindfolds[self.short] = !a:fileinfo.kindfolds[self.short]
endfunction
" s:add_snr() {{{1
function! s:add_snr(funcname) abort
if !exists('s:snr')
let s:snr = matchstr(expand('<sfile>'), '<SNR>\d\+_\zeget_snr$')
endif
return s:snr . a:funcname
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,119 @@
function! tagbar#prototypes#normaltag#new(name) abort
let newobj = tagbar#prototypes#basetag#new(a:name)
let newobj.isNormalTag = function(s:add_snr('s:isNormalTag'))
let newobj.strfmt = function(s:add_snr('s:strfmt'))
let newobj.str = function(s:add_snr('s:str'))
let newobj.getPrototype = function(s:add_snr('s:getPrototype'))
return newobj
endfunction
" s:isNormalTag() {{{1
function! s:isNormalTag() abort dict
return 1
endfunction
" s:strfmt() {{{1
function! s:strfmt() abort dict
let typeinfo = self.typeinfo
let suffix = get(self.fields, 'signature', '')
if has_key(self.fields, 'type')
let suffix .= ' : ' . self.fields.type
elseif has_key(get(typeinfo, 'kind2scope', {}), self.fields.kind)
let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind]
endif
return self._getPrefix() . self.name . suffix
endfunction
" s:str() {{{1
function! s:str(longsig, full) abort dict
if a:full && self.path !=# ''
let str = self.path . self.typeinfo.sro . self.name
else
let str = self.name
endif
if has_key(self.fields, 'signature')
if a:longsig
let str .= self.fields.signature
else
let str .= '()'
endif
endif
return str
endfunction
" s:getPrototype() {{{1
function! s:getPrototype(short) abort dict
if self.prototype !=# ''
let prototype = self.prototype
else
let bufnr = self.fileinfo.bufnr
if self.fields.line == 0 || !bufloaded(bufnr)
" No linenumber available or buffer not loaded (probably due to
" 'nohidden'), try the pattern instead
return substitute(self.pattern, '^\\M\\^\\C\s*\(.*\)\\$$', '\1', '')
endif
let line = getbufline(bufnr, self.fields.line)[0]
let list = split(line, '\zs')
let start = index(list, '(')
if start == -1
return substitute(line, '^\s\+', '', '')
endif
let opening = count(list, '(', 0, start)
let closing = count(list, ')', 0, start)
if closing >= opening
return substitute(line, '^\s\+', '', '')
endif
let balance = opening - closing
let prototype = line
let curlinenr = self.fields.line + 1
while balance > 0
let curline = getbufline(bufnr, curlinenr)[0]
let curlist = split(curline, '\zs')
let balance += count(curlist, '(')
let balance -= count(curlist, ')')
let prototype .= "\n" . curline
let curlinenr += 1
endwhile
let self.prototype = prototype
endif
if a:short
" join all lines and remove superfluous spaces
let prototype = substitute(prototype, '^\s\+', '', '')
let prototype = substitute(prototype, '\_s\+', ' ', 'g')
let prototype = substitute(prototype, '(\s\+', '(', 'g')
let prototype = substitute(prototype, '\s\+)', ')', 'g')
" Avoid hit-enter prompts
let maxlen = &columns - 12
if len(prototype) > maxlen
let prototype = prototype[:maxlen - 1 - 3]
let prototype .= '...'
endif
endif
return prototype
endfunction
" s:add_snr() {{{1
function! s:add_snr(funcname) abort
if !exists('s:snr')
let s:snr = matchstr(expand('<sfile>'), '<SNR>\d\+_\zeget_snr$')
endif
return s:snr . a:funcname
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,36 @@
function! tagbar#prototypes#pseudotag#new(name) abort
let newobj = tagbar#prototypes#basetag#new(a:name)
let newobj.isPseudoTag = function(s:add_snr('s:isPseudoTag'))
let newobj.strfmt = function(s:add_snr('s:strfmt'))
return newobj
endfunction
" s:isPseudoTag() {{{1
function! s:isPseudoTag() abort dict
return 1
endfunction
" s:strfmt() {{{1
function! s:strfmt() abort dict
let typeinfo = self.typeinfo
let suffix = get(self.fields, 'signature', '')
if has_key(typeinfo.kind2scope, self.fields.kind)
let suffix .= ' : ' . typeinfo.kind2scope[self.fields.kind]
endif
return self._getPrefix() . self.name . '*' . suffix
endfunction
" s:add_snr() {{{1
function! s:add_snr(funcname) abort
if !exists('s:snr')
let s:snr = matchstr(expand('<sfile>'), '<SNR>\d\+_\zeget_snr$')
endif
return s:snr . a:funcname
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,26 @@
" A tag that was created because of a tag name that covers multiple scopes
" Inherits the fields of the "main" tag it was split from.
" May be replaced during tag processing if it appears as a normal tag later,
" just like a pseudo tag.
function! tagbar#prototypes#splittag#new(name) abort
let newobj = tagbar#prototypes#normaltag#new(a:name)
let newobj.isSplitTag = function(s:add_snr('s:isSplitTag'))
return newobj
endfunction
function! s:isSplitTag() abort dict
return 1
endfunction
function! s:add_snr(funcname) abort
if !exists('s:snr')
let s:snr = matchstr(expand('<sfile>'), '<SNR>\d\+_\zeget_snr$')
endif
return s:snr . a:funcname
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,42 @@
function! tagbar#prototypes#typeinfo#new(...) abort
let newobj = {}
let newobj.kinddict = {}
if a:0 > 0
call extend(newobj, a:1)
endif
let newobj.getKind = function(s:add_snr('s:getKind'))
let newobj.createKinddict = function(s:add_snr('s:createKinddict'))
return newobj
endfunction
" s:getKind() {{{1
function! s:getKind(kind) abort dict
let idx = self.kinddict[a:kind]
return self.kinds[idx]
endfunction
" s:createKinddict() {{{1
" Create a dictionary of the kind order for fast access in sorting functions
function! s:createKinddict() abort dict
let i = 0
for kind in self.kinds
let self.kinddict[kind.short] = i
let i += 1
endfor
let self.kinddict['?'] = i
endfunction
" s:add_snr() {{{1
function! s:add_snr(funcname) abort
if !exists('s:snr')
let s:snr = matchstr(expand('<sfile>'), '<SNR>\d\+_\zeget_snr$')
endif
return s:snr . a:funcname
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,57 @@
" Script-local variable needed since compare functions can't
" take additional arguments
let s:compare_typeinfo = {}
function! tagbar#sorting#sort(tags, compareby, compare_typeinfo) abort
let s:compare_typeinfo = a:compare_typeinfo
let comparemethod =
\ a:compareby ==# 'kind' ? 's:compare_by_kind' : 's:compare_by_line'
call sort(a:tags, comparemethod)
for tag in a:tags
if !empty(tag.getChildren())
call tagbar#sorting#sort(tag.getChildren(), a:compareby,
\ a:compare_typeinfo)
endif
endfor
endfunction
function! s:compare_by_kind(tag1, tag2) abort
let typeinfo = s:compare_typeinfo
if typeinfo.kinddict[a:tag1.fields.kind] <#
\ typeinfo.kinddict[a:tag2.fields.kind]
return -1
elseif typeinfo.kinddict[a:tag1.fields.kind] >#
\ typeinfo.kinddict[a:tag2.fields.kind]
return 1
else
" Ignore '~' prefix for C++ destructors to sort them directly under
" the constructors
if a:tag1.name[0] ==# '~'
let name1 = a:tag1.name[1:]
else
let name1 = a:tag1.name
endif
if a:tag2.name[0] ==# '~'
let name2 = a:tag2.name[1:]
else
let name2 = a:tag2.name
endif
let ci = g:tagbar_case_insensitive
if (((!ci) && (name1 <=# name2)) || (ci && (name1 <=? name2)))
return -1
else
return 1
endif
endif
endfunction
function! s:compare_by_line(tag1, tag2) abort
return a:tag1.fields.line - a:tag2.fields.line
endfunction
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,51 @@
function! tagbar#state#get_current_file(force_current) abort
return s:get().getCurrent(a:force_current)
endfunction
function! tagbar#state#set_current_file(fileinfo) abort
call s:get().setCurrentFile(a:fileinfo)
endfunction
function! tagbar#state#set_paused() abort
call s:get().setPaused()
endfunction
function! s:get() abort
if !exists('t:tagbar_state')
let t:tagbar_state = s:State.New()
endif
return t:tagbar_state
endfunction
let s:State = {
\ '_current' : {},
\ '_paused' : {},
\ }
" s:state.New() {{{1
function! s:State.New() abort dict
return deepcopy(self)
endfunction
" s:state.getCurrent() {{{1
function! s:State.getCurrent(force_current) abort dict
if !tagbar#is_paused() || a:force_current
return self._current
else
return self._paused
endif
endfunction
" s:state.setCurrentFile() {{{1
function! s:State.setCurrentFile(fileinfo) abort dict
let self._current = a:fileinfo
endfunction
" s:state.setPaused() {{{1
function! s:State.setPaused() abort dict
let self._paused = self._current
endfunction
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,773 @@
" Type definitions for standard Exuberant Ctags
function! tagbar#types#ctags#init(supported_types) abort
let types = {}
" Ant {{{1
let type_ant = tagbar#prototypes#typeinfo#new()
let type_ant.ctagstype = 'ant'
let type_ant.kinds = [
\ {'short' : 'p', 'long' : 'projects', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'targets', 'fold' : 0, 'stl' : 1}
\ ]
let types.ant = type_ant
" Asm {{{1
let type_asm = tagbar#prototypes#typeinfo#new()
let type_asm.ctagstype = 'asm'
let type_asm.kinds = [
\ {'short' : 'm', 'long' : 'macros', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'types', 'fold' : 0, 'stl' : 1},
\ {'short' : 'd', 'long' : 'defines', 'fold' : 0, 'stl' : 1},
\ {'short' : 'l', 'long' : 'labels', 'fold' : 0, 'stl' : 1}
\ ]
let types.asm = type_asm
" ASP {{{1
let type_aspvbs = tagbar#prototypes#typeinfo#new()
let type_aspvbs.ctagstype = 'asp'
let type_aspvbs.kinds = [
\ {'short' : 'd', 'long' : 'constants', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'subroutines', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 1}
\ ]
let types.aspvbs = type_aspvbs
" Asymptote {{{1
" Asymptote gets parsed well using filetype = c
let type_asy = tagbar#prototypes#typeinfo#new()
let type_asy.ctagstype = 'c'
let type_asy.kinds = [
\ {'short' : 'd', 'long' : 'macros', 'fold' : 1, 'stl' : 0},
\ {'short' : 'p', 'long' : 'prototypes', 'fold' : 1, 'stl' : 0},
\ {'short' : 'g', 'long' : 'enums', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0, 'stl' : 0},
\ {'short' : 't', 'long' : 'typedefs', 'fold' : 0, 'stl' : 0},
\ {'short' : 's', 'long' : 'structs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'u', 'long' : 'unions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'members', 'fold' : 0, 'stl' : 0},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let type_asy.sro = '::'
let type_asy.kind2scope = {
\ 'g' : 'enum',
\ 's' : 'struct',
\ 'u' : 'union'
\ }
let type_asy.scope2kind = {
\ 'enum' : 'g',
\ 'struct' : 's',
\ 'union' : 'u'
\ }
let types.asy = type_asy
" Awk {{{1
let type_awk = tagbar#prototypes#typeinfo#new()
let type_awk.ctagstype = 'awk'
let type_awk.kinds = [
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let types.awk = type_awk
" Basic {{{1
let type_basic = tagbar#prototypes#typeinfo#new()
let type_basic.ctagstype = 'basic'
let type_basic.kinds = [
\ {'short' : 'c', 'long' : 'constants', 'fold' : 0, 'stl' : 1},
\ {'short' : 'g', 'long' : 'enumerations', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'l', 'long' : 'labels', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'types', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 1}
\ ]
let types.basic = type_basic
" BETA {{{1
let type_beta = tagbar#prototypes#typeinfo#new()
let type_beta.ctagstype = 'beta'
let type_beta.kinds = [
\ {'short' : 'f', 'long' : 'fragments', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'slots', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'patterns', 'fold' : 0, 'stl' : 1}
\ ]
let types.beta = type_beta
" C {{{1
let type_c = tagbar#prototypes#typeinfo#new()
let type_c.ctagstype = 'c'
let type_c.kinds = [
\ {'short' : 'd', 'long' : 'macros', 'fold' : 1, 'stl' : 0},
\ {'short' : 'p', 'long' : 'prototypes', 'fold' : 1, 'stl' : 0},
\ {'short' : 'g', 'long' : 'enums', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0, 'stl' : 0},
\ {'short' : 't', 'long' : 'typedefs', 'fold' : 0, 'stl' : 0},
\ {'short' : 's', 'long' : 'structs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'u', 'long' : 'unions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'members', 'fold' : 0, 'stl' : 0},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let type_c.sro = '::'
let type_c.kind2scope = {
\ 'g' : 'enum',
\ 's' : 'struct',
\ 'u' : 'union'
\ }
let type_c.scope2kind = {
\ 'enum' : 'g',
\ 'struct' : 's',
\ 'union' : 'u'
\ }
let types.c = type_c
" C++ {{{1
let type_cpp = tagbar#prototypes#typeinfo#new()
let type_cpp.ctagstype = 'c++'
let type_cpp.kinds = [
\ {'short' : 'd', 'long' : 'macros', 'fold' : 1, 'stl' : 0},
\ {'short' : 'p', 'long' : 'prototypes', 'fold' : 1, 'stl' : 0},
\ {'short' : 'g', 'long' : 'enums', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0, 'stl' : 0},
\ {'short' : 't', 'long' : 'typedefs', 'fold' : 0, 'stl' : 0},
\ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'structs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'u', 'long' : 'unions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'members', 'fold' : 0, 'stl' : 0},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}
\ ]
let type_cpp.sro = '::'
let type_cpp.kind2scope = {
\ 'g' : 'enum',
\ 'n' : 'namespace',
\ 'c' : 'class',
\ 's' : 'struct',
\ 'u' : 'union'
\ }
let type_cpp.scope2kind = {
\ 'enum' : 'g',
\ 'namespace' : 'n',
\ 'class' : 'c',
\ 'struct' : 's',
\ 'union' : 'u'
\ }
let types.cpp = type_cpp
let types.cuda = type_cpp
" C# {{{1
let type_cs = tagbar#prototypes#typeinfo#new()
let type_cs.ctagstype = 'c#'
let type_cs.kinds = [
\ {'short' : 'd', 'long' : 'macros', 'fold' : 1, 'stl' : 0},
\ {'short' : 'f', 'long' : 'fields', 'fold' : 0, 'stl' : 1},
\ {'short' : 'g', 'long' : 'enums', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0, 'stl' : 0},
\ {'short' : 't', 'long' : 'typedefs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'structs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'E', 'long' : 'events', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'properties', 'fold' : 0, 'stl' : 1}
\ ]
let type_cs.sro = '.'
let type_cs.kind2scope = {
\ 'n' : 'namespace',
\ 'i' : 'interface',
\ 'c' : 'class',
\ 's' : 'struct',
\ 'g' : 'enum'
\ }
let type_cs.scope2kind = {
\ 'namespace' : 'n',
\ 'interface' : 'i',
\ 'class' : 'c',
\ 'struct' : 's',
\ 'enum' : 'g'
\ }
let types.cs = type_cs
" COBOL {{{1
let type_cobol = tagbar#prototypes#typeinfo#new()
let type_cobol.ctagstype = 'cobol'
let type_cobol.kinds = [
\ {'short' : 'd', 'long' : 'data items', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'file descriptions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'g', 'long' : 'group items', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'paragraphs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'P', 'long' : 'program ids', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'sections', 'fold' : 0, 'stl' : 1}
\ ]
let types.cobol = type_cobol
" DOS Batch {{{1
let type_dosbatch = tagbar#prototypes#typeinfo#new()
let type_dosbatch.ctagstype = 'dosbatch'
let type_dosbatch.kinds = [
\ {'short' : 'l', 'long' : 'labels', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 1}
\ ]
let types.dosbatch = type_dosbatch
" Eiffel {{{1
let type_eiffel = tagbar#prototypes#typeinfo#new()
let type_eiffel.ctagstype = 'eiffel'
let type_eiffel.kinds = [
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'features', 'fold' : 0, 'stl' : 1}
\ ]
let type_eiffel.sro = '.' " Not sure, is nesting even possible?
let type_eiffel.kind2scope = {
\ 'c' : 'class',
\ 'f' : 'feature'
\ }
let type_eiffel.scope2kind = {
\ 'class' : 'c',
\ 'feature' : 'f'
\ }
let types.eiffel = type_eiffel
" Erlang {{{1
let type_erlang = tagbar#prototypes#typeinfo#new()
let type_erlang.ctagstype = 'erlang'
let type_erlang.kinds = [
\ {'short' : 'm', 'long' : 'modules', 'fold' : 0, 'stl' : 1},
\ {'short' : 'd', 'long' : 'macro definitions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'r', 'long' : 'record definitions', 'fold' : 0, 'stl' : 1}
\ ]
let type_erlang.sro = '.' " Not sure, is nesting even possible?
let type_erlang.kind2scope = {
\ 'm' : 'module'
\ }
let type_erlang.scope2kind = {
\ 'module' : 'm'
\ }
let types.erlang = type_erlang
" Flex {{{1
" Vim doesn't support Flex out of the box, this is based on rough
" guesses and probably requires
" http://www.vim.org/scripts/script.php?script_id=2909
" Improvements welcome!
let type_as = tagbar#prototypes#typeinfo#new()
let type_as.ctagstype = 'flex'
let type_as.kinds = [
\ {'short' : 'v', 'long' : 'global variables', 'fold' : 0, 'stl' : 0},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'properties', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'x', 'long' : 'mxtags', 'fold' : 0, 'stl' : 0}
\ ]
let type_as.sro = '.'
let type_as.kind2scope = {
\ 'c' : 'class'
\ }
let type_as.scope2kind = {
\ 'class' : 'c'
\ }
let types.mxml = type_as
let types.actionscript = type_as
" Fortran {{{1
let type_fortran = tagbar#prototypes#typeinfo#new()
let type_fortran.ctagstype = 'fortran'
let type_fortran.kinds = [
\ {'short' : 'm', 'long' : 'modules', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'programs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'k', 'long' : 'components', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'derived types and structures', 'fold' : 0,
\ 'stl' : 1},
\ {'short' : 'c', 'long' : 'common blocks', 'fold' : 0, 'stl' : 1},
\ {'short' : 'b', 'long' : 'block data', 'fold' : 0, 'stl' : 0},
\ {'short' : 'e', 'long' : 'entry points', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'subroutines', 'fold' : 0, 'stl' : 1},
\ {'short' : 'l', 'long' : 'labels', 'fold' : 0, 'stl' : 1},
\ {'short' : 'n', 'long' : 'namelists', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}
\ ]
let type_fortran.sro = '.' " Not sure, is nesting even possible?
let type_fortran.kind2scope = {
\ 'm' : 'module',
\ 'p' : 'program',
\ 'f' : 'function',
\ 's' : 'subroutine'
\ }
let type_fortran.scope2kind = {
\ 'module' : 'm',
\ 'program' : 'p',
\ 'function' : 'f',
\ 'subroutine' : 's'
\ }
let types.fortran = type_fortran
" Go {{{1
let type_go = tagbar#prototypes#typeinfo#new()
let type_go.ctagstype = 'go'
let type_go.kinds = [
\ {'short' : 'p', 'long' : 'packages', 'fold' : 0, 'stl' : 0},
\ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0, 'stl' : 0},
\ {'short' : 'c', 'long' : 'constants', 'fold' : 0, 'stl' : 0},
\ {'short' : 's', 'long' : 'structs', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'struct members', 'fold' : 0, 'stl' : 0},
\ {'short' : 't', 'long' : 'types', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}
\ ]
let type_go.sro = '.'
let type_go.kind2scope = {
\ 's' : 'struct'
\ }
let type_go.scope2kind = {
\ 'struct' : 's'
\ }
let types.go = type_go
" HTML {{{1
let type_html = tagbar#prototypes#typeinfo#new()
let type_html.ctagstype = 'html'
let type_html.kinds = [
\ {'short' : 'f', 'long' : 'JavaScript functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'a', 'long' : 'named anchors', 'fold' : 0, 'stl' : 1}
\ ]
let types.html = type_html
" Java {{{1
let type_java = tagbar#prototypes#typeinfo#new()
let type_java.ctagstype = 'java'
let type_java.kinds = [
\ {'short' : 'p', 'long' : 'packages', 'fold' : 1, 'stl' : 0},
\ {'short' : 'f', 'long' : 'fields', 'fold' : 0, 'stl' : 0},
\ {'short' : 'g', 'long' : 'enum types', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'enum constants', 'fold' : 0, 'stl' : 0},
\ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 1}
\ ]
let type_java.sro = '.'
let type_java.kind2scope = {
\ 'g' : 'enum',
\ 'i' : 'interface',
\ 'c' : 'class'
\ }
let type_java.scope2kind = {
\ 'enum' : 'g',
\ 'interface' : 'i',
\ 'class' : 'c'
\ }
let types.java = type_java
" JavaScript {{{1
let type_javascript = tagbar#prototypes#typeinfo#new()
let type_javascript.ctagstype = 'javascript'
let type_javascript.kinds = [
\ {'short': 'v', 'long': 'global variables', 'fold': 0, 'stl': 0},
\ {'short': 'c', 'long': 'classes', 'fold': 0, 'stl': 1},
\ {'short': 'p', 'long': 'properties', 'fold': 0, 'stl': 0},
\ {'short': 'm', 'long': 'methods', 'fold': 0, 'stl': 1},
\ {'short': 'f', 'long': 'functions', 'fold': 0, 'stl': 1},
\ ]
let type_javascript.sro = '.'
let type_javascript.kind2scope = {
\ 'c' : 'class',
\ 'f' : 'function',
\ 'm' : 'method',
\ 'p' : 'property',
\ }
let type_javascript.scope2kind = {
\ 'class' : 'c',
\ 'function' : 'f',
\ }
let types.javascript = type_javascript
" Lisp {{{1
let type_lisp = tagbar#prototypes#typeinfo#new()
let type_lisp.ctagstype = 'lisp'
let type_lisp.kinds = [
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let types.lisp = type_lisp
let types.clojure = type_lisp
" Lua {{{1
let type_lua = tagbar#prototypes#typeinfo#new()
let type_lua.ctagstype = 'lua'
let type_lua.kinds = [
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let types.lua = type_lua
" Make {{{1
let type_make = tagbar#prototypes#typeinfo#new()
let type_make.ctagstype = 'make'
let type_make.kinds = [
\ {'short' : 'm', 'long' : 'macros', 'fold' : 0, 'stl' : 1}
\ ]
let types.make = type_make
" Matlab {{{1
let type_matlab = tagbar#prototypes#typeinfo#new()
let type_matlab.ctagstype = 'matlab'
let type_matlab.kinds = [
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let types.matlab = type_matlab
" ObjectiveC {{{1
let type_objc = tagbar#prototypes#typeinfo#new()
let type_objc.ctagstype = 'objectivec'
let type_objc.kinds = [
\ {'short' : 'M', 'long' : 'preprocessor macros', 'fold' : 1, 'stl' : 0},
\ {'short' : 'v', 'long' : 'global variables', 'fold' : 0, 'stl' : 0},
\ {'short' : 'i', 'long' : 'class interfaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'I', 'long' : 'class implementations', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'class methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 'F', 'long' : 'object fields', 'fold' : 0, 'stl' : 0},
\ {'short' : 'm', 'long' : 'object methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'type structures', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'type aliases', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'enumerations', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'properties', 'fold' : 0, 'stl' : 0},
\ ]
let type_objc.sro = ':'
let type_objc.kind2scope = {
\ 'i' : 'interface',
\ 'I' : 'implementation',
\ 's' : 'struct',
\ }
let type_objc.scope2kind = {
\ 'interface' : 'i',
\ 'implementation' : 'I',
\ 'struct' : 's',
\ }
let types.objc = type_objc
let types.objcpp = type_objc
" Ocaml {{{1
let type_ocaml = tagbar#prototypes#typeinfo#new()
let type_ocaml.ctagstype = 'ocaml'
let type_ocaml.kinds = [
\ {'short' : 'M', 'long' : 'modules or functors', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'global variables', 'fold' : 0, 'stl' : 0},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'C', 'long' : 'constructors', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'exceptions', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'type names', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'r', 'long' : 'structure fields', 'fold' : 0, 'stl' : 0}
\ ]
let type_ocaml.sro = '.' " Not sure, is nesting even possible?
let type_ocaml.kind2scope = {
\ 'M' : 'Module',
\ 'c' : 'class',
\ 't' : 'type'
\ }
let type_ocaml.scope2kind = {
\ 'Module' : 'M',
\ 'class' : 'c',
\ 'type' : 't'
\ }
let types.ocaml = type_ocaml
" Pascal {{{1
let type_pascal = tagbar#prototypes#typeinfo#new()
let type_pascal.ctagstype = 'pascal'
let type_pascal.kinds = [
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'procedures', 'fold' : 0, 'stl' : 1}
\ ]
let types.pascal = type_pascal
" Perl {{{1
let type_perl = tagbar#prototypes#typeinfo#new()
let type_perl.ctagstype = 'perl'
let type_perl.kinds = [
\ {'short' : 'p', 'long' : 'packages', 'fold' : 1, 'stl' : 0},
\ {'short' : 'c', 'long' : 'constants', 'fold' : 0, 'stl' : 0},
\ {'short' : 'f', 'long' : 'formats', 'fold' : 0, 'stl' : 0},
\ {'short' : 'l', 'long' : 'labels', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'subroutines', 'fold' : 0, 'stl' : 1}
\ ]
let types.perl = type_perl
" PHP {{{1
let type_php = tagbar#prototypes#typeinfo#new()
let type_php.ctagstype = 'php'
let type_php.kinds = [
\ {'short' : 'i', 'long' : 'interfaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'd', 'long' : 'constant definitions', 'fold' : 0, 'stl' : 0},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0},
\ {'short' : 'j', 'long' : 'javascript functions', 'fold' : 0, 'stl' : 1}
\ ]
let types.php = type_php
" Python {{{1
let type_python = tagbar#prototypes#typeinfo#new()
let type_python.ctagstype = 'python'
let type_python.kinds = [
\ {'short' : 'i', 'long' : 'imports', 'fold' : 1, 'stl' : 0},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'members', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0}
\ ]
let type_python.sro = '.'
let type_python.kind2scope = {
\ 'c' : 'class',
\ 'f' : 'function',
\ 'm' : 'function'
\ }
let type_python.scope2kind = {
\ 'class' : 'c',
\ 'function' : 'f'
\ }
let types.python = type_python
let types.pyrex = type_python
let types.cython = type_python
" REXX {{{1
let type_rexx = tagbar#prototypes#typeinfo#new()
let type_rexx.ctagstype = 'rexx'
let type_rexx.kinds = [
\ {'short' : 's', 'long' : 'subroutines', 'fold' : 0, 'stl' : 1}
\ ]
let types.rexx = type_rexx
" Ruby {{{1
let type_ruby = tagbar#prototypes#typeinfo#new()
let type_ruby.ctagstype = 'ruby'
let type_ruby.kinds = [
\ {'short' : 'm', 'long' : 'modules', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 'F', 'long' : 'singleton methods', 'fold' : 0, 'stl' : 1}
\ ]
let type_ruby.sro = '.'
let type_ruby.kind2scope = {
\ 'c' : 'class',
\ 'm' : 'class',
\ 'f' : 'class'
\ }
let type_ruby.scope2kind = {
\ 'class' : 'c'
\ }
let types.ruby = type_ruby
" Scheme {{{1
let type_scheme = tagbar#prototypes#typeinfo#new()
let type_scheme.ctagstype = 'scheme'
let type_scheme.kinds = [
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'sets', 'fold' : 0, 'stl' : 1}
\ ]
let types.scheme = type_scheme
let types.racket = type_scheme
" Shell script {{{1
let type_sh = tagbar#prototypes#typeinfo#new()
let type_sh.ctagstype = 'sh'
let type_sh.kinds = [
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let types.sh = type_sh
let types.csh = type_sh
let types.zsh = type_sh
" SLang {{{1
let type_slang = tagbar#prototypes#typeinfo#new()
let type_slang.ctagstype = 'slang'
let type_slang.kinds = [
\ {'short' : 'n', 'long' : 'namespaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1}
\ ]
let types.slang = type_slang
" SML {{{1
let type_sml = tagbar#prototypes#typeinfo#new()
let type_sml.ctagstype = 'sml'
let type_sml.kinds = [
\ {'short' : 'e', 'long' : 'exception declarations', 'fold' : 0, 'stl' : 0},
\ {'short' : 'f', 'long' : 'function definitions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'functor definitions', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'signature declarations', 'fold' : 0, 'stl' : 0},
\ {'short' : 'r', 'long' : 'structure declarations', 'fold' : 0, 'stl' : 0},
\ {'short' : 't', 'long' : 'type definitions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'value bindings', 'fold' : 0, 'stl' : 0}
\ ]
let types.sml = type_sml
" SQL {{{1
" The SQL ctags parser seems to be buggy for me, so this just uses the
" normal kinds even though scopes should be available. Improvements
" welcome!
let type_sql = tagbar#prototypes#typeinfo#new()
let type_sql.ctagstype = 'sql'
let type_sql.kinds = [
\ {'short' : 'P', 'long' : 'packages', 'fold' : 1, 'stl' : 1},
\ {'short' : 'd', 'long' : 'prototypes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'cursors', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'F', 'long' : 'record fields', 'fold' : 0, 'stl' : 1},
\ {'short' : 'L', 'long' : 'block label', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'procedures', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'subtypes', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'tables', 'fold' : 0, 'stl' : 1},
\ {'short' : 'T', 'long' : 'triggers', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 1},
\ {'short' : 'i', 'long' : 'indexes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'events', 'fold' : 0, 'stl' : 1},
\ {'short' : 'U', 'long' : 'publications', 'fold' : 0, 'stl' : 1},
\ {'short' : 'R', 'long' : 'services', 'fold' : 0, 'stl' : 1},
\ {'short' : 'D', 'long' : 'domains', 'fold' : 0, 'stl' : 1},
\ {'short' : 'V', 'long' : 'views', 'fold' : 0, 'stl' : 1},
\ {'short' : 'n', 'long' : 'synonyms', 'fold' : 0, 'stl' : 1},
\ {'short' : 'x', 'long' : 'MobiLink Table Scripts', 'fold' : 0, 'stl' : 1},
\ {'short' : 'y', 'long' : 'MobiLink Conn Scripts', 'fold' : 0, 'stl' : 1},
\ {'short' : 'z', 'long' : 'MobiLink Properties', 'fold' : 0, 'stl' : 1}
\ ]
let types.sql = type_sql
" Tcl {{{1
let type_tcl = tagbar#prototypes#typeinfo#new()
let type_tcl.ctagstype = 'tcl'
let type_tcl.kinds = [
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'procedures', 'fold' : 0, 'stl' : 1}
\ ]
let types.tcl = type_tcl
" LaTeX {{{1
let type_tex = tagbar#prototypes#typeinfo#new()
let type_tex.ctagstype = 'tex'
let type_tex.kinds = [
\ {'short' : 'i', 'long' : 'includes', 'fold' : 1, 'stl' : 0},
\ {'short' : 'p', 'long' : 'parts', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'chapters', 'fold' : 0, 'stl' : 1},
\ {'short' : 's', 'long' : 'sections', 'fold' : 0, 'stl' : 1},
\ {'short' : 'u', 'long' : 'subsections', 'fold' : 0, 'stl' : 1},
\ {'short' : 'b', 'long' : 'subsubsections', 'fold' : 0, 'stl' : 1},
\ {'short' : 'P', 'long' : 'paragraphs', 'fold' : 0, 'stl' : 0},
\ {'short' : 'G', 'long' : 'subparagraphs', 'fold' : 0, 'stl' : 0},
\ {'short' : 'l', 'long' : 'labels', 'fold' : 0, 'stl' : 0}
\ ]
let type_tex.sro = '""'
let type_tex.kind2scope = {
\ 'p' : 'part',
\ 'c' : 'chapter',
\ 's' : 'section',
\ 'u' : 'subsection',
\ 'b' : 'subsubsection'
\ }
let type_tex.scope2kind = {
\ 'part' : 'p',
\ 'chapter' : 'c',
\ 'section' : 's',
\ 'subsection' : 'u',
\ 'subsubsection' : 'b'
\ }
let type_tex.sort = 0
let types.tex = type_tex
" Vala {{{1
" Vala is supported by the ctags fork provided by Anjuta, so only add the
" type if the fork is used to prevent error messages otherwise
if has_key(a:supported_types, 'vala') || executable('anjuta-tags')
let type_vala = tagbar#prototypes#typeinfo#new()
let type_vala.ctagstype = 'vala'
let type_vala.kinds = [
\ {'short' : 'e', 'long' : 'Enumerations', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'Enumeration values', 'fold' : 0, 'stl' : 0},
\ {'short' : 's', 'long' : 'Structures', 'fold' : 0, 'stl' : 1},
\ {'short' : 'i', 'long' : 'Interfaces', 'fold' : 0, 'stl' : 1},
\ {'short' : 'd', 'long' : 'Delegates', 'fold' : 0, 'stl' : 1},
\ {'short' : 'c', 'long' : 'Classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'Properties', 'fold' : 0, 'stl' : 0},
\ {'short' : 'f', 'long' : 'Fields', 'fold' : 0, 'stl' : 0},
\ {'short' : 'm', 'long' : 'Methods', 'fold' : 0, 'stl' : 1},
\ {'short' : 'E', 'long' : 'Error domains', 'fold' : 0, 'stl' : 1},
\ {'short' : 'r', 'long' : 'Error codes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'S', 'long' : 'Signals', 'fold' : 0, 'stl' : 1}
\ ]
let type_vala.sro = '.'
" 'enum' doesn't seem to be used as a scope, but it can't hurt to have
" it here
let type_vala.kind2scope = {
\ 's' : 'struct',
\ 'i' : 'interface',
\ 'c' : 'class',
\ 'e' : 'enum'
\ }
let type_vala.scope2kind = {
\ 'struct' : 's',
\ 'interface' : 'i',
\ 'class' : 'c',
\ 'enum' : 'e'
\ }
let types.vala = type_vala
endif
if !has_key(a:supported_types, 'vala') && executable('anjuta-tags')
let types.vala.ctagsbin = 'anjuta-tags'
endif
" Vera {{{1
" Why are variables 'virtual'?
let type_vera = tagbar#prototypes#typeinfo#new()
let type_vera.ctagstype = 'vera'
let type_vera.kinds = [
\ {'short' : 'd', 'long' : 'macros', 'fold' : 1, 'stl' : 0},
\ {'short' : 'g', 'long' : 'enums', 'fold' : 0, 'stl' : 1},
\ {'short' : 'T', 'long' : 'typedefs', 'fold' : 0, 'stl' : 0},
\ {'short' : 'c', 'long' : 'classes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'enumerators', 'fold' : 0, 'stl' : 0},
\ {'short' : 'm', 'long' : 'members', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'tasks', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 0, 'stl' : 0},
\ {'short' : 'p', 'long' : 'programs', 'fold' : 0, 'stl' : 1}
\ ]
let type_vera.sro = '.' " Nesting doesn't seem to be possible
let type_vera.kind2scope = {
\ 'g' : 'enum',
\ 'c' : 'class',
\ 'v' : 'virtual'
\ }
let type_vera.scope2kind = {
\ 'enum' : 'g',
\ 'class' : 'c',
\ 'virtual' : 'v'
\ }
let types.vera = type_vera
" Verilog {{{1
let type_verilog = tagbar#prototypes#typeinfo#new()
let type_verilog.ctagstype = 'verilog'
let type_verilog.kinds = [
\ {'short' : 'c', 'long' : 'constants', 'fold' : 0, 'stl' : 0},
\ {'short' : 'e', 'long' : 'events', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'm', 'long' : 'modules', 'fold' : 0, 'stl' : 1},
\ {'short' : 'n', 'long' : 'net data types', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'ports', 'fold' : 0, 'stl' : 1},
\ {'short' : 'r', 'long' : 'register data types', 'fold' : 0, 'stl' : 1},
\ {'short' : 't', 'long' : 'tasks', 'fold' : 0, 'stl' : 1}
\ ]
let types.verilog = type_verilog
" VHDL {{{1
" The VHDL ctags parser unfortunately doesn't generate proper scopes
let type_vhdl = tagbar#prototypes#typeinfo#new()
let type_vhdl.ctagstype = 'vhdl'
let type_vhdl.kinds = [
\ {'short' : 'P', 'long' : 'packages', 'fold' : 1, 'stl' : 0},
\ {'short' : 'c', 'long' : 'constants', 'fold' : 0, 'stl' : 0},
\ {'short' : 't', 'long' : 'types', 'fold' : 0, 'stl' : 1},
\ {'short' : 'T', 'long' : 'subtypes', 'fold' : 0, 'stl' : 1},
\ {'short' : 'r', 'long' : 'records', 'fold' : 0, 'stl' : 1},
\ {'short' : 'e', 'long' : 'entities', 'fold' : 0, 'stl' : 1},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'p', 'long' : 'procedures', 'fold' : 0, 'stl' : 1}
\ ]
let types.vhdl = type_vhdl
" Vim {{{1
let type_vim = tagbar#prototypes#typeinfo#new()
let type_vim.ctagstype = 'vim'
let type_vim.kinds = [
\ {'short' : 'n', 'long' : 'vimball filenames', 'fold' : 0, 'stl' : 1},
\ {'short' : 'v', 'long' : 'variables', 'fold' : 1, 'stl' : 0},
\ {'short' : 'f', 'long' : 'functions', 'fold' : 0, 'stl' : 1},
\ {'short' : 'a', 'long' : 'autocommand groups', 'fold' : 1, 'stl' : 1},
\ {'short' : 'c', 'long' : 'commands', 'fold' : 0, 'stl' : 0},
\ {'short' : 'm', 'long' : 'maps', 'fold' : 1, 'stl' : 0}
\ ]
let types.vim = type_vim
" YACC {{{1
let type_yacc = tagbar#prototypes#typeinfo#new()
let type_yacc.ctagstype = 'yacc'
let type_yacc.kinds = [
\ {'short' : 'l', 'long' : 'labels', 'fold' : 0, 'stl' : 1}
\ ]
let types.yacc = type_yacc
" }}}1
for [type, typeinfo] in items(types)
let typeinfo.ftype = type
endfor
for typeinfo in values(types)
call typeinfo.createKinddict()
endfor
return types
endfunction
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
:TagbarClose tagbar.txt /*:TagbarClose*
:TagbarCurrentTag tagbar.txt /*:TagbarCurrentTag*
:TagbarDebug tagbar.txt /*:TagbarDebug*
:TagbarDebugEnd tagbar.txt /*:TagbarDebugEnd*
:TagbarGetTypeConfig tagbar.txt /*:TagbarGetTypeConfig*
:TagbarOpen tagbar.txt /*:TagbarOpen*
:TagbarOpenAutoClose tagbar.txt /*:TagbarOpenAutoClose*
:TagbarSetFoldlevel tagbar.txt /*:TagbarSetFoldlevel*
:TagbarShowTag tagbar.txt /*:TagbarShowTag*
:TagbarToggle tagbar.txt /*:TagbarToggle*
:TagbarTogglePause tagbar.txt /*:TagbarTogglePause*
g:tagbar_autoclose tagbar.txt /*g:tagbar_autoclose*
g:tagbar_autofocus tagbar.txt /*g:tagbar_autofocus*
g:tagbar_autopreview tagbar.txt /*g:tagbar_autopreview*
g:tagbar_autoshowtag tagbar.txt /*g:tagbar_autoshowtag*
g:tagbar_case_insensitive tagbar.txt /*g:tagbar_case_insensitive*
g:tagbar_compact tagbar.txt /*g:tagbar_compact*
g:tagbar_ctags_bin tagbar.txt /*g:tagbar_ctags_bin*
g:tagbar_ctags_options tagbar.txt /*g:tagbar_ctags_options*
g:tagbar_expand tagbar.txt /*g:tagbar_expand*
g:tagbar_foldlevel tagbar.txt /*g:tagbar_foldlevel*
g:tagbar_hide_nonpublic tagbar.txt /*g:tagbar_hide_nonpublic*
g:tagbar_iconchars tagbar.txt /*g:tagbar_iconchars*
g:tagbar_indent tagbar.txt /*g:tagbar_indent*
g:tagbar_left tagbar.txt /*g:tagbar_left*
g:tagbar_previewwin_pos tagbar.txt /*g:tagbar_previewwin_pos*
g:tagbar_show_balloon tagbar.txt /*g:tagbar_show_balloon*
g:tagbar_show_linenumbers tagbar.txt /*g:tagbar_show_linenumbers*
g:tagbar_show_visibility tagbar.txt /*g:tagbar_show_visibility*
g:tagbar_silent tagbar.txt /*g:tagbar_silent*
g:tagbar_singleclick tagbar.txt /*g:tagbar_singleclick*
g:tagbar_sort tagbar.txt /*g:tagbar_sort*
g:tagbar_status_func tagbar.txt /*g:tagbar_status_func*
g:tagbar_systemenc tagbar.txt /*g:tagbar_systemenc*
g:tagbar_updateonsave_maxlines tagbar.txt /*g:tagbar_updateonsave_maxlines*
g:tagbar_vertical tagbar.txt /*g:tagbar_vertical*
g:tagbar_width tagbar.txt /*g:tagbar_width*
g:tagbar_zoomwidth tagbar.txt /*g:tagbar_zoomwidth*
tagbar tagbar.txt /*tagbar*
tagbar#StopAutoUpdate() tagbar.txt /*tagbar#StopAutoUpdate()*
tagbar-autoopen tagbar.txt /*tagbar-autoopen*
tagbar-commands tagbar.txt /*tagbar-commands*
tagbar-configuration tagbar.txt /*tagbar-configuration*
tagbar-contents tagbar.txt /*tagbar-contents*
tagbar-credits tagbar.txt /*tagbar-credits*
tagbar-extend tagbar.txt /*tagbar-extend*
tagbar-features tagbar.txt /*tagbar-features*
tagbar-functions tagbar.txt /*tagbar-functions*
tagbar-highlight tagbar.txt /*tagbar-highlight*
tagbar-history tagbar.txt /*tagbar-history*
tagbar-ignore tagbar.txt /*tagbar-ignore*
tagbar-installation tagbar.txt /*tagbar-installation*
tagbar-intro tagbar.txt /*tagbar-intro*
tagbar-issues tagbar.txt /*tagbar-issues*
tagbar-keys tagbar.txt /*tagbar-keys*
tagbar-other tagbar.txt /*tagbar-other*
tagbar-pseudotags tagbar.txt /*tagbar-pseudotags*
tagbar-requirements tagbar.txt /*tagbar-requirements*
tagbar-statusline tagbar.txt /*tagbar-statusline*
tagbar-todo tagbar.txt /*tagbar-todo*
tagbar-usage tagbar.txt /*tagbar-usage*
tagbar.txt tagbar.txt /*tagbar.txt*

View File

@ -0,0 +1,153 @@
" ============================================================================
" File: tagbar.vim
" Description: List the current file's tags in a sidebar, ordered by class etc
" Author: Jan Larres <jan@majutsushi.net>
" Licence: Vim licence
" Website: http://majutsushi.github.com/tagbar/
" Version: 2.7
" Note: This plugin was heavily inspired by the 'Taglist' plugin by
" Yegappan Lakshmanan and uses a small amount of code from it.
"
" Original taglist copyright notice:
" Permission is hereby granted to use and distribute this code,
" with or without modifications, provided that this copyright
" notice is copied with it. Like anything else that's free,
" taglist.vim is provided *as is* and comes with no warranty of
" any kind, either expressed or implied. In no event will the
" copyright holder be liable for any damamges resulting from the
" use of this software.
" ============================================================================
scriptencoding utf-8
if &compatible || exists('g:loaded_tagbar')
finish
endif
" Basic init {{{1
if v:version < 700
echohl WarningMsg
echomsg 'Tagbar: Vim version is too old, Tagbar requires at least 7.0'
echohl None
finish
endif
if v:version == 700 && !has('patch167')
echohl WarningMsg
echomsg 'Tagbar: Vim versions lower than 7.0.167 have a bug'
\ 'that prevents this version of Tagbar from working.'
\ 'Please use the alternate version posted on the website.'
echohl None
finish
endif
function! s:init_var(var, value) abort
if !exists('g:tagbar_' . a:var)
execute 'let g:tagbar_' . a:var . ' = ' . string(a:value)
endif
endfunction
function! s:setup_options() abort
if !exists('g:tagbar_vertical') || g:tagbar_vertical == 0
let previewwin_pos = 'topleft'
else
let previewwin_pos = 'rightbelow vertical'
endif
let options = [
\ ['autoclose', 0],
\ ['autofocus', 0],
\ ['autopreview', 0],
\ ['autoshowtag', 0],
\ ['case_insensitive', 0],
\ ['compact', 0],
\ ['expand', 0],
\ ['foldlevel', 99],
\ ['hide_nonpublic', 0],
\ ['indent', 2],
\ ['left', 0],
\ ['previewwin_pos', previewwin_pos],
\ ['show_balloon', 1],
\ ['show_visibility', 1],
\ ['show_linenumbers', 0],
\ ['singleclick', 0],
\ ['sort', 1],
\ ['systemenc', &encoding],
\ ['vertical', 0],
\ ['width', 40],
\ ['zoomwidth', 1],
\ ['silent', 0],
\ ]
for [opt, val] in options
call s:init_var(opt, val)
endfor
endfunction
call s:setup_options()
if !exists('g:tagbar_iconchars')
if has('multi_byte') && has('unix') && &encoding ==# 'utf-8' &&
\ (!exists('+termencoding') || empty(&termencoding) || &termencoding ==# 'utf-8')
let g:tagbar_iconchars = ['▶', '▼']
else
let g:tagbar_iconchars = ['+', '-']
endif
endif
function! s:setup_keymaps() abort
let keymaps = [
\ ['jump', '<CR>'],
\ ['preview', 'p'],
\ ['previewwin', 'P'],
\ ['nexttag', '<C-N>'],
\ ['prevtag', '<C-P>'],
\ ['showproto', '<Space>'],
\ ['hidenonpublic', 'v'],
\
\ ['openfold', ['+', '<kPlus>', 'zo']],
\ ['closefold', ['-', '<kMinus>', 'zc']],
\ ['togglefold', ['o', 'za']],
\ ['openallfolds', ['*', '<kMultiply>', 'zR']],
\ ['closeallfolds', ['=', 'zM']],
\ ['incrementfolds', ['zr']],
\ ['decrementfolds', ['zm']],
\ ['nextfold', 'zj'],
\ ['prevfold', 'zk'],
\
\ ['togglesort', 's'],
\ ['togglecaseinsensitive', 'i'],
\ ['toggleautoclose', 'c'],
\ ['togglepause', 't'],
\ ['zoomwin', 'x'],
\ ['close', 'q'],
\ ['help', ['<F1>', '?']],
\ ]
for [map, key] in keymaps
call s:init_var('map_' . map, key)
unlet key
endfor
endfunction
call s:setup_keymaps()
augroup TagbarSession
autocmd!
autocmd SessionLoadPost * nested call tagbar#RestoreSession()
augroup END
" Commands {{{1
command! -nargs=0 Tagbar call tagbar#ToggleWindow()
command! -nargs=0 TagbarToggle call tagbar#ToggleWindow()
command! -nargs=? TagbarOpen call tagbar#OpenWindow(<f-args>)
command! -nargs=0 TagbarOpenAutoClose call tagbar#OpenWindow('fcj')
command! -nargs=0 TagbarClose call tagbar#CloseWindow()
command! -nargs=1 -bang TagbarSetFoldlevel call tagbar#SetFoldLevel(<args>, <bang>0)
command! -nargs=0 TagbarShowTag call tagbar#highlighttag(1, 1)
command! -nargs=? TagbarCurrentTag echo tagbar#currenttag('%s', 'No current tag', <f-args>)
command! -nargs=1 TagbarGetTypeConfig call tagbar#gettypeconfig(<f-args>)
command! -nargs=? TagbarDebug call tagbar#debug#start_debug(<f-args>)
command! -nargs=0 TagbarDebugEnd call tagbar#debug#stop_debug()
command! -nargs=0 TagbarTogglePause call tagbar#toggle_pause()
" Modeline {{{1
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

View File

@ -0,0 +1,64 @@
" File: tagbar.vim
" Description: Tagbar syntax settings
" Author: Jan Larres <jan@majutsushi.net>
" Licence: Vim licence
" Website: http://majutsushi.github.com/tagbar/
" Version: 2.7
scriptencoding utf-8
if exists('b:current_syntax')
finish
endif
let s:ics = escape(join(g:tagbar_iconchars, ''), ']^\-')
let s:pattern = '\(^[' . s:ics . '] \?\)\@3<=[^-+: ]\+[^:]\+$'
execute "syntax match TagbarKind '" . s:pattern . "'"
let s:pattern = '\(\S\@<![' . s:ics . '][-+# ]\?\)\@<=[^*(]\+\(\*\?\(([^)]\+)\)\? :\)\@='
execute "syntax match TagbarScope '" . s:pattern . "'"
let s:pattern = '\S\@<![' . s:ics . ']\([-+# ]\?\)\@='
execute "syntax match TagbarFoldIcon '" . s:pattern . "'"
let s:pattern = '\(\S\@<![' . s:ics . ' ]\)\@<=+\([^-+# ]\)\@='
execute "syntax match TagbarVisibilityPublic '" . s:pattern . "'"
let s:pattern = '\(\S\@<![' . s:ics . ' ]\)\@<=#\([^-+# ]\)\@='
execute "syntax match TagbarVisibilityProtected '" . s:pattern . "'"
let s:pattern = '\(\S\@<![' . s:ics . ' ]\)\@<=-\([^-+# ]\)\@='
execute "syntax match TagbarVisibilityPrivate '" . s:pattern . "'"
unlet s:pattern
syntax match TagbarHelp '^".*' contains=TagbarHelpKey,TagbarHelpTitle
syntax match TagbarHelpKey '" \zs.*\ze:' contained
syntax match TagbarHelpTitle '" \zs-\+ \w\+ -\+' contained
syntax match TagbarNestedKind '^\s\+\[[^]]\+\]$'
syntax match TagbarType ' : \zs.*'
syntax match TagbarSignature '(.*)'
syntax match TagbarPseudoID '\*\ze :'
highlight default link TagbarHelp Comment
highlight default link TagbarHelpKey Identifier
highlight default link TagbarHelpTitle PreProc
highlight default link TagbarKind Identifier
highlight default link TagbarNestedKind TagbarKind
highlight default link TagbarScope Title
highlight default link TagbarType Type
highlight default link TagbarSignature SpecialKey
highlight default link TagbarPseudoID NonText
highlight default link TagbarFoldIcon Statement
highlight default link TagbarHighlight Search
highlight default TagbarAccessPublic guifg=Green ctermfg=Green
highlight default TagbarAccessProtected guifg=Blue ctermfg=Blue
highlight default TagbarAccessPrivate guifg=Red ctermfg=Red
highlight default link TagbarVisibilityPublic TagbarAccessPublic
highlight default link TagbarVisibilityProtected TagbarAccessProtected
highlight default link TagbarVisibilityPrivate TagbarAccessPrivate
let b:current_syntax = 'tagbar'
" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
Vp4 vp4.txt /*Vp4*
Vp4Add vp4.txt /*Vp4Add*
Vp4Annotate vp4.txt /*Vp4Annotate*
Vp4Change vp4.txt /*Vp4Change*
Vp4Delete vp4.txt /*Vp4Delete*
Vp4Describe vp4.txt /*Vp4Describe*
Vp4Diff vp4.txt /*Vp4Diff*
Vp4Edit vp4.txt /*Vp4Edit*
Vp4Explore vp4.txt /*Vp4Explore*
Vp4Filelog vp4.txt /*Vp4Filelog*
Vp4Info vp4.txt /*Vp4Info*
Vp4Reopen vp4.txt /*Vp4Reopen*
Vp4Revert vp4.txt /*Vp4Revert*
Vp4Shelve vp4.txt /*Vp4Shelve*
g:vp4_allow_open_depot_file vp4.txt /*g:vp4_allow_open_depot_file*
g:vp4_annotate_revision vp4.txt /*g:vp4_annotate_revision*
g:vp4_diff_suppress_header vp4.txt /*g:vp4_diff_suppress_header*
g:vp4_filelog_max vp4.txt /*g:vp4_filelog_max*
g:vp4_open_loclist vp4.txt /*g:vp4_open_loclist*
g:vp4_perforce_executable vp4.txt /*g:vp4_perforce_executable*
g:vp4_prompt_on_write vp4.txt /*g:vp4_prompt_on_write*
vp4-commands vp4.txt /*vp4-commands*
vp4-credits vp4.txt /*vp4-credits*
vp4-intro vp4.txt /*vp4-intro*
vp4-issues vp4.txt /*vp4-issues*
vp4-options vp4.txt /*vp4-options*
vp4-passive vp4.txt /*vp4-passive*
vp4.txt vp4.txt /*vp4.txt*

View File

@ -0,0 +1,251 @@
*vp4.txt* integration with perforce
___
//| |
___ __ __//_| |_
\ \ // '_ \__ __|
\ V/| |_) ; | |
\_/ | .--' |_|
| |
\_|
Integration with perforce. Inspired by tpope/vim-fugitive.
==============================================================================
INTRO *vp4-intro*
vp4 does the following:
* Provides commands for interacting with perforce while remaining in Vim
* Automatically detects operations on files not open for edit
* Ridiculously functional annotation by adding more useful information
such as the date, user, and description of the changelist
* Fantastical diffing, including vs depot, vs shelved, vs previous rev
* File history browsing, with which you can (fairly) easily diff two
arbitrary revisions of any file
==============================================================================
COMMANDS *vp4-commands*
ANALYSIS - Query and display information about a file.
Annotate.|Vp4Annotate|
Diff.....|Vp4Diff|
Info.....|Vp4Info|
Filelog..|Vp4Filelog|
CHANGE SPECIFICATION - Perform actions on changelists.
Change...|Vp4Change|
Describe.|Vp4Describe|
Shelve...|Vp4Shelve|
FILE EDITING - Perform actions on files that alter their state in Perforce.
Add......|Vp4Add|
Delete...|Vp4Delete|
Edit.....|Vp4Edit|
Reopen...|Vp4Reopen|
Revert...|Vp4Revert|
FILE EXPLORATION - Explore the depot
Explore..|Vp4Explore|
------------------------------------------------------------------------------
ANALYSIS
*Vp4Annotate*
:[range]Vp4Annotate [q]
Opens a scrollbound split showing the changelist where each line was last
modified, and the date, user, and description of the changelist. This feature
is slow on large files with many different last changes. To speed it up,
visually select lines to fully annotate (recommended), or use the q option
to show only the changelist number. 'q' exits.
Opens a view like:>
+----------------------------------+------------------------+
| <Description> <date> <user> <cl> | for (auto elem : l) { |
| <Description> <date> <user> <cl> | std::cout << elem; |
| ... | ... |
+----------------------------------+------------------------+
| :Pannotate |
+----------------------------------+------------------------+
<
Note: Annotations will be misaligned on files that are currently being edited.
This is because `p4 annotate` works only submitted revisions of files. To
workaround this, it is suggested to open the last submitted revision of the
filelog using :Vp4Filelog and run :Vp4Annotate on that.
*Vp4Diff*
:Vp4Diff [s][p][@{cl}][#{rev}]
With no arguments, the depot version of the current file in a vertical split,
in diff mode. Hit 'q' to exit.
With [s] diff with shelved in current changelist. Only available if file
is open for edit and shelved.
With [p] diff with previous version. Available on any file that exists in
the depot.
With [@{cl}] diff with shelved in changelist {cl}. Available on any file
that exists in the depot, provided it is actually shelved in changelist.
With [#{rev}] diff with revision {rev}.
*Vp4Info*
Call `fstat` on this file.
*Vp4Filelog*
:Vp4Filelog [n]
Populate the quick-fix or location list with the past [n] or default revisions
of this file. The file is not actually retrieved from the server until it is
opened. Lists in chronologically reverse order.
Unset |g:vp4_open_loclist| to prevent the location list from being opened
automatically. Set |g:vp4_filelog_max| to limit the number of revisions
listed by default.
------------------------------------------------------------------------------
CHANGE SPECIFICATION
*Vp4Change*
Opens the change specification in a new split. Equivalent to `p4 change -o`
if current file is not already opened in a changelist and `p4 change -o -c
{cl}` if already opened in a changelist. Use the write (:w) command to make
the change, quit (:q) to abort.
*Vp4Describe*
Opens a preview window containing a description of the changelist in which the
current file is open, obtained from `p4 describe <cl>`
*Vp4Shelve*
:Vp4Shelve[!]
Calls the shelve command for the current file, for the changelist in which it
is currently open. Not available unless the file is open in a named
changelist (i.e. not the default changelist). With [!] performs the command
with '-f', overwriting any existing shelved version.
------------------------------------------------------------------------------
FILE EDITING
*Vp4Add*
Opens current file for add.
*Vp4Delete*
:Vp4Delete[!]
Opens current file for delete. Unloads current buffer. Confirms before doing
so; use [!] to skip confirmation.
*Vp4Edit*
Opens current file for edit.
*Vp4Reopen*
Move the current file to a different changelist. Lists all open changelists
and prompts for a selection.
*Vp4Revert*
:Vp4Revert[!]
Reverts current file. Confirms before doing so. Use [!] to skip
confirmation.
------------------------------------------------------------------------------
EXPLORATION
*Vp4Explore*
Opens depot file explorer at the current filepath.
Key mappings:
+======+===========================================+
| Key | function |
+------+-------------------------------------------+
| <CR> | Expand/collapse directory; go to file |
| - | Explore parent node |
| c | Change root of explorer to this directory |
| s | Open file in new split, syncing if req. |
| v | Open file in new vsplit, syncing if req. |
| t | Open file in new tab, syncing if req. |
| q | Quit |
+======+===========================================+
Set g:vp4_sync_options to pass options to perforce sync command.
------------------------------------------------------------------------------
SYSTEM
*Vp4*
:Vp4 <command>
Run arbitrary perforce command. Results are shown in a preview window.
==============================================================================
PASSIVE FEATURES *vp4-passive*
Prompt for edit
When writing a file, set |g:vp4_prompt_on_write| to enable prompt on write to
`p4 edit` the file.
Open depot file
Set |g:vp4_allow_open_depot_file| to allow vim to be invoked on a depot path
specification, like `vim //main/foo/bar/baz.cpp` where:
- if the file has been synced into the workspace, open the local file
- otherwise, fetch the file contents from server
==============================================================================
OPTIONS *vp4-options*
*g:vp4_perforce_executable* Name of perforce executable.
= p4 (default)
*g:vp4_prompt_on_write* Prompt for edit when (force) writing a file that
has not already been opened for edit.
= 0
= 1 (default)
*g:vp4_diff_suppress_header*
Suppress perforce header information in file
being diffed
= 0
= 1 (default)
*g:vp4_annotate_revision* Show revision number instead of changelist number
in which line was changed. Full annotation
(username, date, description) is not available if
set.
= 0 (default)
= 1
*g:vp4_open_loclist* Automatically open the location list after
performing |Vp4Filelog|
= 0
= 1 (default)
*g:vp4_filelog_max* Limit the number of revisions listed by
|Vp4Filelog|. Runs faster with a smaller limit.
= 10 (default)
<= 0 lists all revisions
*g:vp4_allow_open_depot_file*
Allow invoking vim with a perforce depot path. If
the file is synced locally, open that file.
Otherwise, open a new buffer with the server file
contents.
g:vp4_sync_options Options to pass to perforce sync command when
syncing files via the Explorer.
g:vp4_base_path_replacements
Allows P4 paths to be replaced at command time
= { /home/u/bad/repo/ : /home/u/good/repo} (ex)
= {} (default)
==============================================================================
KNOWN ISSUES *vp4-issues*
Extra line at top of depot file~
In any command that issues a `p4 print`, i.e. any diff command, or opening
other revisions of files, leaves an extra blank line at the top of the screen.
==============================================================================
CREDITS *vp4-credits*
This plugin was heavily inspired by vim-fugitive. Additionally, the author
was helped greatly by the book Learn Vimscript the Hard Way and Vim's
excellent built-in documentation.
vim:tw=78:ts=8:ft=help:norl:

View File

@ -0,0 +1,79 @@
" File: vp4.vim
" Description: vim global plugin for perforce integration
" Last Change: Nov 22, 2016
" Author: Emily Ng
" {{{ Initialization
if exists('g:loaded_vp4') || !executable('p4') || &cp
if exists('g:perforce_debug') && !g:perforce_debug
finish
endif
endif
let g:loaded_vp4 = 1
function! vp4#sid()
return maparg('<SID>', 'n')
endfunction
nnoremap <SID> <SID>
" Options
function! s:set(var, default)
if !exists(a:var)
if type(a:default)
execute 'let' a:var '=' string(a:default)
else
execute 'let' a:var '=' a:default
endif
endif
endfunction
call s:set('g:vp4_perforce_executable', 'p4')
call s:set('g:vp4_prompt_on_write', 1)
call s:set('g:vp4_annotate_revision', 0)
call s:set('g:vp4_open_loclist', 1)
call s:set('g:vp4_filelog_max', 10)
call s:set('g:perforce_debug', 0)
call s:set('g:vp4_diff_suppress_header', 1)
call s:set('g:vp4_print_suppress_header', 1)
call s:set('g:_vp4_curpos', [0, 0, 0, 0])
call s:set('g:_vp4_filetype', 'txt')
call s:set('g:vp4_allow_open_depot_file', 1)
call s:set('g:vp4_sync_options', '')
call s:set('g:vp4_base_path_replacements', {})
" }}}
" {{{ Auto-commands
augroup PromptOnWrite
autocmd!
if g:vp4_prompt_on_write
autocmd BufWritePre * call vp4#PromptForOpen()
endif
augroup END
augroup Vp4Enter
autocmd!
if g:vp4_allow_open_depot_file
autocmd VimEnter,BufReadCmd \(//\)\|\(#[0-9]\+\) call vp4#CheckServerPath(expand('%'))
endif
augroup END
" }}}
" {{{ Register commands
command! -nargs=? Vp4Diff call vp4#PerforceDiff(<f-args>)
command! -range=% -nargs=? Vp4Annotate <line1>,<line2>call vp4#PerforceAnnotate(<f-args>)
command! Vp4Change call vp4#PerforceChange()
command! -nargs=? Vp4Filelog call vp4#PerforceFilelog(<f-args>)
command! -bang Vp4Revert call vp4#PerforceRevert(<bang>0)
command! -bang Vp4Delete call vp4#PerforceDelete(<bang>0)
command! Vp4Reopen call vp4#PerforceReopen()
command! Vp4Edit call vp4#PerforceEdit()
command! Vp4Add call vp4#PerforceAdd()
command! -bang Vp4Shelve call vp4#PerforceShelve(<bang>0)
command! Vp4Describe call vp4#PerforceDescribe()
command! -nargs=+ Vp4 call vp4#PerforceSystemWr(<f-args>)
command! Vp4Info call vp4#PerforceSystemWr('fstat ' . expand('%'))
command! -nargs=? Vp4Explore call vp4#PerforceExplore(<f-args>)
" }}}
" vim: foldenable foldmethod=marker

85
.vim/colors/boring.vim Normal file
View File

@ -0,0 +1,85 @@
" Inspired by and based on Berk D. Demir's `noclown`:
" https://github.com/bdd/.vim/blob/09b4dbef06612c52c9c160773645bea82c0f490d/colors/noclown.vim
hi clear
if exists("syntax_on")
syntax reset
endif
let g:colors_name = "boring"
" Terminals that don't support italics resort to rendering them as standout.
" For comments and other things we italicize, this can become annoying very
" quickly. We are going to ignore 'italic' attribute if the terminal doesn't
" know about it.
let g:boring_has_italics = 0
if (has('gui_running') || has('unix') && system('tput sitm') == "\e[3m")
let g:boring_has_italics = 1
endif
let s:palette = {
\ 'bg' : ["black", '#000000'],
\ 'fg' : ["white", '#ffffff'],
\ 'dull' : [ 251, '#c6c6c6'],
\ 'dark' : [ 246, '#949494'],
\ 'deep' : [ 239, '#4e4e4e'],
\ }
function! s:Clear(group)
execute 'highlight! clear ' . a:group
execute 'highlight ' . a:group . ' NONE'
endfunction
function! s:Define(group, fg, bg, style)
call s:Clear(a:group)
let [l:ctermfg, l:guifg] = s:palette[a:fg]
let [l:ctermbg, l:guibg] = s:palette[a:bg]
let l:style = g:boring_has_italics || a:style != 'italic' ? a:style : 'NONE'
let l:hi_expr = 'highlight ' . a:group
let l:hi_expr .= ' cterm=' . l:style
let l:hi_expr .= ' ctermfg=' . l:ctermfg
let l:hi_expr .= ' ctermbg=' . l:ctermbg
let l:hi_expr .= ' gui=' . l:style
let l:hi_expr .= ' guifg=' . l:guifg
let l:hi_expr .= ' guibg=' . l:guibg
execute l:hi_expr
endfunction
function! s:Link(from, to)
call s:Clear(a:from)
execute 'highlight link ' . a:from . ' ' . a:to
endfunction
call s:Define('Normal', 'fg', 'bg', 'NONE')
call s:Define('PreProc', 'dull', 'bg', 'NONE')
call s:Define('Constant', 'dull', 'bg', 'NONE')
call s:Define('String', 'dull', 'bg', 'italic')
call s:Define('Comment', 'dark', 'bg', 'NONE')
call s:Define('SpecialKey', 'deep', 'bg', 'NONE')
call s:Define('TODO', 'dark', 'bg', 'bold')
call s:Define('IncSearch', 'dull', 'bg', 'inverse')
call s:Define('Search', 'fg', 'bg', 'inverse')
call s:Define('Folded', 'dark', 'bg', 'inverse')
call s:Define('Title', 'fg', 'bg', 'bold')
call s:Define('Underlined', 'fg', 'bg', 'underline')
call s:Define('Pmenu ', 'fg', 'bg', 'inverse')
call s:Define('PmenuSel', 'fg', 'bg', 'bold')
call s:Define('MatchParen', 'fg', 'bg', 'bold')
call s:Clear('Identifier')
call s:Clear('Special')
call s:Clear('Statement')
call s:Clear('Type')
call s:Clear('WarningMsg')
call s:Clear('Wildmenu')
call s:Clear('Directory')
call s:Clear('LineNr')
call s:Clear('SignColumn')
call s:Link('NonText', 'SpecialKey')
call s:Link('Error', 'Search')
call s:Link('ErrorMsg', 'Search')
call s:Link('FoldColumn', 'Folded')

13
.vim/spell/de.utf-8.add Normal file
View File

@ -0,0 +1,13 @@
iSeries
pdfgrep
Wireshark
ABAP
roundtrip
runtimes
STFK
ingwwdf1
saprouter
sapserv2
saprouttab
Steampunk
umkonfigurieren

BIN
.vim/spell/de.utf-8.spl Normal file

Binary file not shown.

BIN
.vim/spell/de.utf-8.sug Normal file

Binary file not shown.

BIN
.vim/spell/en.utf-8.spl Normal file

Binary file not shown.

BIN
.vim/spell/en.utf-8.sug Normal file

Binary file not shown.

230
.vim/vimrc Normal file
View File

@ -0,0 +1,230 @@
execute pathogen#infect()
Helptags
" VIM CORE
set nocompatible
set autochdir
set notitle
set shm+=I
set path+=.,**
set mouse=v
set laststatus=2
set keywordprg="man"
set backspace=indent,eol,start
set ttimeout
set ttimeoutlen=50
set number
set cursorline
set scrolloff=3
set spelllang=de,en
syntax on
filetype plugin indent on
set mmp=5000
set spelllang=de,en
set re=1
let mapleader = ","
nnoremap * *``
" INDENTATION
set noautoindent
set nosmartindent
set nocindent
" DIFF
set formatoptions=crolj
" SEARCH
set hlsearch
set ignorecase
set smartcase
" SPACES (TABS)
set tabstop=8
set shiftwidth=4
let &softtabstop=&shiftwidth
set expandtab
set smarttab
set textwidth=72
set list
set listchars=tab:»·,trail:•
set fillchars=vert:\|,eob:\
set showcmd
set clipboard=unnamedplus
" C specific highlighting
let c_space_errors=1
let c_gnu=1
let c_comment_strings=1
let c_curly_error=1
set makeprg=make\ %:r
set autowrite
" Work scripts
nnoremap mm :w\|!mymake<CR>
nnoremap mt :w\|!mytest<CR>
" TEMPORARY FILES
set undofile
set undodir=~/.local/vim/undo//
set backup
set backupcopy=yes
set backupdir=~/.local/vim/backup//
set directory=~/.local/vim/swapfiles//
set updatetime=2000
set updatecount=100
" CREATE DIRECTORIES
silent execute '!mkdir -p ~/.local/vim/backup ~/.local/vim/undo ~/.local/vim/swapfiles'
silent execute 'cs add ~/.dev/cscope.out'
set csprg=cscope\ -C
set cst
set cspc=9
" LOOK N FEEL
set t_Co=256
set t_ut=
set background=dark
let g:is_posix=1
" HIGHLIGHT SPECIAL WORDS
match ErrorMsg '\(TODO:\|FIXME\|XXX\|workaround\|WTF\|: error:.*\|\s\+$\| \+\ze\t\)'
" MY THEME
hi Comment ctermbg=NONE ctermfg=249 cterm=italic
hi Constant ctermbg=NONE ctermfg=251 cterm=italic
hi CursorLine ctermbg=NONE ctermfg=NONE cterm=NONE
hi CursorLineNr ctermbg=NONE ctermfg=NONE cterm=NONE
hi Directory ctermbg=NONE ctermfg=NONE cterm=NONE
hi Error ctermbg=NONE ctermfg=NONE cterm=NONE
hi ErrorMsg ctermbg=NONE ctermfg=196 cterm=NONE
hi Folded ctermbg=NONE ctermfg=246 cterm=inverse
hi Identifier ctermbg=NONE ctermfg=NONE cterm=NONE
hi Identifier ctermbg=NONE ctermfg=NONE cterm=NONE
hi Ignore ctermbg=NONE ctermfg=NONE cterm=NONE
hi IncSearch ctermbg=NONE ctermfg=251 cterm=inverse
hi LineNr ctermbg=NONE ctermfg=240 cterm=NONE
hi MatchParen ctermbg=NONE ctermfg=251 cterm=bold
hi NonText ctermbg=NONE ctermfg=NONE cterm=NONE
hi Normal ctermbg=NONE ctermfg=NONE cterm=NONE
hi Pmenu ctermbg=NONE ctermfg=251 cterm=inverse
hi PmenuSel ctermbg=NONE ctermfg=251 cterm=bold
hi PreProc ctermbg=NONE ctermfg=251 cterm=NONE
hi Search ctermbg=NONE ctermfg=251 cterm=inverse
hi SignColumn ctermbg=NONE ctermfg=NONE cterm=NONE
hi Special ctermbg=NONE ctermfg=NONE cterm=NONE
hi SpecialComment ctermbg=NONE ctermfg=NONE cterm=NONE
hi SpecialKey ctermbg=NONE ctermfg=239 cterm=NONE
hi Statement ctermbg=NONE ctermfg=NONE cterm=NONE
hi Statement ctermbg=NONE ctermfg=251 cterm=NONE
hi String ctermbg=NONE ctermfg=251 cterm=NONE
hi TODO ctermbg=NONE ctermfg=246 cterm=italic
hi Title ctermbg=NONE ctermfg=246 cterm=bold
hi Type ctermbg=NONE ctermfg=NONE cterm=NONE
hi Underlined ctermbg=NONE ctermfg=251 cterm=underline
hi VisualNOS ctermbg=NONE ctermfg=246 cterm=NONE
hi WarningMsg ctermbg=NONE ctermfg=NONE cterm=NONE
hi Wildmenu ctermbg=NONE ctermfg=NONE cterm=NONE
" VIMDIFF COLORS
hi DiffAdd ctermbg=22 ctermfg=NONE cterm=NONE
hi DiffDelete ctermbg=234 ctermfg=NONE cterm=NONE
hi DiffChange ctermbg=234 ctermfg=NONE cterm=NONE
hi DiffText ctermbg=NONE ctermfg=NONE cterm=NONE
" SPLIT AND FOLD COLORS
hi VertSplit ctermbg=NONE ctermfg=246 cterm=NONE
hi FoldColumn ctermbg=NONE ctermfg=251 cterm=NONE
hi Folded ctermbg=233 ctermfg=251 cterm=NONE
" SPELL COLOR
hi SpellBad ctermbg=NONE ctermfg=124
" C+PgUp/PgDown
nnoremap gn :next<CR>
nnoremap gp :prev<CR>
" NAVIGATE ON VISUAL LINES (SOFT WRAP)
imap <silent> <Down> <C-o> gj
imap <silent> <Up> <C-o> gk
nmap <silent> <Down> gj
nmap <silent> <Up> gk
" USE ARROW / VIM KEYS INSIDE OMNIBOX
inoremap <expr> j pumvisible() ? '<C-n>' : 'j'
inoremap <expr> k pumvisible() ? '<C-p>' : 'k'
inoremap <expr> <Down> pumvisible() ? '<C-n>' : '<Down>'
inoremap <expr> <Up> pumvisible() ? '<C-p>' : '<Up>'
" NETRW
let g:netrw_banner = 0
let g:netrw_browse_split = 3
let g:netrw_liststyle = 3
let g:netrw_ctags = "ectags"
let g:netrw_silent = 1
" STATUSLINE, AIRLINE/POWERLINE IS FOR NOOBS
set statusline=%#VisualNOS#
set statusline+=%F\ (%{&filetype})
set statusline+=%=
set statusline+=%m%r%h%w%q
set statusline+=\ %{&fileformat}/%{&fileencoding?&fileencoding:&encoding}
set statusline+=\ %b/0x%B
set statusline+=\ %c\ %p%%
set statusline+=\
" TAGS FILE
set tags="~/.dev/tags"
nnoremap gt :cs find 1 <C-R>=expand("<cword>")<CR><CR>
nnoremap gg :cs find 4 <C-R>=expand("<cword>")<CR><CR>
nnoremap gb <c-o>
nnoremap gh :FSHere<CR>
nnoremap oo :browse oldfiles<CR>
nnoremap XX :qall!<CR>
" PLUGIN: TAGBAR
nmap <F12> :TagbarToggle<CR>
let g:tagbar_ctags_bin = "ectags"
" PLUGIN: EASY ALIGN
xmap ga <Plug>(EasyAlign)
nmap ga <Plug>(EasyAlign)
" CUSTOM: NO CLUTTER PASTE MODE
nnoremap <silent> <Tab> :call TogglePaste()<CR>
let g:paste=0
function! TogglePaste()
if (g:paste == 0)
:set paste nolist nonumber |
\ echo "-- PASTE --"
let g:paste=1
else
:set nopaste list number |
\ echo "-- NOPASTE --"
let g:paste=0
endif
endfunction
" CUSTOM: COPY ACROSS VIM INSTANCES
vnoremap vy :call VisualYank()<CR>
nnoremap vp :call VisualPaste()<CR>
let s:temp_file_path = $HOME . '/.cache/vim-snap'
function! VisualYank()
call writefile(getline(getpos("'<")[1],
\ getpos("'>")[1]), s:temp_file_path)
endfunction
function! VisualPaste()
let file_msg = readfile(s:temp_file_path)
call append(line("."), file_msg)
endfunction
augroup mystuff
au!
au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
au BufRead,BufNewFile *.h,*.c set filetype=c.doxygen
au BufRead,BufNewFile Makefile,/usr/src/*.c,/usr/src/*.h,*.gmk setl sw=8 sts=8 noet
au BufWritePost vimrc so ~/.vim/vimrc
augroup end