aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock176
-rw-r--r--Cargo.toml2
-rw-r--r--src/bill.rs15
-rw-r--r--src/cli.rs97
4 files changed, 286 insertions, 4 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 02d2ef5..3beac18 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,6 +3,65 @@
version = 4
[[package]]
+name = "aho-corasick"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anstream"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
+
+[[package]]
+name = "anstyle-parse"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys",
+]
+
+[[package]]
name = "anyhow"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -50,6 +109,12 @@ dependencies = [
]
[[package]]
+name = "colorchoice"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
+
+[[package]]
name = "dirs"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -71,6 +136,29 @@ dependencies = [
]
[[package]]
+name = "env_filter"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "jiff",
+ "log",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -146,12 +234,42 @@ dependencies = [
]
[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
+
+[[package]]
name = "itoa"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
+name = "jiff"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359"
+dependencies = [
+ "jiff-static",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde_core",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "js-sys"
version = "0.3.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -222,8 +340,10 @@ dependencies = [
name = "mingling_core"
version = "0.1.4"
dependencies = [
+ "env_logger",
"just_fmt",
"just_template",
+ "log",
"once_cell",
"ron",
"serde",
@@ -252,6 +372,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
+name = "once_cell_polyfill"
+version = "1.70.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+
+[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -264,6 +390,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
+name = "portable-atomic"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618"
+dependencies = [
+ "portable-atomic",
+]
+
+[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -309,6 +450,35 @@ dependencies = [
]
[[package]]
+name = "regex"
+version = "1.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
+
+[[package]]
name = "ron"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -557,6 +727,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
name = "uuid"
version = "1.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 627fde0..f962729 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ name = "cobill"
path = "src/main.rs"
[dependencies]
-mingling = { path = "../mingling/mingling", features = ["full"] }
+mingling = { path = "../mingling/mingling", features = ["full", "debug"] }
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread" ] }
uuid = { version = "1", features = ["v4"] }
serde = { version = "1", features = ["derive"] }
diff --git a/src/bill.rs b/src/bill.rs
index 4b66554..291b759 100644
--- a/src/bill.rs
+++ b/src/bill.rs
@@ -235,4 +235,19 @@ impl Bills {
bills
}
+
+ pub fn get_members(&self) -> Vec<String> {
+ let mut members = std::collections::HashSet::new();
+
+ for item in self.items.values() {
+ members.insert(item.who_paid.to_string());
+ for who in &item.split {
+ members.insert(who.to_string());
+ }
+ }
+
+ let mut result: Vec<String> = members.into_iter().collect();
+ result.sort();
+ result
+ }
}
diff --git a/src/cli.rs b/src/cli.rs
index a39624f..71936cc 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -1,8 +1,8 @@
use std::{fs::create_dir_all, io::ErrorKind, path::PathBuf};
use mingling::{
- AnyOutput, Groupped,
- macros::{chain, dispatcher, gen_program, pack, r_println, renderer},
+ AnyOutput, Groupped, ShellContext, Suggest, SuggestItem,
+ macros::{chain, completion, dispatcher, gen_program, pack, r_println, renderer, suggest},
marker::NextProcess,
parser::Picker,
setup::GeneralRendererSetup,
@@ -52,6 +52,97 @@ dispatcher!("add", AddBillCommand => AddBillEntry);
dispatcher!("edit", EditCommand => EditEntry);
dispatcher!("ls", ListAllBillCommand => ListAllBillEntry);
+#[completion(AddBillEntry)]
+fn comp_add(ctx: &ShellContext) -> Suggest {
+ if ctx.filling_argument_first(["-p", "--paid"]) {
+ return suggest!();
+ }
+
+ if ctx.filling_argument_first(["-r", "--reason"]) {
+ return suggest!();
+ }
+
+ if ctx.previous_word == "add" {
+ return name_suggest(vec![]);
+ }
+
+ let mut found_for_arg = false;
+ let mut typed_names = Vec::new();
+
+ // Collect all names that have already been typed after -f/--for
+ let mut i = 0;
+ while i < ctx.word_index {
+ if ctx.all_words[i] == "-f" || ctx.all_words[i] == "--for" {
+ // Start collecting names after this flag
+ let mut j = i + 1;
+ while j < ctx.word_index && !ctx.all_words[j].starts_with('-') {
+ typed_names.push(ctx.all_words[j].clone());
+ j += 1;
+ }
+ found_for_arg = true;
+ }
+ i += 1;
+ }
+
+ if found_for_arg {
+ return name_suggest(typed_names);
+ }
+
+ if ctx.typing_argument() {
+ return suggest! {
+ "-p" : "Payment amount",
+ "--paid" : "Payment amount",
+ "-r" : "Payment reason",
+ "--reason" : "Payment reason",
+ "-f" : "Who to pay for",
+ "--for" : "Who to pay for",
+ }
+ .strip_typed_argument(ctx);
+ }
+ suggest!()
+}
+
+fn name_suggest(typed: Vec<String>) -> Suggest {
+ let members = read_bills().get_members();
+ let mut suggest = Suggest::new();
+ for member in members {
+ if !typed.contains(&member) {
+ suggest.insert(SuggestItem::Simple(member));
+ }
+ }
+ return suggest;
+}
+
+#[completion(ListAllBillEntry)]
+fn comp_ls(ctx: &ShellContext) -> Suggest {
+ if ctx.typing_argument() {
+ return suggest! {
+ "-O": "Output the bill optimized to the simplest result",
+ "--optimize": "Output the bill optimized to the simplest result"
+ };
+ }
+ suggest!()
+}
+
+#[completion(EditEntry)]
+fn comp_edit(ctx: &ShellContext) -> Suggest {
+ if ctx.filling_argument_first(["-e", "--editor"]) {
+ let mut suggest = Suggest::new();
+ for editor in ["vi", "vim", "nvim", "helix", "nano"] {
+ suggest.insert(SuggestItem::Simple(editor.to_string()));
+ }
+ return suggest;
+ }
+ if ctx.typing_argument() {
+ return suggest! {
+ "-e": "Specify editor to use",
+ "--editor": "Specify editor to use"
+ }
+ .strip_typed_argument(ctx);
+ }
+ suggest!()
+}
+
#[chain]
async fn do_clear_cmd(_prev: ClearAllBillEntry) -> NextProcess {
op_bills(|b| b.clear_items());
@@ -143,7 +234,7 @@ fn render_bills(prev: ResultBills) {
fn render_split_result(prev: ResultSplitResult) {
let mut table = SimpleTable::new(string_vec!["Who", "|", "Should Pay", "|", "To"]);
for ((who, to), paid) in prev.inner.final_result {
- table.push_item(string_vec![who, "|", paid, "|", to]);
+ table.push_item(string_vec![who, "->", paid, "->", to]);
}
r_println!("{}", table)
}