Remove all submodules
They're more trouble than they're worth. Ick.
This commit is contained in:
		
							parent
							
								
									306cdc552c
								
							
						
					
					
						commit
						fa57bf9fcb
					
				
					 16 changed files with 0 additions and 819 deletions
				
			
		
							
								
								
									
										39
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1,39 +0,0 @@
 | 
				
			||||||
[submodule "vim/bundle/surround"]
 | 
					 | 
				
			||||||
        path = vim/bundle/surround
 | 
					 | 
				
			||||||
        url = https://github.com/tpope/vim-surround.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/speeddating"]
 | 
					 | 
				
			||||||
        path = vim/bundle/speeddating
 | 
					 | 
				
			||||||
        url = https://github.com/tpope/vim-speeddating.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/blackboard"]
 | 
					 | 
				
			||||||
	path = vim/bundle/blackboard
 | 
					 | 
				
			||||||
	url = https://github.com/nelstrom/vim-blackboard.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/fugitive"]
 | 
					 | 
				
			||||||
	path = vim/bundle/fugitive
 | 
					 | 
				
			||||||
	url = https://github.com/tpope/vim-fugitive.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/snipmate"]
 | 
					 | 
				
			||||||
	path = vim/bundle/snipmate
 | 
					 | 
				
			||||||
	url = https://github.com/msanders/snipmate.vim.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/unimpaired"]
 | 
					 | 
				
			||||||
	path = vim/bundle/unimpaired
 | 
					 | 
				
			||||||
	url = https://github.com/tpope/vim-unimpaired.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/git"]
 | 
					 | 
				
			||||||
	path = vim/bundle/git
 | 
					 | 
				
			||||||
	url = https://github.com/tpope/vim-git.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/solarized"]
 | 
					 | 
				
			||||||
	path = vim/bundle/solarized
 | 
					 | 
				
			||||||
	url = https://github.com/altercation/vim-colors-solarized.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/gundo"]
 | 
					 | 
				
			||||||
	path = vim/bundle/gundo
 | 
					 | 
				
			||||||
	url = https://github.com/sjl/gundo.vim.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/command-t"]
 | 
					 | 
				
			||||||
	path = vim/bundle/command-t
 | 
					 | 
				
			||||||
	url = https://github.com/wincent/Command-T.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/repeat"]
 | 
					 | 
				
			||||||
	path = vim/bundle/repeat
 | 
					 | 
				
			||||||
	url = https://github.com/tpope/vim-repeat
 | 
					 | 
				
			||||||
[submodule "mutt/mutt-colors-solarized"]
 | 
					 | 
				
			||||||
	path = mutt/mutt-colors-solarized
 | 
					 | 
				
			||||||
	url = https://github.com/altercation/mutt-colors-solarized.git
 | 
					 | 
				
			||||||
[submodule "vim/bundle/nerdtree"]
 | 
					 | 
				
			||||||
	path = vim/bundle/nerdtree
 | 
					 | 
				
			||||||
	url = https://github.com/scrooloose/nerdtree.git
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit c216b4355d4ece0b0868d621c60dd221e7751b0f
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit 3c0dc0a392fbea847ac97efe25f774cf1f2dcda0
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit f112f9b830a8f42375183c9a47965270ae8b3ae4
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit ca001e529f3d02675d66f9dd8b7253ab4f284ee1
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit 634756283ac38cc559235b24f4220a27fe04338f
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,89 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
This is the ledger filetype for vim.
 | 
					 | 
				
			||||||
Copy each file to the corresponding directory in your ~/.vim directory.
 | 
					 | 
				
			||||||
Then include the following line in your .vimrc  or in ~/.vim/filetype.vim
 | 
					 | 
				
			||||||
  au BufNewFile,BufRead *.ldg,*.ledger setf ledger | comp ledger
 | 
					 | 
				
			||||||
You can also use a modeline like this in every ledger file
 | 
					 | 
				
			||||||
  vim:filetype=ledger
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Tips and useful commands
 | 
					 | 
				
			||||||
======================================================================
 | 
					 | 
				
			||||||
 • Try account-completion (as explained below)
 | 
					 | 
				
			||||||
 • :call LedgerSetDate(line('.'), 'effective')
 | 
					 | 
				
			||||||
   will set today's date as the effective date of the current
 | 
					 | 
				
			||||||
   transaction. You can use also 'actual' in place of 'effective'
 | 
					 | 
				
			||||||
   or pass in a different date measured as seconds since 1st Jan 1970.
 | 
					 | 
				
			||||||
 • :call LedgerSetTransactionState(line('.'), '*')
 | 
					 | 
				
			||||||
   sets the state of the current transaction to '*'. You can
 | 
					 | 
				
			||||||
   use this in custom mappings.
 | 
					 | 
				
			||||||
 • :call LedgerToggleTransactionState(line('.'), ' *?!')
 | 
					 | 
				
			||||||
   will toggle through the provided transaction states.
 | 
					 | 
				
			||||||
   You can map this to double-clicking for example:
 | 
					 | 
				
			||||||
   noremap <silent><buffer> <2-LeftMouse>
 | 
					 | 
				
			||||||
   \ :call LedgerToggleTransactionState(line('.'), ' *?!')<CR>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Configuration
 | 
					 | 
				
			||||||
======================================================================
 | 
					 | 
				
			||||||
Include the following let-statements somewhere in your .vimrc
 | 
					 | 
				
			||||||
to modify the behaviour of the ledger filetype.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Number of colums 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 = '    -'
 | 
					 | 
				
			||||||
  My special tip is to use so-called digraphs:
 | 
					 | 
				
			||||||
  Press <C-K> followed by the two-characters key sequence below.
 | 
					 | 
				
			||||||
  (in insert-mode)
 | 
					 | 
				
			||||||
    '. = ˙ or ': = ¨ --> ˙˙˙˙˙˙ or ¨¨¨¨¨¨
 | 
					 | 
				
			||||||
    ', = ¸           --> ¸¸¸¸¸¸
 | 
					 | 
				
			||||||
    .M = ·           --> ······
 | 
					 | 
				
			||||||
    >> = »           --> »»»»»»
 | 
					 | 
				
			||||||
  All those look rather unobstrusive
 | 
					 | 
				
			||||||
  and provide a good visual aid to find the correct amount.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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
 | 
					 | 
				
			||||||
======================================================================
 | 
					 | 
				
			||||||
Copyright 2011-2009 by Johann Klähn
 | 
					 | 
				
			||||||
Copyright      2009 by Stefan Karrmann
 | 
					 | 
				
			||||||
Copyright      2005 by 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 <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,28 +0,0 @@
 | 
				
			||||||
" 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if exists("current_compiler")
 | 
					 | 
				
			||||||
  finish
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
let current_compiler = "ledger"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if exists(":CompilerSet") != 2
 | 
					 | 
				
			||||||
  command -nargs=* CompilerSet setlocal <args>
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" default value will be set in ftplugin
 | 
					 | 
				
			||||||
if ! exists("g:ledger_bin") || empty(g:ledger_bin) || ! executable(split(g:ledger_bin, '\s')[0])
 | 
					 | 
				
			||||||
  finish
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" %-G throws away blank lines, everything else is assumed to be part of a
 | 
					 | 
				
			||||||
" multi-line error message.
 | 
					 | 
				
			||||||
CompilerSet errorformat=%-G,%EWhile\ parsing\ file\ \"%f\"\\,\ line\ %l:%.%#,%ZError:\ %m,%C%.%#
 | 
					 | 
				
			||||||
CompilerSet errorformat+=%tarning:\ \"%f\"\\,\ line\ %l:\ %m
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" unfortunately there is no 'check file' command,
 | 
					 | 
				
			||||||
" so we will just use a query that returns no results. ever.
 | 
					 | 
				
			||||||
exe 'CompilerSet makeprg='.substitute(g:ledger_bin, ' ', '\\ ', 'g').'\ -f\ %\ reg\ not\ ''.*''\ \>\ /dev/null'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,597 +0,0 @@
 | 
				
			||||||
" 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if exists("b:did_ftplugin")
 | 
					 | 
				
			||||||
  finish
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let b:did_ftplugin = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let b:undo_ftplugin = "setlocal ".
 | 
					 | 
				
			||||||
                    \ "foldmethod< foldtext< ".
 | 
					 | 
				
			||||||
                    \ "include< comments< omnifunc< formatprg<"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" don't fill fold lines --> cleaner look
 | 
					 | 
				
			||||||
setl fillchars="fold: "
 | 
					 | 
				
			||||||
setl foldtext=LedgerFoldText()
 | 
					 | 
				
			||||||
setl foldmethod=syntax
 | 
					 | 
				
			||||||
setl include=^!include
 | 
					 | 
				
			||||||
setl comments=b:;
 | 
					 | 
				
			||||||
setl omnifunc=LedgerComplete
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" set location of ledger binary for checking and auto-formatting
 | 
					 | 
				
			||||||
if ! exists("g:ledger_bin") || empty(g:ledger_bin) || ! executable(split(g:ledger_bin, '\s')[0])
 | 
					 | 
				
			||||||
  if executable('ledger')
 | 
					 | 
				
			||||||
    let g:ledger_bin = 'ledger'
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    unlet g:ledger_bin
 | 
					 | 
				
			||||||
    echoerr "ledger command not found. Set g:ledger_bin or extend $PATH ".
 | 
					 | 
				
			||||||
          \ "to enable error checking and auto-formatting."
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if exists("g:ledger_bin")
 | 
					 | 
				
			||||||
  exe 'setl formatprg='.substitute(g:ledger_bin, ' ', '\\ ', 'g').'\ -f\ -\ print'
 | 
					 | 
				
			||||||
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 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 = 0
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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
 | 
					 | 
				
			||||||
  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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let fmt = '%s %s '
 | 
					 | 
				
			||||||
  " 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 columns -= s:multibyte_strlen(printf(fmt, '', amount))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  " add spaces so the text is always long enough when we strip it
 | 
					 | 
				
			||||||
  " to a certain width (fake table)
 | 
					 | 
				
			||||||
  if strlen(g:ledger_fillstring)
 | 
					 | 
				
			||||||
    " add extra spaces so fillstring aligns
 | 
					 | 
				
			||||||
    let filen = s:multibyte_strlen(g:ledger_fillstring)
 | 
					 | 
				
			||||||
    let folen = s:multibyte_strlen(foldtext)
 | 
					 | 
				
			||||||
    let foldtext .= repeat(' ', filen - (folen%filen))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let foldtext .= repeat(g:ledger_fillstring,
 | 
					 | 
				
			||||||
                  \ s:get_columns()/filen)
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    let foldtext .= repeat(' ', s:get_columns())
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  " we don't use slices[:5], because that messes up multibyte characters
 | 
					 | 
				
			||||||
  let foldtext = substitute(foldtext, '.\{'.columns.'}\zs.*$', '', '')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return printf(fmt, 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-marks)
 | 
					 | 
				
			||||||
        " is the beginning of the account name
 | 
					 | 
				
			||||||
        let b:compl_context = 'account'
 | 
					 | 
				
			||||||
        return matchend(line, '^\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 results = []
 | 
					 | 
				
			||||||
    if b:compl_context == 'account' "{{{2 (account)
 | 
					 | 
				
			||||||
      unlet! b:compl_context
 | 
					 | 
				
			||||||
      let hierarchy = split(a:base, ':')
 | 
					 | 
				
			||||||
      if a:base =~ ':$'
 | 
					 | 
				
			||||||
        call add(hierarchy, '')
 | 
					 | 
				
			||||||
      endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      let results = LedgerFindInTree(b:compl_cache.accounts, hierarchy)
 | 
					 | 
				
			||||||
      " sort by alphabet and reverse because it will get reversed one more time
 | 
					 | 
				
			||||||
      if g:ledger_detailed_first
 | 
					 | 
				
			||||||
        let results = reverse(sort(results, 's:sort_accounts_by_depth'))
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        let results = sort(results)
 | 
					 | 
				
			||||||
      endif
 | 
					 | 
				
			||||||
      call insert(results, a:base)
 | 
					 | 
				
			||||||
    elseif b:compl_context == 'description' "{{{2 (description)
 | 
					 | 
				
			||||||
      let results = [a:base] + s:filter_items(b:compl_cache.descriptions, a:base)
 | 
					 | 
				
			||||||
    elseif b:compl_context == 'new' "{{{2 (new line)
 | 
					 | 
				
			||||||
      return [strftime('%Y/%m/%d')]
 | 
					 | 
				
			||||||
    endif "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    " no completion (apart from a:base) found. update cache if file has changed
 | 
					 | 
				
			||||||
    if len(results) <= 1 && b:compl_cache['#'] != changenr()
 | 
					 | 
				
			||||||
      unlet b:compl_cache
 | 
					 | 
				
			||||||
      return LedgerComplete(a:findstart, a:base)
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      unlet! b:compl_context
 | 
					 | 
				
			||||||
      return results
 | 
					 | 
				
			||||||
    endif
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! LedgerFindInTree(tree, levels) "{{{1
 | 
					 | 
				
			||||||
  if empty(a:levels)
 | 
					 | 
				
			||||||
    return []
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
  let results = []
 | 
					 | 
				
			||||||
  let currentlvl = a:levels[0]
 | 
					 | 
				
			||||||
  let nextlvls = a:levels[1:]
 | 
					 | 
				
			||||||
  let branches = s:filter_items(keys(a:tree), currentlvl)
 | 
					 | 
				
			||||||
  for branch in branches
 | 
					 | 
				
			||||||
    call add(results, branch)
 | 
					 | 
				
			||||||
    if !empty(nextlvls)
 | 
					 | 
				
			||||||
      for result in LedgerFindInTree(a:tree[branch], nextlvls)
 | 
					 | 
				
			||||||
        call add(results, branch.':'.result)
 | 
					 | 
				
			||||||
      endfor
 | 
					 | 
				
			||||||
    endif
 | 
					 | 
				
			||||||
  endfor
 | 
					 | 
				
			||||||
  return results
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! LedgerToggleTransactionState(lnum, ...)
 | 
					 | 
				
			||||||
  if a:0 == 1
 | 
					 | 
				
			||||||
    let chars = a:1
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    let chars = ' *'
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
  let trans = s:transaction.from_lnum(a:lnum)
 | 
					 | 
				
			||||||
  if empty(trans)
 | 
					 | 
				
			||||||
    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! LedgerSetTransactionState(lnum, char) "{{{1
 | 
					 | 
				
			||||||
  " modifies or sets the state of the transaction at the cursor,
 | 
					 | 
				
			||||||
  " removing the state alltogether if a:char is empty
 | 
					 | 
				
			||||||
  let trans = s:transaction.from_lnum(a:lnum)
 | 
					 | 
				
			||||||
  if empty(trans)
 | 
					 | 
				
			||||||
    return
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  call trans.set_state(a:char)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  call setline(trans['head'], trans.format_head())
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! LedgerSetDate(lnum, type, ...) "{{{1
 | 
					 | 
				
			||||||
  let time = a:0 == 1 ? a:1 : localtime()
 | 
					 | 
				
			||||||
  let trans = s:transaction.from_lnum(a:lnum)
 | 
					 | 
				
			||||||
  if empty(trans)
 | 
					 | 
				
			||||||
    return
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let formatted = strftime('%Y/%m/%d', time)
 | 
					 | 
				
			||||||
  if has_key(trans, 'date') && ! empty(trans['date'])
 | 
					 | 
				
			||||||
    let date = split(trans['date'], '=')
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    let date = [formatted]
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if a:type ==? 'actual'
 | 
					 | 
				
			||||||
    let date[0] = formatted
 | 
					 | 
				
			||||||
  elseif a:type ==? 'effective'
 | 
					 | 
				
			||||||
    if time < 0
 | 
					 | 
				
			||||||
      " remove effective date
 | 
					 | 
				
			||||||
      let date = [date[0]]
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      " set effective date
 | 
					 | 
				
			||||||
      if len(date) >= 2
 | 
					 | 
				
			||||||
        let date[1] = formatted
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        call add(date, formatted)
 | 
					 | 
				
			||||||
      endif
 | 
					 | 
				
			||||||
    endif
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let trans['date'] = join(date, '=')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  call setline(trans['head'], trans.format_head())
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! s:collect_completion_data() "{{{1
 | 
					 | 
				
			||||||
  let transactions = s:get_transactions()
 | 
					 | 
				
			||||||
  let cache = {'descriptions': [], 'tags': {}, 'accounts': {}}
 | 
					 | 
				
			||||||
  let accounts = []
 | 
					 | 
				
			||||||
  for xact in transactions
 | 
					 | 
				
			||||||
    " collect descriptions
 | 
					 | 
				
			||||||
    if index(cache.descriptions, xact['description']) < 0
 | 
					 | 
				
			||||||
      call add(cache.descriptions, xact['description'])
 | 
					 | 
				
			||||||
    endif
 | 
					 | 
				
			||||||
    let [t, postings] = xact.parse_body()
 | 
					 | 
				
			||||||
    let tagdicts = [t]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    " collect account names
 | 
					 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    " 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 "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let s:transaction = {} "{{{1
 | 
					 | 
				
			||||||
function! s:transaction.new() dict
 | 
					 | 
				
			||||||
  return copy(s:transaction)
 | 
					 | 
				
			||||||
endf
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! s:transaction.from_lnum(lnum) 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] !~ '^\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) dict "{{{2
 | 
					 | 
				
			||||||
  if has_key(self, 'state') && a:char =~ '^\s*$'
 | 
					 | 
				
			||||||
    call remove(self, 'state')
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    let self['state'] = a:char
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! s:transaction.parse_body(...) 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
 | 
					 | 
				
			||||||
      " FIXME: replaces original spacing in amount with single spaces
 | 
					 | 
				
			||||||
      let parts = split(line[0], '\%(\t\|  \)\s*')
 | 
					 | 
				
			||||||
      call add(postings, {'account': parts[0], 'amount': join(parts[1:], '  ')})
 | 
					 | 
				
			||||||
    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() dict "{{{2
 | 
					 | 
				
			||||||
  if has_key(self, 'expr')
 | 
					 | 
				
			||||||
    return '~ '.self['expr']
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let parts = []
 | 
					 | 
				
			||||||
  if has_key(self, 'date') | call add(parts, self['date']) | endif
 | 
					 | 
				
			||||||
  if has_key(self, 'code') | call add(parts, '('.self['code'].')') | endif
 | 
					 | 
				
			||||||
  if has_key(self, 'state') | call add(parts, self['state']) | 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 {{{1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! s:get_transactions(...) "{{{2
 | 
					 | 
				
			||||||
  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:]]\S\+', 'cW')
 | 
					 | 
				
			||||||
  endw
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  " restore view / position
 | 
					 | 
				
			||||||
  let &foldenable = fe
 | 
					 | 
				
			||||||
  call winrestview(view)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return transactions
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function! s:get_transaction_extents(lnum) "{{{2
 | 
					 | 
				
			||||||
  if ! (indent(a:lnum) || getline(a:lnum) =~ '^[~[:digit:]]\S\+')
 | 
					 | 
				
			||||||
    " 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:]]\S\+', '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! s:findall(text, rx) " {{{2
 | 
					 | 
				
			||||||
  " 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 "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" 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 "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" remove spaces at start and end of string
 | 
					 | 
				
			||||||
function! s:strip_spaces(text) "{{{2
 | 
					 | 
				
			||||||
  return matchstr(a:text, '^\s*\zs\S\%(.*\S\)\?\ze\s*$')
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" return only those items that start with a specified keyword
 | 
					 | 
				
			||||||
function! s:filter_items(list, keyword) "{{{2
 | 
					 | 
				
			||||||
  return filter(copy(a:list), 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''')
 | 
					 | 
				
			||||||
endf "}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" return all lines matching an expression, returning only the matched part
 | 
					 | 
				
			||||||
function! s:grep_buffer(expression) "{{{2
 | 
					 | 
				
			||||||
  let lines = map(getline(1, '$'), 'matchstr(v:val, '''.a:expression.''')')
 | 
					 | 
				
			||||||
  return filter(lines, 'v:val != ""')
 | 
					 | 
				
			||||||
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 "}}}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,55 +0,0 @@
 | 
				
			||||||
" 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if version < 600
 | 
					 | 
				
			||||||
  syntax clear
 | 
					 | 
				
			||||||
elseif exists("b:current_sytax")
 | 
					 | 
				
			||||||
  finish
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" for debugging
 | 
					 | 
				
			||||||
syntax clear
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
" DATE[=EDATE] [*|!] [(CODE)] DESC <-- first line of transaction
 | 
					 | 
				
			||||||
"   ACCOUNT AMOUNT [; NOTE]  <-- posting
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
syn region ledgerTransaction start=/^[[:digit:]~]/ skip=/^\s/ end=/^/
 | 
					 | 
				
			||||||
    \ fold keepend transparent contains=ledgerTransactionDate,ledgerMetadata,ledgerPosting
 | 
					 | 
				
			||||||
syn match ledgerTransactionDate /^\d\S\+/ contained
 | 
					 | 
				
			||||||
syn match ledgerPosting /^\s\+[^[:blank:];][^;]*\ze\%($\|;\)/
 | 
					 | 
				
			||||||
    \ contained transparent contains=ledgerAccount,ledgerMetadata
 | 
					 | 
				
			||||||
" 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
 | 
					 | 
				
			||||||
syn match ledgerAccount /^\s\+\zs\%(\S\@<= \S\|\S\)\+\ze\%(  \|\t\|\s*$\)/ contained
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
syn match ledgerComment /^;.*$/
 | 
					 | 
				
			||||||
" comments at eol must be preceeded by at least 2 spaces / 1 tab
 | 
					 | 
				
			||||||
syn region ledgerMetadata start=/\%(  \|\t\|^\s\+\);/ skip=/^\s\+;/ end=/^/
 | 
					 | 
				
			||||||
    \ keepend contained contains=ledgerTag,ledgerTypedTag
 | 
					 | 
				
			||||||
syn match ledgerTag /:[^:]\+:/hs=s+1,he=e-1 contained
 | 
					 | 
				
			||||||
syn match ledgerTag /\%(\%(;\|^tag\)[^:]\+\)\@<=[^:]\+:\ze[^:]\+$/ contained
 | 
					 | 
				
			||||||
syn match ledgerTypedTag /\%(\%(;\|^tag\)[^:]\+\)\@<=[^:]\+::\ze[^:]\+$/ contained
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
syn region ledgerTagStack
 | 
					 | 
				
			||||||
    \ matchgroup=ledgerTagPush start=/^tag\>/
 | 
					 | 
				
			||||||
    \ matchgroup=ledgerTagPop end=/^pop\>/
 | 
					 | 
				
			||||||
    \ contains=ledgerTagHead,ledgerTagStack,ledgerTransaction,ledgerComment
 | 
					 | 
				
			||||||
syn match ledgerTagHead /\%(^tag\s\+\)\@<=\S.*$/ contained contains=ledgerTag transparent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
highlight default link ledgerTransactionDate Constant
 | 
					 | 
				
			||||||
highlight default link ledgerMetadata Tag
 | 
					 | 
				
			||||||
highlight default link ledgerTypedTag Keyword
 | 
					 | 
				
			||||||
highlight default link ledgerTag Type
 | 
					 | 
				
			||||||
highlight default link ledgerTagPop Tag
 | 
					 | 
				
			||||||
highlight default link ledgerTagPush Tag
 | 
					 | 
				
			||||||
highlight default link ledgerAccount Identifier
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
" syncinc is easy: search for the first transaction.
 | 
					 | 
				
			||||||
syn sync clear
 | 
					 | 
				
			||||||
syn sync match ledgerSync grouphere ledgerTransaction "^[[:digit:]~]"
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
let b:current_syntax = "ledger"
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit 2914f11f7494adefaaec1d8c817a301c464c94b2
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit 36e8f1322727a4e2cca7b65e4786b8d1d508b05d
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit 54180f1a5bc7950af8c0a43a86e8146179f48eaa
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit b0ee6ec2153c5f30827d67db1668f37a975a1005
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit d9e6bfdd902fc661c8fd58ede248ccfc3b3039d7
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
Subproject commit fe95324a679685054f2db2cc47fe482e9861ee8f
 | 
					 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue