1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
" 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< iskeyword< "
" don't fill fold lines --> cleaner look
setl fillchars="fold: "
setl foldtext=LedgerFoldText()
setl foldmethod=syntax
setl include=^!include
setl comments=b:;
" so you can use C-X C-N completion on accounts
" FIXME: Does not work with something like:
" Assets:Accountname with Spaces
setl iskeyword+=:
" 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 "}}}
|