#[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)]
_ => 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
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() {
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),