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(-)

(limited to 'rplugin/python3/deoplete')

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(-)

(limited to 'rplugin/python3/deoplete')

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(-)

(limited to 'rplugin/python3/deoplete')

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(-)

(limited to 'rplugin/python3/deoplete')

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