aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--autoload/beancount.vim14
-rw-r--r--doc/beancount.txt61
-rw-r--r--rplugin/python3/deoplete/sources/beancount.py75
3 files changed, 134 insertions, 16 deletions
diff --git a/autoload/beancount.vim b/autoload/beancount.vim
index 9d18252..e262f11 100644
--- a/autoload/beancount.vim
+++ b/autoload/beancount.vim
@@ -113,7 +113,7 @@ function! beancount#complete(findstart, base)
endif
endfunction
-function! s:get_root()
+function! beancount#get_root()
if exists('b:beancount_root')
return b:beancount_root
endif
@@ -122,7 +122,7 @@ endfunction
function! beancount#load_everything()
if s:using_python3 && !exists('b:beancount_loaded')
- let l:root = s:get_root()
+ let l:root = beancount#get_root()
python3 << EOF
import vim
from beancount import loader
@@ -166,35 +166,35 @@ endfunction
function! beancount#load_accounts()
if !s:using_python3 && !exists('b:beancount_accounts')
- let l:root = s:get_root()
+ let l:root = beancount#get_root()
let b:beancount_accounts = beancount#find_accounts(l:root)
endif
endfunction
function! beancount#load_tags()
if !s:using_python3 && !exists('b:beancount_tags')
- let l:root = s:get_root()
+ let l:root = beancount#get_root()
let b:beancount_tags = beancount#find_tags(l:root)
endif
endfunction
function! beancount#load_links()
if !s:using_python3 && !exists('b:beancount_links')
- let l:root = s:get_root()
+ let l:root = beancount#get_root()
let b:beancount_links = beancount#find_links(l:root)
endif
endfunction
function! beancount#load_currencies()
if !s:using_python3 && !exists('b:beancount_currencies')
- let l:root = s:get_root()
+ let l:root = beancount#get_root()
let b:beancount_currencies = beancount#find_currencies(l:root)
endif
endfunction
function! beancount#load_payees()
if !s:using_python3 && !exists('b:beancount_payees')
- let l:root = s:get_root()
+ let l:root = beancount#get_root()
let b:beancount_payees = beancount#find_payees(l:root)
endif
endfunction
diff --git a/doc/beancount.txt b/doc/beancount.txt
index 2a2f37c..048a6c6 100644
--- a/doc/beancount.txt
+++ b/doc/beancount.txt
@@ -11,6 +11,7 @@ Filetype plugin and functions for working with beancount files.
Contents:
Commands.............|beancount-commands|
+ Options...............|beancount-options|
Completion.........|beancount-completion|
Syntax.................|beancount-syntax|
Compiler.............|beancount-compiler|
@@ -23,7 +24,7 @@ COMMANDS *beancount-commands*
*beancount-:AlignCommodity*
:AlignCommodity Adds spaces between an account and commodity so that the
decimal points of the commodities all occur in the column
- given by `g:decimal_separator_col`. If an amount has no
+ given by |g:beancount_separator_col|. If an amount has no
decimal point, the imaginary decimal point to the right
of the least significant digit will align.
@@ -34,7 +35,7 @@ COMMANDS *beancount-commands*
that it remains on the same character.
The alignment character can be set using
- `g:beancount_decimal_separator`. The script assumes the
+ |g:beancount_decimal_separator|. The script assumes the
use of spaces for alignment. It does not understand tabs.
You can use the following insert-mode remap to
@@ -60,14 +61,49 @@ COMMANDS *beancount-commands*
nnoremap <buffer> <LocalLeader>c :GetContext<CR>
<
+OPTIONS *beancount-options*
+
+*g:beancount_account_completion*
+ See |beancount-completion|. Can be either 'default' or 'chunks'.
+
+ Default value: 'default'
+
+*g:beancount_detailed_first*
+ If non-zero, accounts higher down the hierarchy will be listed first as
+ completions.
+
+ Default value: 0
+
+*g:beancount_separator_col*
+ The column that the decimal separator is aligned to.
+
+ Default value: 50
+
+*g:beancount_decimal_separator*
+ Set the decimal separator that numbers are aligned by.
+
+ Default value: '.'
+
+*b:beancount_root*
+ Set the root Beancount file. This is used to gather values for the
+ completion. If not set, the current file will be used.
+
+ Default value: not set
COMPLETION *beancount-completion*
-You can complete account names using CTRL-X CTRL-O. |i_CTRL-X_CTRL-O|
-Accounts must have their `open` directive in the current file. Completion is
-always case sensitive and exact. If the base string includes colons, each
-colon-separated piece can separately match a piece of the account.
+The plugin sets 'omnifunc' to provide omni completion for account names, tags,
+links, and payees. Omni completion is accessible with |i_CTRL-X_CTRL-O|.
+
+Completion works for values defined |b:beancount_root| and included files.
+
+Account Completion~
+ *beancount-complete-accounts*
+
+Completion is always case sensitive and exact. If the base string includes
+colons, each colon-separated piece can separately match a piece of the
+account.
For example, `Ex:Other` would complete to `Expenses:Donations:Other` or
`Liabilities:AmericanExpress:InterestOther`.
@@ -77,15 +113,22 @@ has to match at the beginning of that level of the account hierarchy, e.g.
`Ex:Oth` would match `Expenses:Other` but not `Expenses:Other:Something`
nor one of the two examples given above.
`Ex:Oth:` would, however, list all direct sub-accounts of `Expenses:Other`.
-To enable this mode use
+To enable this mode use >
let g:beancount_account_completion = 'chunks'
-
+<
Optionally, the list of candidates can be sorted by the number of levels
in the account hierarchy (e.g. return 'Expenses:Other' before 'Expenses').
-This behavior can be enabled using
+This behavior can be enabled using >
let g:beancount_detailed_first = 1
+<
+Deoplete~
+ *beancount-complete-deoplete*
+
+The plugin ships with a source for the deoplete.nvim, which provides
+asynchronous autocompletion. This should just work if deoplete is enabled. The
+options for the account completion do not work for the deoplete source.
SYNTAX *beancount-syntax*
diff --git a/rplugin/python3/deoplete/sources/beancount.py b/rplugin/python3/deoplete/sources/beancount.py
new file mode 100644
index 0000000..f595a54
--- /dev/null
+++ b/rplugin/python3/deoplete/sources/beancount.py
@@ -0,0 +1,75 @@
+import re
+
+from deoplete.source.base import Base
+
+try:
+ from beancount.loader import load_file
+ from beancount.core.data import Open, Transaction
+ HAS_BEANCOUNT = True
+except ImportError:
+ HAS_BEANCOUNT = False
+
+DIRECTIVES = ['open', 'close', 'commodity', 'txn', 'balance', 'pad', 'note',
+ 'document', 'price', 'event', 'query', 'custom']
+
+
+class Source(Base):
+ def __init__(self, vim):
+ super().__init__(vim)
+ self.vim = vim
+
+ self.name = 'beancount'
+ self.mark = '[bc]'
+ self.filetypes = ['beancount']
+ self.min_pattern_length = 0
+
+ def on_init(self, context):
+ if not HAS_BEANCOUNT:
+ self.error('Importing beancount failed.')
+
+ def on_event(self, context):
+ self.__make_cache(context)
+
+ def get_complete_position(self, context):
+ m = re.search(r'\S*$', context['input'])
+ return m.start() if m else -1
+
+ def gather_candidates(self, context):
+ if re.match(r'^\d{4}[/-]\d\d[/-]\d\d \w*$', context['input']):
+ return DIRECTIVES
+ if not context['complete_str']:
+ return []
+ first = context['complete_str'][0]
+ if first == '#':
+ return ['#' + w for w in self._tags]
+ elif first == '^':
+ return ['^' + w for w in self._links]
+ elif first == '"':
+ return ['"{}"'.format(w) for w in self._payees]
+ return self._accounts
+
+ def __make_cache(self, context):
+ accounts = set()
+ links = set()
+ payees = set()
+ tags = set()
+ if HAS_BEANCOUNT:
+ entries, _, _ = load_file(self.vim.eval("beancount#get_root()"))
+ else:
+ entries = []
+
+ for entry in entries:
+ if isinstance(entry, Open):
+ accounts.add(entry.account)
+ elif isinstance(entry, Transaction):
+ if entry.payee:
+ payees.add(entry.payee)
+ if hasattr(entry, 'links') and entry.links:
+ links.update(entry.links)
+ if hasattr(entry, 'tags') and entry.tags:
+ tags.update(entry.tags)
+
+ self._accounts = sorted(accounts)
+ self._links = sorted(links)
+ self._payees = sorted(payees)
+ self._tags = sorted(tags)