summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/ParseCcStmt.cs2
-rwxr-xr-xcontrib/iso4127-commodities/iso4217ledger.sh54
-rw-r--r--contrib/iso4127-commodities/iso4217ledger.xsl138
-rw-r--r--contrib/ledger-completion.bash2
-rw-r--r--contrib/vim/README89
-rw-r--r--contrib/vim/compiler/ledger.vim28
-rw-r--r--contrib/vim/ftplugin/ledger.vim639
-rw-r--r--contrib/vim/indent/ledger.vim46
-rw-r--r--contrib/vim/syntax/ledger.vim69
9 files changed, 194 insertions, 873 deletions
diff --git a/contrib/ParseCcStmt.cs b/contrib/ParseCcStmt.cs
index c9ad1d55..04e3dbb9 100644
--- a/contrib/ParseCcStmt.cs
+++ b/contrib/ParseCcStmt.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2008, John Wiegley. All rights reserved.
+ * Copyright (c) 2003-2015, John Wiegley. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
diff --git a/contrib/iso4127-commodities/iso4217ledger.sh b/contrib/iso4127-commodities/iso4217ledger.sh
new file mode 100755
index 00000000..1841abe8
--- /dev/null
+++ b/contrib/iso4127-commodities/iso4217ledger.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# iso4217ledger.sh - Convert ISO 4217 currencies to ledger commodities
+#
+# This script will download the latest XML for ISO 4217 Table A.1
+# and print the contained currency & funds code list as ledger
+# commodity definitions to stdout.
+
+# Copyright (c) 2014 Alexis Hildebrandt
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+xml_url="http://www.currency-iso.org/dam/downloads/table_a1.xml"
+xsl_file="$(dirname $0)/iso4217ledger.xsl"
+
+xsltproc="$(which xsltproc)"
+if [ ! -f "$xsltproc" -o ! -x "$xsltproc" ]; then
+ echo "Can't find xsltproc"
+ exit 1
+fi
+
+download_command="$(which curl)"
+if [ -f "$download_command" \
+ -a -x "$download_command" ]; then
+ download_options="--silent"
+else
+ download_command="$(which wget)"
+ if [ -n "$download_command" \
+ -a -f "$download_command" \
+ -a -x "$download_command" ]; then
+ download_options="--quiet --output-document -"
+ else
+ echo "Can't find curl or wget."
+ exit 1
+ fi
+fi
+
+$download_command $download_options "$xml_url" | $xsltproc "$xsl_file" -
diff --git a/contrib/iso4127-commodities/iso4217ledger.xsl b/contrib/iso4127-commodities/iso4217ledger.xsl
new file mode 100644
index 00000000..cd70d2d6
--- /dev/null
+++ b/contrib/iso4127-commodities/iso4217ledger.xsl
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ! iso4217ledger.xsl - Transform ISO 4217 Table A.1 to ledger commodities
+ !
+ ! The current currency & funds code list is found at:
+ ! http://www.currency-iso.org/en/home/tables/table-a1.html
+ ! -->
+
+<!--
+ ! Copyright (c) 2014 Alexis Hildebrandt
+ !
+ ! Permission is hereby granted, free of charge, to any person obtaining a copy
+ ! of this software and associated documentation files (the "Software"), to deal
+ ! in the Software without restriction, including without limitation the rights
+ ! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ ! copies of the Software, and to permit persons to whom the Software is
+ ! furnished to do so, subject to the following conditions:
+ !
+ ! The above copyright notice and this permission notice shall be included in
+ ! all copies or substantial portions of the Software.
+ !
+ ! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ ! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ ! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ ! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ ! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ ! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ ! SOFTWARE.
+ ! -->
+
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ >
+
+ <!--
+ ! Set the value of this variable to your preferred decimal separator.
+ ! For European countries this is likely to be the comma ','.
+ ! -->
+ <xsl:variable name="decimal_separator">
+ <xsl:text>,</xsl:text>
+ <!--
+ <xsl:text>.</xsl:text>
+ -->
+ </xsl:variable>
+
+
+ <!--
+ ! Ensure that plain text will be written,
+ ! and all whitespace from the XML source is stripped.
+ ! -->
+ <xsl:output method="text"/>
+ <xsl:template match="text()" />
+
+ <!--
+ ! Add comment that the file was generated.
+ ! -->
+ <xsl:template match="/">
+ <xsl:text>; Ledger commodity declarations
+; Generated from ISO 4217 Table A.1 XML (</xsl:text>
+ <xsl:value-of select="ISO_4217/@Pblshd"/>
+<xsl:text>) using iso4217ledger.xsl
+
+</xsl:text>
+ <xsl:apply-templates />
+ </xsl:template>
+
+ <!--
+ ! Create ledger entry for the corresponding commodity
+ ! -->
+ <xsl:template match="CcyNtry">
+ <xsl:variable name="ccy">
+ <xsl:choose>
+ <xsl:when test="Ccy">
+ <xsl:value-of select="Ccy"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>¤</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:text>commodity </xsl:text>
+ <xsl:value-of select="$ccy"/>
+
+ <xsl:text>
+ note </xsl:text>
+ <xsl:value-of select="CcyNm"/>
+ <xsl:text> - </xsl:text>
+ <xsl:value-of select="normalize-space(CtryNm)"/>
+ <xsl:if test="CcyNbr">
+ <xsl:text> (</xsl:text>
+ <xsl:value-of select="CcyNbr"/>
+ <xsl:text>)</xsl:text>
+ </xsl:if>
+
+ <xsl:text>
+ format </xsl:text>
+ <xsl:value-of select="$ccy"/><xsl:text> </xsl:text>
+ <xsl:text>0000</xsl:text>
+ <xsl:choose>
+ <xsl:when test="CcyMnrUnts > 0">
+ <xsl:value-of select="$decimal_separator"/>
+ <xsl:call-template name="zero">
+ <xsl:with-param name="count" select="CcyMnrUnts"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="CcyMnrUnts = 'N.A.'">
+ <xsl:value-of select="$decimal_separator"/>
+ <xsl:call-template name="zero">
+ <xsl:with-param name="count" select="3"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:text>
+ nomarket
+
+</xsl:text>
+ </xsl:template>
+
+
+ <!--
+ ! Recursive template to generate 0s
+ ! -->
+ <xsl:template name="zero">
+ <xsl:param name="count" select="0"/>
+ <xsl:if test="$count > 0">
+ <xsl:text>0</xsl:text>
+ <xsl:call-template name="zero">
+ <xsl:with-param name="count" select="$count - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/contrib/ledger-completion.bash b/contrib/ledger-completion.bash
index 8f3e16af..d46b712d 100644
--- a/contrib/ledger-completion.bash
+++ b/contrib/ledger-completion.bash
@@ -43,7 +43,7 @@ _ledger()
# report.cc::lookup_option
# session.cc::lookup_option
#
- options="--abbrev-len= --account-width= --account= --actual --actual-dates --add-budget --amount-data --amount-width= --amount= --anon --ansi --args-only --auto-match --aux-date --average --balance-format= --base --basis --begin= --bold-if= --budget --budget-format= --by-payee --cache= --change --check-payees --cleared --cleared-format= --collapse --collapse-if-zero --color --columns= --cost --count --csv-format= --current --daily --date-format= --date-width= --date= --datetime-format= --day-break --days-of-week --dc --debug= --decimal-comma --depth= --detail --deviation --display-amount= --display-total= --display= --dow --download --effective --empty --end= --equity --exact --exchange= --explicit --file= --first= --flat --force-color --force-pager --forecast-years= --forecast= --format= --full-help --gain --generated --group-by= --group-title-format= --head= --help --help-calc --help-comm --help-disp --historical --immediate --init-file= --inject= --input-date-format= --invert --last= --leeway= --limit= --lot-dates --lot-notes --lot-prices --lot-tags --lots --lots-actual --market --master-account= --meta-width= --meta= --monthly --no-color --no-rounding --no-titles --no-total --now= --only= --options --output= --pager= --payee-width= --payee= --pedantic --pending --percent --period-sort= --period= --permissive --pivot= --plot-amount-format= --plot-total-format= --prepend-format= --prepend-width= --price --price-db= --price-exp= --pricedb-format= --prices-format= --primary-date --quantity --quarterly --raw --real --register-format= --related --related-all --revalued --revalued-only --revalued-total= --rich-data --script= --seed= --sort-all= --sort-xacts= --sort= --start-of-week= --strict --subtotal --tail= --time-colon --time-report --total-data --total-width= --total= --trace= --truncate= --unbudgeted --uncleared --unrealized --unrealized-gains= --unrealized-losses= --unround --value --value-expr= --values --verbose --verify --verify-memory --version --weekly --wide --yearly"
+ options="--abbrev-len= --account-width= --account= --actual --actual-dates --add-budget --amount-data --amount-width= --amount= --anon --ansi --args-only --auto-match --aux-date --average --balance-format= --base --basis --begin= --bold-if= --budget --budget-format= --by-payee --cache= --change --check-payees --cleared --cleared-format= --collapse --collapse-if-zero --color --columns= --cost --count --csv-format= --current --daily --date-format= --date-width= --date= --datetime-format= --day-break --days-of-week --dc --debug= --decimal-comma --depth= --detail --deviation --display-amount= --display-total= --display= --dow --download --effective --empty --end= --equity --exact --exchange= --explicit --file= --first= --flat --force-color --force-pager --forecast-while= --forecast-years= --forecast= --format= --full-help --gain --generated --group-by= --group-title-format= --head= --help --help-calc --help-comm --help-disp --historical --immediate --init-file= --inject= --input-date-format= --invert --last= --leeway= --limit= --lot-dates --lot-notes --lot-prices --lot-tags --lots --lots-actual --market --master-account= --meta-width= --meta= --monthly --no-aliases --no-color --no-pager --no-rounding --no-titles --no-total --now= --only= --options --output= --pager= --payee-width= --payee= --pedantic --pending --percent --period-sort= --period= --permissive --pivot= --plot-amount-format= --plot-total-format= --prepend-format= --prepend-width= --price --price-db= --price-exp= --pricedb-format= --prices-format= --primary-date --quantity --quarterly --raw --real --recursive-aliases --register-format= --related --related-all --revalued --revalued-only --revalued-total= --rich-data --script= --seed= --sort-all= --sort-xacts= --sort= --start-of-week= --strict --subtotal --tail= --time-colon --time-report --total-data --total-width= --total= --trace= --truncate= --unbudgeted --uncleared --unrealized --unrealized-gains= --unrealized-losses= --unround --value --value-expr= --values --verbose --verify --verify-memory --version --weekly --wide --yearly"
# Bash FAQ E13 http://tiswww.case.edu/php/chet/bash/FAQ
#
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"