summaryrefslogtreecommitdiffstats
path: root/cli/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/main.rs')
-rw-r--r--cli/src/main.rs37
1 files changed, 18 insertions, 19 deletions
diff --git a/cli/src/main.rs b/cli/src/main.rs
index 12325e2..e405e48 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -1,5 +1,6 @@
use chrono::naive::NaiveDate;
use rust_decimal::Decimal;
+use std::cmp::Ordering;
use std::path::PathBuf;
use std::str::FromStr;
use structopt::clap::AppSettings;
@@ -141,46 +142,44 @@ fn main() {
if sort.is_empty() {
transactions.sort_by_key(|t| t.date);
} else {
- match &sort[0] {
- SortTarget::Amount => transactions.sort_by_key(|t| t.amount),
- SortTarget::Date => transactions.sort_by_key(|t| t.date),
- }
- for i in 1..sort.len() {
- //TODO This won't work with 3+ sorts in case key 2 are equal across a key 1
- // border. We need to pass the earlier buckets for later sorts as well.
- // `Vec<range>`?
- inner_sort_by(&mut transactions, sort_by_func(&sort[i-1]), sort_by_func(&sort[i]));
- }
+ let mut sorts: Vec<_> = sort.iter().map(sort_by_func).collect();
+ inner_sort_by(&mut transactions, &mut sorts);
}
println!("{}", Table::new(transactions).with(Style::psql()));
}
}
}
-fn sort_by_func(sort: &SortTarget) -> impl FnMut(&&Transaction, &&Transaction) -> std::cmp::Ordering {
+fn sort_by_func(sort: &SortTarget) -> impl FnMut(&&Transaction, &&Transaction) -> Ordering {
match sort {
SortTarget::Amount => |t1: &&Transaction, t2: &&Transaction| t1.amount.cmp(&t2.amount),
SortTarget::Date => |t1: &&Transaction, t2: &&Transaction| t1.date.cmp(&t2.date),
}
}
-fn inner_sort_by<T, F>(v: &mut [T], mut outer_cmp: F, mut inner_cmp: F)
+fn inner_sort_by<T, F>(v: &mut [T], cmps: &mut [F])
where
- F: FnMut(&T, &T) -> std::cmp::Ordering,
+ F: FnMut(&T, &T) -> Ordering,
{
// Early out
- if v.len() < 2 {
+ if v.len() < 2 || cmps.is_empty() {
return;
}
+ v.sort_by(&mut cmps[0]);
+
+ let mut ranges = Vec::new();
let mut lower = 0; // Lower bound of current equal range
for i in 0..v.len() {
- if outer_cmp(&v[i], &v[lower]) != std::cmp::Ordering::Equal {
- let upper = i;
- if upper - lower > 1 {
- v[lower..upper].sort_by(&mut inner_cmp);
- }
+ if cmps[0](&v[i], &v[lower]) != Ordering::Equal {
+ ranges.push(lower..i);
lower = i;
}
}
+
+ if cmps.len() != 1 {
+ for range in ranges {
+ inner_sort_by(&mut v[range], &mut cmps[1..]);
+ }
+ }
}