Skip to content

Commit 43ae1d2

Browse files
committed
fix: payee and narration bugs
1 parent 56c7278 commit 43ae1d2

File tree

2 files changed

+993
-31
lines changed

2 files changed

+993
-31
lines changed

crates/lsp/src/beancount_data.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub struct FlaggedEntry {
1717
#[derive(Clone, Debug)]
1818
pub struct BeancountData {
1919
accounts: Vec<String>,
20+
payees: Vec<String>,
2021
narration: Vec<String>,
2122
pub flagged_entries: Vec<FlaggedEntry>,
2223
tags: Vec<String>,
@@ -27,6 +28,7 @@ pub struct BeancountData {
2728
impl BeancountData {
2829
pub fn new(tree: &tree_sitter::Tree, content: &ropey::Rope) -> Self {
2930
let mut accounts = vec![];
31+
let mut payees = vec![];
3032
let mut narration = vec![];
3133
let mut flagged_entries = vec![];
3234

@@ -55,17 +57,41 @@ impl BeancountData {
5557
accounts.push(account);
5658
}
5759

58-
// Update narration with frequency tracking
59-
tracing::debug!("beancount_data:: get narration nodes");
60+
// Update payees and narration with frequency tracking
61+
tracing::debug!("beancount_data:: get payee and narration nodes");
6062
let transactions = tree
6163
.root_node()
6264
.children(&mut cursor)
6365
.filter(|c| c.kind() == "transaction")
6466
.collect::<Vec<_>>();
6567

68+
let mut payee_count: std::collections::HashMap<String, usize> =
69+
std::collections::HashMap::new();
6670
let mut narration_count: std::collections::HashMap<String, usize> =
6771
std::collections::HashMap::new();
6872
for transaction in transactions {
73+
// When there's a payee field (two strings), use it
74+
if let Some(payee_node) = transaction.child_by_field_name("payee") {
75+
let payee_text = text_for_tree_sitter_node(content, &payee_node)
76+
.trim()
77+
.to_string();
78+
if !payee_text.is_empty() {
79+
*payee_count.entry(payee_text).or_insert(0) += 1;
80+
}
81+
}
82+
// When there's only narration (one string), also add it to payees
83+
// since semantically it often represents the payee
84+
else if let Some(narration_node) = transaction.child_by_field_name("narration") {
85+
let narration_text = text_for_tree_sitter_node(content, &narration_node)
86+
.trim()
87+
.to_string();
88+
if !narration_text.is_empty() {
89+
// Add single-string transactions to payees for completion
90+
*payee_count.entry(narration_text.clone()).or_insert(0) += 1;
91+
}
92+
}
93+
94+
// Always collect narration for narration completions
6995
if let Some(narration_node) = transaction.child_by_field_name("narration") {
7096
let narration_text = text_for_tree_sitter_node(content, &narration_node)
7197
.trim()
@@ -76,6 +102,14 @@ impl BeancountData {
76102
}
77103
}
78104

105+
tracing::debug!("beancount_data:: update payees");
106+
payees.clear();
107+
108+
// Sort by frequency (most used first), then alphabetically
109+
let mut payee_vec: Vec<(String, usize)> = payee_count.into_iter().collect();
110+
payee_vec.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| a.0.cmp(&b.0)));
111+
payees = payee_vec.into_iter().map(|(text, _)| text).collect();
112+
79113
tracing::debug!("beancount_data:: update narration");
80114
narration.clear();
81115

@@ -235,6 +269,7 @@ impl BeancountData {
235269

236270
Self {
237271
accounts,
272+
payees,
238273
narration,
239274
flagged_entries,
240275
tags,
@@ -247,6 +282,10 @@ impl BeancountData {
247282
self.accounts.clone()
248283
}
249284

285+
pub fn get_payees(&self) -> Vec<String> {
286+
self.payees.clone()
287+
}
288+
250289
pub fn get_narration(&self) -> Vec<String> {
251290
self.narration.clone()
252291
}

0 commit comments

Comments
 (0)