" Vim syntax file " filetype: ledger " Version: 0.1.0 " 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. " Revision history " 2009-06-12 J. Klähn: Use all available columns for foldtext " 2009-03-25 J. Klähn: Allow Metadata " in transactions and postings (Ledger 3.0) " Also fixed alignment for multi-byte-characters " 2009-01-28 S.Karrmann: minor fixes " 2009-01-27 third version by S.Karrmann. " better extraction of the amount of the posting " decimal separator can be one of '.' and ','. " 2005-02-05 first version (partly copied from ledger.vim 0.0.1) " vim:ts=2:sw=2:sts=2:foldmethod=marker if version < 600 syntax clear elseif exists("b:current_sytax") finish 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 " for debugging syntax clear " region: a transaction containing postings syn region transNorm start=/^\d/ skip=/^\s/ end=/^/ \ fold keepend transparent contains=transDate, Metadata syn match transDate /^\d\S\+/ contained syn match Metadata /^\s\+;.*/ contained syn match Comment /^;.*$/ highlight default link Comment SpecialKey highlight default link Metadata SpecialKey highlight default link transDate Question function! s:multibyte_strlen(text) "{{{ return strlen(substitute(a:text, ".", "x", "g")) endf "}}} function s:get_columns(win) "{{{ " 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()/ " FIXME: Although this will propably never be used with debug mode enabled " this should take the signs column into account (:help sign.txt) let columns = (winwidth(a:win) == 0 ? 80 : winwidth(a:win)) - &foldcolumn if &number " line('w$') is the line number of the last line let columns -= max([len(line('w$'))+1, &numberwidth]) endif return columns endf "}}} let s:rx_amount = '\('. \ '\%([0-9]\+\)'. \ '\%([,.][0-9]\+\)*'. \ '\|'. \ '[,.][0-9]\+'. \ '\)'. \ '\s*\%([[:alpha:]¢$€£]\+\s*\)\?'. \ '\%(\s*;.*\)\?$' " folding: how to represent a transaction in one line. function! LedgerFoldText() " find amount let amount = "" let lnum = v:foldstart while lnum <= v:foldend let line = getline(lnum) " Skip metadata/leading comment if line !~ '^\s\+;' " No comment, look for amount... let groups = matchlist(line, s:rx_amount) echomsg string(groups) if ! empty(groups) echomsg amount 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(0) 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) let foldtext .= repeat(' ', s:get_columns(0)) " we don't use slices[:5], because that messes up multibyte characters let foldtext = substitute(foldtext, '.\{'.columns.'}\zs.*$', '', '') return printf(fmt, foldtext, amount) endfunction set foldtext=LedgerFoldText() set foldmethod=syntax " syncinc is easy: search for the first transaction. syn sync clear syn sync match ledgerSync grouphere transNorm "^\d" let b:current_syntax = "ledger"