Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Tips and useful commands
noremap <silent><buffer> <2-LeftMouse>\
:call ledger#transaction_state_toggle(line('.'), ' *?!')<CR>

* Align commodities at the decimal point. See `help ledger-tips`.

Configuration
-------------

Expand Down
63 changes: 63 additions & 0 deletions autoload/ledger.vim
Original file line number Diff line number Diff line change
Expand Up @@ -330,3 +330,66 @@ function! s:findall(text, rx)

return matches
endf

" Move the cursor to the specified column, filling the line with spaces if necessary.
function! s:goto_col(pos)
exec "normal" a:pos . "|"
let diff = a:pos - virtcol('.')
if diff > 0 | exec "normal" diff . "a " | endif
endf

" Align the amount expression after an account name at the decimal point.
"
" This function moves the amount expression of a posting so that the decimal
" separator is aligned at the column specified by g:ledger_align_at.
"
" For example, after selecting:
"
" 2015/05/09 Some Payee
" Expenses:Other $120,23 ; Tags here
" Expenses:Something $-4,99
" Expenses:More ($12,34 + $16,32)
"
" :'<,'>call ledger#align_commodity() produces:
"
" 2015/05/09 Some Payee
" Expenses:Other $120,23 ; Tags here
" Expenses:Something $-4,99
" Expenses:More ($12,34 + $16,32)
"
function! ledger#align_commodity()
" Extract the part of the line after the account name (excluding spaces):
let rhs = matchstr(getline('.'), '\m^\s\+[^;[:space:]].\{-}\(\t\| \)\s*\zs.*$')
if rhs != ''
" Remove everything after the account name (including spaces):
.s/\m^\s\+[^[:space:]].\{-}\zs\(\t\| \).*$//
if g:ledger_decimal_sep == ''
let pos = matchend(rhs, '\m\d[^[:space:]]*')
else
" Find the position of the first decimal separator:
let pos = match(rhs, '\V' . g:ledger_decimal_sep)
endif
" Go to the column that allows us to align the decimal separator at g:ledger_align_at:
call s:goto_col(g:ledger_align_at - pos - 1)
" Append the part of the line that was previously removed:
exe 'normal a' . rhs
endif
endf!

" Align the amount under the cursor and append/prepend the default currency.
function! ledger#align_amount_at_cursor()
" Select and cut text:
normal viWd
" Find the position of the decimal separator
let pos = match(@", g:ledger_decimal_sep) " Returns zero when the separator is the empty string
" Paste text at the correct column and append/prepend default commodity:
if g:ledger_commodity_before
call s:goto_col(g:ledger_align_at - (pos > 0 ? pos : len(@")) - len(g:ledger_default_commodity) - len(g:ledger_commodity_sep) - 1)
exe 'normal a' . g:ledger_default_commodity . g:ledger_commodity_sep
normal p
else
call s:goto_col(g:ledger_align_at - (pos > 0 ? pos : len(@")) - 1)
exe 'normal pa' . g:ledger_commodity_sep . g:ledger_default_commodity
endif
endf!

52 changes: 52 additions & 0 deletions doc/ledger.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,38 @@ Tips and useful commands
noremap <silent><buffer> <2-LeftMouse>\
:call ledger#transaction_state_toggle(line('.'), ' *?!')<CR>

* `:LedgerAlign`

moves the amount expression of a posting so that the decimal separator is
aligned at the column specified by g:ledger_align_at. If an amount has no
decimal point, the imaginary decimal point to the right of the least
significant digit will align. The command acts on a range, with the default
being the current line.

The decimal separator can be set using `g:ledger_decimal_sep`. The default
value of `g:ledger_decimal_sep` is `'.'`.

It is convenient to remap the command, for example to `<Leader>a`:

au FileType ledger vnoremap <silent><buffer> <Leader>a \
:LedgerAlign<CR>

* :call ledger#align_amount_at_cursor()

aligns the amount under the cursor and append/prepend the default currency.
The default currency can be set using `g:ledger_default_commodity`. Whether
the commodity should be inserted before the amount or appended to it can be
configured with the boolean flag `g:ledger_commodity_before` (the default
value is 1). A separator between the commodity and the amount may be set
using `g:ledger_commodity_sep`.

It is convenient to define a mapping like the following:

au FileType ledger inoremap <silent><buffer> <C-l> \
<Esc>:call ledger#align_amount_at_cursor()<CR>

Now, you may type `123.45<C-l>`, and have `$123.45` properly aligned (assuming
your default commodity is set to `'$'`).
==============================================================================
SETTINGS *ledger-settings*

Expand Down Expand Up @@ -90,6 +122,26 @@ behaviour of the ledger filetype.
folding. You can take advantage of this to disable this feature on a
case-by-case basis.

* Decimal separator:

let g:ledger_decimal_sep = '.'

* Specify at which column decimal separators should be aligned:

let g:ledger_align_at = 60

* Default commodity used by `ledger#align_amount_at_cursor()`:

let g:ledger_default_commodity = ''

* Flag that tells whether the commodity should be prepended or appended to the
amount:

let g:ledger_commodity_before = 1

* String to be put between the commodity and the amount:

let g:ledger_commodity_sep = ''
==============================================================================
COMPLETION *ledger-completion*

Expand Down
27 changes: 27 additions & 0 deletions ftplugin/ledger.vim
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ if !exists('g:ledger_fillstring')
let g:ledger_fillstring = ' '
endif

if !exists('g:ledger_decimal_sep')
let g:ledger_decimal_sep = '.'
endif

if !exists('g:ledger_align_at')
let g:ledger_align_at = 60
endif

if !exists('g:ledger_default_commodity')
let g:ledger_default_commodity = ''
endif

if !exists('g:ledger_commodity_before')
let g:ledger_commodity_before = 1
endif

if !exists('g:ledger_commodity_sep')
let g:ledger_commodity_sep = ''
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:
Expand Down Expand Up @@ -328,3 +348,10 @@ endf "}}}
function! s:count_expression(text, expression) "{{{2
return len(split(a:text, a:expression, 1))-1
endf "}}}

" Commands {{{1
if !exists(":LedgerAlign")
command -range LedgerAlign <line1>,<line2>call ledger#align_commodity()
endif
" }}}