diff options
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | contrib/vim/README | 89 | ||||
-rw-r--r-- | contrib/vim/compiler/ledger.vim | 28 | ||||
-rw-r--r-- | contrib/vim/ftplugin/ledger.vim | 639 | ||||
-rw-r--r-- | contrib/vim/indent/ledger.vim | 46 | ||||
-rw-r--r-- | contrib/vim/syntax/ledger.vim | 69 |
6 files changed, 7 insertions, 871 deletions
@@ -17,6 +17,13 @@ Now try your first ledger command: ./ledger -f test/input/sample.dat reg +For help on keeping your journal have a look at the +[documentation](http://www.ledger-cli.org/docs.html) and the +[wiki](http://wiki.ledger-cli.org/) (Also see the “Resources” section at the +end of this file). An emacs mode for ledger files can be found in the `lisp` +directory and a vim plugin is located in the [ledger/vim-ledger +repository](https://github.com/ledger/vim-ledger). + ## To the Rest If you're reading this file, you have in your hands the Bleeding Edge. This diff --git a/contrib/vim/README b/contrib/vim/README deleted file mode 100644 index a3f5a877..00000000 --- a/contrib/vim/README +++ /dev/null @@ -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/>. - diff --git a/contrib/vim/compiler/ledger.vim b/contrib/vim/compiler/ledger.vim deleted file mode 100644 index e9e98a8e..00000000 --- a/contrib/vim/compiler/ledger.vim +++ /dev/null @@ -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' - diff --git a/contrib/vim/ftplugin/ledger.vim b/contrib/vim/ftplugin/ledger.vim deleted file mode 100644 index 0067f9f8..00000000 --- a/contrib/vim/ftplugin/ledger.vim +++ /dev/null @@ -1,639 +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< commentstring< 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 commentstring=;%s -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 = 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 - -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 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 = LedgerFindInTree(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 = s: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('%Y/%m/%d')] - 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 "}}} - -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) - let exact = empty(nextlvls) - for branch in branches - call add(results, [branch, exact]) - if ! empty(nextlvls) - for [result, exact] in LedgerFindInTree(a:tree[branch], nextlvls) - call add(results, [branch.':'.result, exact]) - 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) || 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! 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) || has_key(trans, 'expr') - 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) || has_key(trans, 'expr') - 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 has_key(xact, 'description') && 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] ==# '=' - 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) 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 - 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() 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, '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:]]', '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:]]') - " 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! 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 "}}} diff --git a/contrib/vim/indent/ledger.vim b/contrib/vim/indent/ledger.vim deleted file mode 100644 index ce5d508d..00000000 --- a/contrib/vim/indent/ledger.vim +++ /dev/null @@ -1,46 +0,0 @@ -" 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 - -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 &sw - 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 &sw - else - return 0 - endif - else - " Everything else is not indented: - " start of transactions, pre-declarations, apply/end-lines - return 0 - endif -endf diff --git a/contrib/vim/syntax/ledger.vim b/contrib/vim/syntax/ledger.vim deleted file mode 100644 index c516bab0..00000000 --- a/contrib/vim/syntax/ledger.vim +++ /dev/null @@ -1,69 +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,ledgerTransactionExpression -syn match ledgerTransactionDate /^\d\S\+/ contained -syn match ledgerTransactionExpression /^[=~]\s\+\zs.*/ 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 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 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 ledgerApply - \ matchgroup=ledgerStartApply start=/^apply\>/ - \ matchgroup=ledgerEndApply end=/^end\s\+apply\>/ - \ contains=ledgerApplyHead,ledgerApply,ledgerTransaction,ledgerComment -syn match ledgerApplyHead /\%(^apply\s\+\)\@<=\S.*$/ contained - -highlight default link ledgerTransactionDate Constant -highlight default link ledgerTransactionExpression Statement -highlight default link ledgerMetadata Tag -highlight default link ledgerTypedTag Keyword -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 ledgerPreDeclarationType Type -highlight default link ledgerPreDeclarationName Identifier -highlight default link ledgerPreDeclarationDirective Type - -" syncinc is easy: search for the first transaction. -syn sync clear -syn sync match ledgerSync grouphere ledgerTransaction "^[[:digit:]~=]" - -let b:current_syntax = "ledger" |