Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending auto-completion possibilities #31

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
"default": true,
"description": "Controls whether the auto completion list should include payee and narration fields."
},
"beancount.completeTransaction": {
"type": "boolean",
"default": true,
"description": "Controls whether the auto completion list should include whole transactions."
},
"beancount.mainBeanFile": {
"type": "string",
"default": "",
Expand Down
21 changes: 19 additions & 2 deletions pythonFiles/beancheck.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
''' load beancount file and print errors
'''
from datetime import date
from sys import argv
from beancount import loader
from beancount.core import flags
from beancount.core.data import Transaction, Open, Close
from beancount.core.display_context import Align
from beancount.core.realization import dump_balances, realize
from beancount.parser.printer import format_entry
import io
import json

Expand Down Expand Up @@ -34,6 +36,7 @@ def get_flag_metadata(thing):

entries, errors, options = loader.load_file(argv[1])
completePayeeNarration = "--payeeNarration" in argv
completeTransaction = "--transaction" in argv

error_list = [{"file": e.source['filename'], "line": e.source['lineno'], "message": e.message} for e in errors]

Expand All @@ -42,6 +45,8 @@ def get_flag_metadata(thing):
commodities = set()
payees = set()
narrations = set()
transactions = {}
lastTransactionDate = date.fromtimestamp(0)
tags = set()
links = set()
flagged_entries = []
Expand All @@ -50,17 +55,27 @@ def get_flag_metadata(thing):
if hasattr(entry, 'flag') and entry.flag == "!":
flagged_entries.append(get_flag_metadata(entry))
if isinstance(entry, Transaction):
lastTransactionDate = entry.date if entry.date > lastTransactionDate else lastTransactionDate
if completePayeeNarration:
payees.add(f'{entry.payee}')
payees.add(str(entry.payee))
if not entry.narration.startswith("(Padding inserted"):
if completePayeeNarration:
narrations.add(f'{entry.narration}')
narrations.add(str(entry.narration))
tags.update(entry.tags)
links.update(entry.links)
for posting in entry.postings:
commodities.add(posting.units.currency)
if hasattr(posting, 'flag') and posting.flag == "!":
flagged_entries.append(get_flag_metadata(posting))
if completeTransaction:
# Add transaction to dict (replace if already exists, i.e. newest transaction wins)
if entry.payee:
transaction_key = ' '.join([entry.flag, entry.payee, entry.narration])
else:
transaction_key = ' '.join([entry.flag, entry.narration])
transaction_value = format_entry(entry)
transaction_value = transaction_value.lstrip(entry.date.__str__()).lstrip()
transactions[transaction_key] = transaction_value
elif isinstance(entry, Open):
accounts[entry.account] = {
'open': entry.date.__str__(),
Expand Down Expand Up @@ -97,6 +112,8 @@ def get_flag_metadata(thing):
output['commodities'] = list(commodities)
output['payees'] = list(payees)
output['narrations'] = list(narrations)
output['transactions'] = transactions
output['lastTransactionDate'] = lastTransactionDate.isoformat()
output['tags'] = list(tags)
output['links'] = list(links)

Expand Down
74 changes: 69 additions & 5 deletions src/completer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ interface CompletionData {
commodities: string[];
payees: string[];
narrations: string[];
transactions: { [key: string]: string };
lastTransactionDate: string;
tags: string[];
links: string[];
}
Expand All @@ -36,6 +38,8 @@ export class Completer
payees: string[];
narrations: string[];
commodities: string[];
transactions: { [key: string]: string };
lastTransactionDate: string;
tags: string[];
links: string[];
wordPattern: RegExp;
Expand All @@ -47,6 +51,8 @@ export class Completer
this.payees = [];
this.narrations = [];
this.commodities = [];
this.transactions = {};
this.lastTransactionDate = '';
this.tags = [];
this.links = [];
this.wordPattern = new RegExp('[A-Za-z:]+\\S+|"([^\\\\"]|\\\\")*"');
Expand All @@ -69,6 +75,8 @@ export class Completer
this.commodities = data.commodities;
this.payees = data.payees;
this.narrations = data.narrations;
this.transactions = data.transactions;
this.lastTransactionDate = data.lastTransactionDate;
this.tags = data.tags;
this.links = data.links;
}
Expand Down Expand Up @@ -176,13 +184,35 @@ export class Completer
(today.getMonth() + 1).toString();
const date =
(today.getDate() < 10 ? '0' : '') + today.getDate().toString();
const dateString = year + '-' + month + '-' + date;

const dateStringToday = year + '-' + month + '-' + date;
const itemToday = new CompletionItem(
dateString,
dateStringToday,
CompletionItemKind.Event
);
itemToday.documentation = 'Today';

const dateStringYear = year + '-';
const itemYear = new CompletionItem(
dateStringYear,
CompletionItemKind.Event
);
itemToday.documentation = 'today';
resolve([itemToday]);
itemYear.documentation = 'This year';

const dateStringLastTransactionDate = this.lastTransactionDate;
const itemLastTransactionDate = new CompletionItem(
dateStringLastTransactionDate,
CompletionItemKind.Event
);
itemLastTransactionDate.documentation = 'Last transaction';

const dateStringLastTransactionMonth = this.lastTransactionDate.slice(0, -2);
const itemLastTransactionMonth = new CompletionItem(
dateStringLastTransactionMonth,
CompletionItemKind.Event
);

resolve([itemToday, itemYear, itemLastTransactionDate, itemLastTransactionMonth]);
return;
} else if (
triggerCharacter === '"' &&
Expand All @@ -193,6 +223,7 @@ export class Completer
countOccurrences(textBefore, /\"/g) -
countOccurrences(textBefore, /\\"/g);
if (r != null && numQuotes % 2 === 1) {

const insertItemWithLetters = (
list: CompletionItem[],
text: string,
Expand All @@ -215,6 +246,7 @@ export class Completer
list.push(new CompletionItem(text, kind));
}
};

const list: CompletionItem[] = [];
if (numQuotes === 1) {
this.payees.forEach((payee, i, a) => {
Expand Down Expand Up @@ -271,9 +303,41 @@ export class Completer
});
resolve(list);
return;
} else if (
vscode.workspace.getConfiguration('beancount')['completeTransaction'] &&
textBefore.match(/([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/)
) { // Match a date at the string beginning

const instertTransactionItem = (list: CompletionItem[], key: string, transactionText: string) => {
let findOne = false;
const completionItemKind = CompletionItemKind.Value;

for (const inputMethod of this.inputMethods) {
const letters = inputMethod.getLetterRepresentation(key);
if (letters.length > 0) {
findOne = true;
const item = new CompletionItem(
letters + '(' + key + ')',
completionItemKind
);
item.insertText = transactionText;
list.push(item);
}
}
if (!findOne) {
const item = new CompletionItem(key, completionItemKind);
item.insertText = transactionText;
list.push(item);
}
};

const list: CompletionItem[] = [];
for (const key in this.transactions) {
instertTransactionItem(list, key, this.transactions[key]);
}
resolve(list);
}
}
resolve([]);
});
}
}
8 changes: 5 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,14 @@ export class Extension {
this.logger.appendLine('find no valid bean files.');
return;
}
const extConfig = vscode.workspace.getConfiguration('beancount');
const pyArgs = [checkpy, mainBeanFile];
if (
vscode.workspace.getConfiguration('beancount')['completePayeeNarration']
) {
if (extConfig['completePayeeNarration']) {
pyArgs.push('--payeeNarration');
}
if (extConfig['completeTransaction']) {
pyArgs.push('--transaction');
}
this.logger.appendLine(
`running ${python3Path} ${pyArgs} to refresh data...`
);
Expand Down