From 1437e782228dd649ee922fb3fb54c2b9a2b5052a Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Wed, 8 Mar 2017 23:35:51 -0300 Subject: deoplete: improve account completion; fix bug Don't try to complete for accounts in all places, only after the appropriate keywords or at the start of a line. Also initialize the "cache" using a defaultdict as to not get errors when the completions are accessed before the file is loaded. --- rplugin/python3/deoplete/sources/beancount.py | 37 +++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/rplugin/python3/deoplete/sources/beancount.py b/rplugin/python3/deoplete/sources/beancount.py index c21c057..dcc6a27 100644 --- a/rplugin/python3/deoplete/sources/beancount.py +++ b/rplugin/python3/deoplete/sources/beancount.py @@ -1,3 +1,4 @@ +import collections import re from deoplete.source.base import Base @@ -9,8 +10,10 @@ try: except ImportError: HAS_BEANCOUNT = False -DIRECTIVES = ['open', 'close', 'commodity', 'txn', 'balance', 'pad', 'note', - 'document', 'price', 'event', 'query', 'custom'] +DIRECTIVES = [ + 'open', 'close', 'commodity', 'txn', 'balance', 'pad', 'note', 'document', + 'price', 'event', 'query', 'custom' +] class Source(Base): @@ -22,6 +25,7 @@ class Source(Base): self.mark = '[bc]' self.filetypes = ['beancount'] self.min_pattern_length = 0 + self.attributes = collections.defaultdict(list) def on_init(self, context): if not HAS_BEANCOUNT: @@ -35,18 +39,29 @@ class Source(Base): return m.start() if m else -1 def gather_candidates(self, context): + attrs = self.attributes if re.match(r'^\d{4}[/-]\d\d[/-]\d\d \w*$', context['input']): return [{'word': x, 'kind': 'directive'} for x in DIRECTIVES] + # line that starts with whitespace (-> accounts) + if re.match(r'^(\s)+\w+$', context['input']): + return [{'word': x, 'kind': 'account'} for x in attrs['accounts']] + # directive followed by account + if re.match(r'(balance|document|note|open|close|pad(\s\S*)?)\s\w+$', + context['input']): + return [{'word': x, 'kind': 'account'} for x in attrs['accounts']] if not context['complete_str']: return [] first = context['complete_str'][0] if first == '#': - return [{'word': '#' + w, 'kind': 'tag'} for w in self._tags] + return [{'word': '#' + w, 'kind': 'tag'} for w in attrs['tags']] elif first == '^': - return [{'word': '^' + w, 'kind': 'link'} for w in self._links] + return [{'word': '^' + w, 'kind': 'link'} for w in attrs['links']] elif first == '"': - return [{'word': '"{}"'.format(w), 'kind': 'payee'} for w in self._payees] - return [{'word': x, 'kind': 'account'} for x in self._accounts] + return [{ + 'word': '"{}"'.format(w), + 'kind': 'payee' + } for w in attrs['payees']] + return [] def __make_cache(self, context): accounts = set() @@ -69,7 +84,9 @@ class Source(Base): 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) + self.attributes = { + 'accounts': sorted(accounts), + 'links': sorted(links), + 'payees': sorted(payees), + 'tags': sorted(tags), + } -- cgit v1.2.3-2-gb3c3 From e72ec57a6f79ca72dfebdcb4e49ea753a8806d7d Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Wed, 8 Mar 2017 23:46:48 -0300 Subject: deoplete: commodity completion Match commodities after numbers. Close #33. --- rplugin/python3/deoplete/sources/beancount.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/rplugin/python3/deoplete/sources/beancount.py b/rplugin/python3/deoplete/sources/beancount.py index dcc6a27..f149ff0 100644 --- a/rplugin/python3/deoplete/sources/beancount.py +++ b/rplugin/python3/deoplete/sources/beancount.py @@ -46,9 +46,16 @@ class Source(Base): if re.match(r'^(\s)+\w+$', context['input']): return [{'word': x, 'kind': 'account'} for x in attrs['accounts']] # directive followed by account - if re.match(r'(balance|document|note|open|close|pad(\s\S*)?)\s\w+$', - context['input']): + if re.search(r'(balance|document|note|open|close|pad(\s\S*)?)\s\w+$', + context['input']): return [{'word': x, 'kind': 'account'} for x in attrs['accounts']] + # commodity after number + if re.search(r'([0-9]+|[0-9][0-9,]+[0-9])(\.[0-9]*)?\s\w+', + context['input']): + return [{ + 'word': x, + 'kind': 'commodity' + } for x in attrs['commodities']] if not context['complete_str']: return [] first = context['complete_str'][0] @@ -64,14 +71,15 @@ class Source(Base): return [] def __make_cache(self, context): + if not HAS_BEANCOUNT: + return + + entries, _, options = load_file(self.vim.eval("beancount#get_root()")) + 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): @@ -86,6 +94,7 @@ class Source(Base): self.attributes = { 'accounts': sorted(accounts), + 'commodities': options['commodities'], 'links': sorted(links), 'payees': sorted(payees), 'tags': sorted(tags), -- cgit v1.2.3-2-gb3c3 From 6357da05215fa95da4049384886e61be817efa74 Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Thu, 9 Mar 2017 17:46:09 -0300 Subject: deoplete: event completion Close #34. --- rplugin/python3/deoplete/sources/beancount.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/rplugin/python3/deoplete/sources/beancount.py b/rplugin/python3/deoplete/sources/beancount.py index f149ff0..ae6f6e1 100644 --- a/rplugin/python3/deoplete/sources/beancount.py +++ b/rplugin/python3/deoplete/sources/beancount.py @@ -5,7 +5,7 @@ from deoplete.source.base import Base try: from beancount.loader import load_file - from beancount.core.data import Open, Transaction + from beancount.core import data HAS_BEANCOUNT = True except ImportError: HAS_BEANCOUNT = False @@ -24,6 +24,7 @@ class Source(Base): self.name = 'beancount' self.mark = '[bc]' self.filetypes = ['beancount'] + self.rank = 500 self.min_pattern_length = 0 self.attributes = collections.defaultdict(list) @@ -49,6 +50,12 @@ class Source(Base): if re.search(r'(balance|document|note|open|close|pad(\s\S*)?)\s\w+$', context['input']): return [{'word': x, 'kind': 'account'} for x in attrs['accounts']] + # events + if re.search(r'event "[^"]*$', context['input']): + return [{ + 'word': '"{}"'.format(x), + 'kind': 'event' + } for x in attrs['events']] # commodity after number if re.search(r'([0-9]+|[0-9][0-9,]+[0-9])(\.[0-9]*)?\s\w+', context['input']): @@ -77,23 +84,27 @@ class Source(Base): entries, _, options = load_file(self.vim.eval("beancount#get_root()")) accounts = set() + events = set() links = set() payees = set() tags = set() for entry in entries: - if isinstance(entry, Open): + if isinstance(entry, data.Open): accounts.add(entry.account) - elif isinstance(entry, Transaction): + elif isinstance(entry, data.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) + if isinstance(entry, data.Event): + events.add(entry.type) self.attributes = { 'accounts': sorted(accounts), + 'events': sorted(events), 'commodities': options['commodities'], 'links': sorted(links), 'payees': sorted(payees), -- cgit v1.2.3-2-gb3c3 From 65665b799b32541f70345b11896430498338075a Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Mon, 20 Mar 2017 13:45:39 -0300 Subject: deoplete: accounts can contain colons --- rplugin/python3/deoplete/sources/beancount.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rplugin/python3/deoplete/sources/beancount.py b/rplugin/python3/deoplete/sources/beancount.py index ae6f6e1..0194da3 100644 --- a/rplugin/python3/deoplete/sources/beancount.py +++ b/rplugin/python3/deoplete/sources/beancount.py @@ -44,11 +44,13 @@ class Source(Base): if re.match(r'^\d{4}[/-]\d\d[/-]\d\d \w*$', context['input']): return [{'word': x, 'kind': 'directive'} for x in DIRECTIVES] # line that starts with whitespace (-> accounts) - if re.match(r'^(\s)+\w+$', context['input']): + if re.match(r'^(\s)+[\w:]+$', context['input']): return [{'word': x, 'kind': 'account'} for x in attrs['accounts']] # directive followed by account - if re.search(r'(balance|document|note|open|close|pad(\s\S*)?)\s\w+$', - context['input']): + if re.search( + r'(balance|document|note|open|close|pad(\s[\w:]+)?)' + r'\s[\w:]+$', + context['input']): return [{'word': x, 'kind': 'account'} for x in attrs['accounts']] # events if re.search(r'event "[^"]*$', context['input']): @@ -57,7 +59,7 @@ class Source(Base): 'kind': 'event' } for x in attrs['events']] # commodity after number - if re.search(r'([0-9]+|[0-9][0-9,]+[0-9])(\.[0-9]*)?\s\w+', + if re.search(r'\s([0-9]+|[0-9][0-9,]+[0-9])(\.[0-9]*)?\s\w+$', context['input']): return [{ 'word': x, -- cgit v1.2.3-2-gb3c3