summary history branches tags files
commit:dc5673995bfcb9d7769f8145a63909b3337026b8
author:Trevor Bentley
committer:Trevor Bentley
date:Thu Aug 29 03:43:50 2024 +0200
parents:abbf04160357f2d715fbfdcc507dc36ef99b6c89
add org-mode export with formulas
diff --git a/src/main.rs b/src/main.rs
line changes: +69/-4
index 692476c..276bcbc
--- a/src/main.rs
+++ b/src/main.rs
@@ -62,9 +62,9 @@ struct CalcArgs {
     #[arg(short, long)]
     csv: bool,
 
-    /// Output CSV with formulas instead of values
+    /// Output tables with formulas instead of values
     #[arg(long)]
-    csv_formulas: bool,
+    formulas: bool,
 
     /// Output CSV without header row and column
     #[arg(long)]
@@ -247,6 +247,17 @@ impl FstopEntry {
             _ => format!("={} * POWER({}, {} * {} + {} * {}){}", cell, self.growth(), self.multiplier(), self.frac.denom(), self.frac.sign, self.frac.modulo(), rel_str),
         }
     }
+    pub fn org_formula_str(&self, cell: String, relative: bool) -> String {
+        let growth = self.base * self.growth().powf(self.multiplier() * self.frac.denominator + self.frac.sign * self.frac.modulo());
+        let rel_str = match relative {
+            true => format!(" - {}", cell),
+            _ => format!(""),
+        };
+        match growth.is_nan() {
+            true => format!("{}{}", self.base, rel_str),
+            _ => format!("{}*{}**({}*{}+{}*{}){}", cell, self.growth(), self.multiplier(), self.frac.denom(), self.frac.sign, self.frac.modulo(), rel_str),
+        }
+    }
 }
 
 // generate a table of all f-stop fractions and their calculated times
@@ -366,6 +377,57 @@ fn fstop_table_org(col_steps: &Vec<Fraction>, row_steps: &Vec<Fraction>, table: 
     println!("|-");
 }
 
+// print an f-stop table in org-mode format
+fn fstop_table_formula_org(col_steps: &Vec<Fraction>, row_steps: &Vec<Fraction>, table: &Vec<FstopEntry>, cli: &CalcArgs) {
+    let col_idx = match cli.csv_skip_header { true => (col_steps.len() / 2) + 1, _ => (col_steps.len() / 2) + 2 };
+    let row_idx = match cli.csv_skip_header { true => (row_steps.len() / 2) + 1, _ => (row_steps.len() / 2) + 2 };
+
+    println!("|-");
+    print!("|");
+    if !cli.csv_skip_header {
+        print!(" |");
+        for col_frac in col_steps {
+            print!(" {} |", col_frac.offset_str(0, true));
+        }
+        println!();
+        println!("|-");
+    }
+    let mut tblfmt: Vec<String> = vec!();
+    for (row, row_frac) in row_steps.iter().enumerate() {
+        print!("|");
+        if !cli.csv_skip_header {
+            print!(" {} |", row_frac.offset_str(0, true));
+        }
+        for (col, _col_frac) in col_steps.iter().enumerate() {
+            let org_row = match cli.csv_skip_header { false => row + 2, _ => row + 1};
+            let org_col = match cli.csv_skip_header { false => col + 2, _ => col + 1};
+
+            match col == col_steps.len() / 2 {
+                true => match row == row_steps.len() / 2 {
+                    // middle column and middle row == base point, insert literal value
+                    true => print!(" {} |", table[row*col_steps.len() + col].str(cli.precision(), false)),
+                    false => {
+                        // make a new entry relative to the row offset
+                        let entry = FstopEntry::new(table[row*col_steps.len() + col].base, row_frac.num(), row_frac.denom());
+                        // base everything around the center-most field
+                        let base_cell = format!("@{}${}", row_idx, col_idx);
+                        print!(" |");
+                        tblfmt.push(format!("@{}${}={};%.{}f", org_row, org_col, entry.org_formula_str(base_cell, cli.relative), cli.precision()));
+                    },
+                },
+                false => {
+                    let base_cell = format!("@{}${}", row + match cli.csv_skip_header { true => 1, _ => 2}, col_idx);
+                    print!(" |");
+                    tblfmt.push(format!("@{}${}={};%.{}f", org_row, org_col, table[row*col_steps.len() + col].org_formula_str(base_cell, cli.relative), cli.precision()));
+                },
+            }
+        }
+        println!();
+    }
+    println!("|-");
+    println!("#+TBLFM: {}", tblfmt.join("::"));
+}
+
 // print a single-rowed f-stop table for the terminal
 fn fstop_table_print_row(col_steps: &Vec<Fraction>, table: &Vec<FstopEntry>, cli: &CalcArgs) {
     for idx in 0..col_steps.len() {
@@ -404,8 +466,11 @@ fn main() {
             let (col_steps, row_steps, table) = fstop_table(&cli);
             match row_steps.len() {
                 1 => fstop_table_print_row(&col_steps, &table, &cli),
-                _ => match cli.csv_formulas {
-                    true => fstop_table_formula_csv(&col_steps, &row_steps, &table, &cli),
+                _ => match cli.formulas {
+                    true => match cli.org {
+                        true => fstop_table_formula_org(&col_steps, &row_steps, &table, &cli),
+                        _ => fstop_table_formula_csv(&col_steps, &row_steps, &table, &cli),
+                    },
                     _ => match cli.org {
                         true => fstop_table_org(&col_steps, &row_steps, &table, &cli),
                         _ => fstop_table_csv(&col_steps, &row_steps, &table, &cli),