From 7c67866b220514cf4771509521c297266bc7aa2c Mon Sep 17 00:00:00 2001 From: Johann Klähn Date: Fri, 12 Jun 2009 23:08:25 +0200 Subject: ledger.vim: use full width, not only 80 chars Also add option g:ledger_maxwidth to provide old behaviour by putting a line like this in .vimrc: let g:ledger_maxwidth = 80 I think that it would make sense to put all the functions and everything that has to do with foldtext in ftplugin/ledger.vim --- contrib/ledger.vim | 120 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 35 deletions(-) (limited to 'contrib') diff --git a/contrib/ledger.vim b/contrib/ledger.vim index fbe00f62..7ac1581c 100644 --- a/contrib/ledger.vim +++ b/contrib/ledger.vim @@ -1,74 +1,124 @@ " Vim syntax file " filetype: ledger -" Version: 0.0.5 +" 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-03-25 J. Klähn: Allow Metadata in postings (Ledger 3.0) +" 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 normal posting -syn region postNorm start=/^\d/ skip=/^\s/ end=/^/ fold keepend transparent contains=postDate,Metadata -syn match postDate /^\d\S\+/ contained +" 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 postDate Question +highlight default link transDate Question -" folding: how to represent a posting in one line. +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() - let line = strpart(getline(v:foldstart), 0, 99) - let amount = "" + " find amount + let amount = "" + let lnum = v:foldstart + while lnum <= v:foldend + let line = getline(lnum) - let delta = 1 - while (delta >= 1 && delta < (v:foldend-v:foldstart+1)) - let other_line = getline(v:foldstart+delta) - - if len(matchstr(other_line, '^\s\+;')) != 0 - " Skip metadata/leading comment - let delta = delta + 1 - else - " No comment, look for amount... - let delta = -1 - let lst = matchlist(other_line,'\(\%([0-9]\+[,.]\)\=[0-9]\+\%([,.][0-9]\+\)\=\|[,.][0-9]\+\)\s*\%([A-Za-z$€¢]\+\s*\)\=\%(\s*;.*\)\=$') - if (len(lst) != 0) - let amount = lst[1] - endif + " 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 - endwhile + endif + let lnum += 1 + endwhile - " Replace each char with x prior to counting - " this fixes problems with multi byte characters - let pad_len = 80 - strlen(substitute(line, ".", "x", "g")) - strlen(substitute(amount, ".", "x", "g")) - - if (pad_len < 0) - pad_len = 0 - endif - let pad = strpart(" ", 0, pad_len) - return line . pad . amount + 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 posting. +" syncinc is easy: search for the first transaction. syn sync clear -syn sync match ledgerSync grouphere postNorm "^\d" +syn sync match ledgerSync grouphere transNorm "^\d" let b:current_syntax = "ledger" -- cgit v1.2.3 From b96df34d75e9c0afde5b1706c00a6c8a58b2fff4 Mon Sep 17 00:00:00 2001 From: Johann Klähn Date: Mon, 15 Jun 2009 23:37:57 +0200 Subject: ledger.vim: split into multiple files for better extendability --- contrib/ledger.vim | 124 ---------------------------------------- contrib/vim/ftplugin/ledger.vim | 101 ++++++++++++++++++++++++++++++++ contrib/vim/syntax/ledger.vim | 43 ++++++++++++++ 3 files changed, 144 insertions(+), 124 deletions(-) delete mode 100644 contrib/ledger.vim create mode 100644 contrib/vim/ftplugin/ledger.vim create mode 100644 contrib/vim/syntax/ledger.vim (limited to 'contrib') diff --git a/contrib/ledger.vim b/contrib/ledger.vim deleted file mode 100644 index 7ac1581c..00000000 --- a/contrib/ledger.vim +++ /dev/null @@ -1,124 +0,0 @@ -" 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" diff --git a/contrib/vim/ftplugin/ledger.vim b/contrib/vim/ftplugin/ledger.vim new file mode 100644 index 00000000..4e8bfcf1 --- /dev/null +++ b/contrib/vim/ftplugin/ledger.vim @@ -0,0 +1,101 @@ +" Vimwiki filetype plugin file +" filetype: ledger +" Version: 0.1.0 +" 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< " + +" don't fill fold lines --> cleaner look +setl fillchars="fold: " +setl foldtext=LedgerFoldText() +setl foldmethod=syntax +setl include=^!include +setl comments=b:; + +" 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 + +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\+;' + " 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 "}}} + +" Helper functions {{{1 +function! s:multibyte_strlen(text) "{{{2 + return strlen(substitute(a:text, ".", "x", "g")) +endfunction "}}} + +function s:get_columns(win) "{{{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()/ + " 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 +endfunction "}}} + diff --git a/contrib/vim/syntax/ledger.vim b/contrib/vim/syntax/ledger.vim new file mode 100644 index 00000000..aac6c2fa --- /dev/null +++ b/contrib/vim/syntax/ledger.vim @@ -0,0 +1,43 @@ +" 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 + +" 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 + +" syncinc is easy: search for the first transaction. +syn sync clear +syn sync match ledgerSync grouphere transNorm "^\d" + +let b:current_syntax = "ledger" -- cgit v1.2.3 From 9701548f7e634f9a19295e34f624264343b78f0b Mon Sep 17 00:00:00 2001 From: Johann Klähn Date: Wed, 17 Jun 2009 12:40:50 +0200 Subject: vim: highlight account names This helps to avoid confusion when an account is not seperated from the amount by two spaces or a tab but only by one space. In these cases the amount will now be highlighted as if it belongs to the account name. Thanks to user 'plaindocs' for reporting this. --- contrib/vim/ftplugin/ledger.vim | 2 +- contrib/vim/syntax/ledger.vim | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'contrib') diff --git a/contrib/vim/ftplugin/ledger.vim b/contrib/vim/ftplugin/ledger.vim index 4e8bfcf1..cef0d81e 100644 --- a/contrib/vim/ftplugin/ledger.vim +++ b/contrib/vim/ftplugin/ledger.vim @@ -85,7 +85,7 @@ function! s:multibyte_strlen(text) "{{{2 return strlen(substitute(a:text, ".", "x", "g")) endfunction "}}} -function s:get_columns(win) "{{{2 +function! s:get_columns(win) "{{{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()/ diff --git a/contrib/vim/syntax/ledger.vim b/contrib/vim/syntax/ledger.vim index aac6c2fa..1c1968e4 100644 --- a/contrib/vim/syntax/ledger.vim +++ b/contrib/vim/syntax/ledger.vim @@ -26,15 +26,21 @@ endif syntax clear " region: a transaction containing postings -syn region transNorm start=/^\d/ skip=/^\s/ end=/^/ - \ fold keepend transparent contains=transDate, Metadata +syn region transNorm start=/^[[:digit:]~]/ skip=/^\s/ end=/^/ + \ fold keepend transparent contains=transDate, Metadata, Posting syn match transDate /^\d\S\+/ contained syn match Metadata /^\s\+;.*/ contained syn match Comment /^;.*$/ +" 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 Account /^\s\+\zs\%(\S\|\S \S\)\+\ze\%([ ]\{2,}\|\t\s*\|\s*$\)/ contained +syn match Posting /^\s\+[^[:blank:];].*$/ contained transparent contains=Account + -highlight default link Comment SpecialKey -highlight default link Metadata SpecialKey highlight default link transDate Question +highlight default link Metadata PreProc +highlight default link Comment Comment +highlight default link Account Identifier " syncinc is easy: search for the first transaction. syn sync clear -- cgit v1.2.3