From 3a9665dd45ad38bc98f18a091fe460f7a46ea4df Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Sun, 20 Nov 2016 18:20:53 +0100 Subject: add deoplete source --- rplugin/python3/deoplete/sources/beancount.py | 75 +++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 rplugin/python3/deoplete/sources/beancount.py diff --git a/rplugin/python3/deoplete/sources/beancount.py b/rplugin/python3/deoplete/sources/beancount.py new file mode 100644 index 0000000..4618105 --- /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("expand('%')")) + 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) -- cgit v1.2.3-2-gb3c3 From 983ec6f9f764212c3e52275e480752d5c02ca49a Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Mon, 21 Nov 2016 09:58:23 +0100 Subject: doc: document options --- doc/beancount.txt | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/doc/beancount.txt b/doc/beancount.txt index 2a2f37c..7da58f3 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,6 +61,35 @@ COMMANDS *beancount-commands* nnoremap c :GetContext < +OPTIONS *beancount-options* + +*g:beancount_account_completion* + Sets the behaviour of the 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* @@ -77,15 +107,16 @@ 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 +< SYNTAX *beancount-syntax* -- cgit v1.2.3-2-gb3c3 From 11b166d9efb5e0f51a1fad42fe62e5c867d4a6db Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Mon, 21 Nov 2016 10:14:02 +0100 Subject: doc: document deoplete --- doc/beancount.txt | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/doc/beancount.txt b/doc/beancount.txt index 7da58f3..048a6c6 100644 --- a/doc/beancount.txt +++ b/doc/beancount.txt @@ -64,8 +64,7 @@ COMMANDS *beancount-commands* OPTIONS *beancount-options* *g:beancount_account_completion* - Sets the behaviour of the completion. See |beancount-completion|. - Can be either 'default' or 'chunks'. + See |beancount-completion|. Can be either 'default' or 'chunks'. Default value: 'default' @@ -94,10 +93,17 @@ OPTIONS *beancount-options* 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`. @@ -117,6 +123,12 @@ 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* -- cgit v1.2.3-2-gb3c3 From 81e9f05e3a1eac547813b7d80bf7417f38be8346 Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Mon, 21 Nov 2016 10:21:57 +0100 Subject: deoplete: use b:beancount_root --- autoload/beancount.vim | 14 +++++++------- rplugin/python3/deoplete/sources/beancount.py | 2 +- 2 files changed, 8 insertions(+), 8 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/rplugin/python3/deoplete/sources/beancount.py b/rplugin/python3/deoplete/sources/beancount.py index 4618105..f595a54 100644 --- a/rplugin/python3/deoplete/sources/beancount.py +++ b/rplugin/python3/deoplete/sources/beancount.py @@ -54,7 +54,7 @@ class Source(Base): payees = set() tags = set() if HAS_BEANCOUNT: - entries, _, _ = load_file(self.vim.eval("expand('%')")) + entries, _, _ = load_file(self.vim.eval("beancount#get_root()")) else: entries = [] -- cgit v1.2.3-2-gb3c3