1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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)
|