Compare commits
5 Commits
v0.1.0-rc1
...
v0.1.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
| 04058a48f9 | |||
| 37411bf747 | |||
| 5e90fbe0f7 | |||
| 1350e875c5 | |||
| d4f6efd1c0 |
1086
Cargo.lock
generated
1086
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
14
Cargo.toml
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "improvise"
|
||||
version = "0.1.0-rc1"
|
||||
edition = "2021"
|
||||
version = "0.1.0-rc2"
|
||||
edition = "2024"
|
||||
description = "Terminal pivot-table modeling in the spirit of Lotus Improv"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/fiddlerwoaroof/improvise"
|
||||
@ -15,17 +15,17 @@ name = "improvise"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
ratatui = "0.29"
|
||||
crossterm = "0.28"
|
||||
ratatui = "0.30"
|
||||
crossterm = "0.29"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
anyhow = "1"
|
||||
thiserror = "1"
|
||||
thiserror = "2"
|
||||
indexmap = { version = "2", features = ["serde"] }
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
flate2 = "1"
|
||||
unicode-width = "0.2"
|
||||
dirs = "5"
|
||||
unicode-width = "^0.2"
|
||||
dirs = "6"
|
||||
csv = "1"
|
||||
clap = { version = "4.6.0", features = ["derive"] }
|
||||
enum_dispatch = "0.3.13"
|
||||
|
||||
18
flake.lock
generated
18
flake.lock
generated
@ -247,11 +247,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1774709303,
|
||||
"narHash": "sha256-D3Q07BbIA2KnTcSXIqqu9P586uWxN74zNoCH3h2ESHg=",
|
||||
"lastModified": 1775710090,
|
||||
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8110df5ad7abf5d4c0f6fb0f8f978390e77f9685",
|
||||
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -263,11 +263,11 @@
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1774794121,
|
||||
"narHash": "sha256-gih24b728CK8twDNU7VX9vVYK2tLEXvy9gm/GKq2VeE=",
|
||||
"lastModified": 1744536153,
|
||||
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c397ef6af68c018462d786e1b65384abc472a907",
|
||||
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -316,11 +316,11 @@
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1774926780,
|
||||
"narHash": "sha256-JMdDYn0F+swYBILlpCeHDbCSyzqkeSGNxZ/Q5J584jM=",
|
||||
"lastModified": 1775877051,
|
||||
"narHash": "sha256-wpSQm2PD/w4uRo2wb8utk0b5hOBkkg/CZ1xICY+qB7M=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "962a0934d0e32f42d1b5e49186f9595f9b178d2d",
|
||||
"rev": "08b4f3633471874c8894632ade1b78d75dbda002",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@ -140,7 +140,7 @@ impl ImportPipeline {
|
||||
}
|
||||
|
||||
// Create derived date-component categories
|
||||
for (_, _, _, ref derived_name) in &date_extractions {
|
||||
for (_, _, _, derived_name) in &date_extractions {
|
||||
model.add_category(derived_name)?;
|
||||
}
|
||||
|
||||
@ -176,7 +176,7 @@ impl ImportPipeline {
|
||||
coords.push((cat_proposal.field.clone(), v.clone()));
|
||||
|
||||
// Extract date components from this field's value
|
||||
for (field, fmt, comp, ref derived_name) in &date_extractions {
|
||||
for (field, fmt, comp, derived_name) in &date_extractions {
|
||||
if *field == cat_proposal.field {
|
||||
if let Some(derived_val) = extract_date_component(&v, fmt, *comp) {
|
||||
if let Some(cat) = model.category_mut(derived_name) {
|
||||
|
||||
@ -371,7 +371,7 @@ fn run_headless_script(script_path: &PathBuf, file: &Option<PathBuf>) -> Result<
|
||||
// ── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
fn get_initial_model(file_path: &Option<PathBuf>) -> Result<Model> {
|
||||
if let Some(ref path) = file_path {
|
||||
if let Some(path) = file_path {
|
||||
if path.exists() {
|
||||
let mut m = persistence::load(path)
|
||||
.with_context(|| format!("Failed to load {}", path.display()))?;
|
||||
|
||||
@ -2118,7 +2118,7 @@ mod parser_edge_cases {
|
||||
// files. The generator and parser share a single source of truth: the grammar.
|
||||
|
||||
#[cfg(test)]
|
||||
mod gen {
|
||||
mod generator {
|
||||
use pest_meta::ast::{Expr, RuleType};
|
||||
use pest_meta::parser;
|
||||
use proptest::prelude::*;
|
||||
@ -2253,15 +2253,15 @@ mod gen {
|
||||
// Use random bytes as entropy for choices in the grammar walk
|
||||
prop::collection::vec(any::<u8>(), 64..=256).prop_map(|choices| {
|
||||
let rules = load_grammar();
|
||||
let mut gen = Gen::new(&rules, choices);
|
||||
gen.generate("file")
|
||||
let mut g = Gen::new(&rules, choices);
|
||||
g.generate("file")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod grammar_prop_tests {
|
||||
use super::{format_md, gen, parse_md};
|
||||
use super::{format_md, generator, parse_md};
|
||||
use proptest::prelude::*;
|
||||
|
||||
proptest! {
|
||||
@ -2269,7 +2269,7 @@ mod grammar_prop_tests {
|
||||
|
||||
/// parse(generate()) — every generated file parses without error.
|
||||
#[test]
|
||||
fn generated_file_parses(file in gen::improv_file()) {
|
||||
fn generated_file_parses(file in generator::improv_file()) {
|
||||
let result = parse_md(&file);
|
||||
prop_assert!(result.is_ok(),
|
||||
"Generated file failed to parse:\n{}\nError: {}",
|
||||
@ -2278,7 +2278,7 @@ mod grammar_prop_tests {
|
||||
|
||||
/// parse(print(parse(generate()))) — round-trip through format is stable.
|
||||
#[test]
|
||||
fn generated_file_roundtrips(file in gen::improv_file()) {
|
||||
fn generated_file_roundtrips(file in generator::improv_file()) {
|
||||
let result1 = parse_md(&file);
|
||||
// Skip inputs that don't parse (the grammar walk may produce
|
||||
// degenerate inputs like empty model names)
|
||||
|
||||
@ -121,7 +121,7 @@ impl View {
|
||||
pub fn categories_on(&self, axis: Axis) -> Vec<&str> {
|
||||
self.category_axes
|
||||
.iter()
|
||||
.filter(|(_, &a)| a == axis)
|
||||
.filter(|&(_, &a)| a == axis)
|
||||
.map(|(n, _)| n.as_str())
|
||||
.collect()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user