Start work on formatting options
This commit is contained in:
parent
062cd97609
commit
85ea8ca776
11
src/calc.rs
11
src/calc.rs
@ -333,7 +333,7 @@ impl<'a> Calculator<'a> {
|
||||
push: OpArgs::Unary(f),
|
||||
})
|
||||
}
|
||||
fn pop(&mut self) -> CalculatorResult<f64> {
|
||||
pub fn pop(&mut self) -> CalculatorResult<f64> {
|
||||
let f = self.checked_get(0)?;
|
||||
self.direct_state_change(CalculatorStateChange {
|
||||
pop: OpArgs::Unary(f),
|
||||
@ -341,6 +341,15 @@ impl<'a> Calculator<'a> {
|
||||
})?;
|
||||
Ok(f)
|
||||
}
|
||||
pub fn pop_usize(&mut self) -> CalculatorResult<usize> {
|
||||
let f = self.checked_get(0)?;
|
||||
let ret = usize::from(f as usize);
|
||||
self.direct_state_change(CalculatorStateChange {
|
||||
pop: OpArgs::Unary(f),
|
||||
push: OpArgs::None,
|
||||
})?;
|
||||
Ok(ret)
|
||||
}
|
||||
pub fn op(&mut self, op: CalculatorOperation) -> CalculatorResult<()> {
|
||||
// Dup is special -- don't actually run it if l needs to be flushed
|
||||
if self.flush_l()? {
|
||||
|
114
src/main.rs
114
src/main.rs
@ -27,7 +27,18 @@ struct Dimensions {
|
||||
height: u16,
|
||||
}
|
||||
|
||||
enum DisplayMode {
|
||||
Default(Option<char>),
|
||||
Scientific(usize),
|
||||
Engineering,
|
||||
}
|
||||
|
||||
struct AppSettings {
|
||||
display_mode: DisplayMode,
|
||||
}
|
||||
|
||||
enum AppState {
|
||||
AppSettings,
|
||||
Calculator,
|
||||
Help,
|
||||
}
|
||||
@ -37,6 +48,7 @@ struct App<'a> {
|
||||
error_msg: Option<String>,
|
||||
state: AppState,
|
||||
current_macro: Option<char>,
|
||||
app_settings: AppSettings,
|
||||
}
|
||||
|
||||
impl<'a> Default for App<'a> {
|
||||
@ -46,6 +58,9 @@ impl<'a> Default for App<'a> {
|
||||
error_msg: None,
|
||||
state: AppState::Calculator,
|
||||
current_macro: None,
|
||||
app_settings: AppSettings {
|
||||
display_mode: DisplayMode::Default(None),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,13 +95,24 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
Span::raw("Error: "),
|
||||
Span::styled(e, Style::default().add_modifier(Modifier::RAPID_BLINK)),
|
||||
],
|
||||
(None, AppState::Calculator) => vec![
|
||||
Span::raw("Press "),
|
||||
Span::styled("q", Style::default().add_modifier(Modifier::BOLD)),
|
||||
Span::raw(" to exit, "),
|
||||
Span::styled("h", Style::default().add_modifier(Modifier::BOLD)),
|
||||
Span::raw(" for help"),
|
||||
],
|
||||
(None, AppState::Calculator) => {
|
||||
// TODO: There has to be a better way than making strings each time
|
||||
let display_mode_str = match &app.app_settings.display_mode {
|
||||
DisplayMode::Default(None) => String::from("[d]"),
|
||||
DisplayMode::Default(Some(c)) => format!("[d({})]", c),
|
||||
DisplayMode::Scientific(p) => format!("[s({})]", p),
|
||||
DisplayMode::Engineering => String::from("[e]"),
|
||||
};
|
||||
|
||||
vec![
|
||||
Span::raw("Press "),
|
||||
Span::styled("q", Style::default().add_modifier(Modifier::BOLD)),
|
||||
Span::raw(" to exit, "),
|
||||
Span::styled("h", Style::default().add_modifier(Modifier::BOLD)),
|
||||
Span::raw(" for help - "),
|
||||
Span::raw(display_mode_str),
|
||||
]
|
||||
}
|
||||
(None, _) => vec![
|
||||
Span::raw("Press "),
|
||||
Span::styled("<esc>", Style::default().add_modifier(Modifier::BOLD)),
|
||||
@ -106,7 +132,16 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
.enumerate()
|
||||
.rev()
|
||||
.map(|(i, m)| {
|
||||
let content = vec![Spans::from(Span::raw(format!("{}: {}", i, m)))];
|
||||
let content = vec![Spans::from(Span::raw(
|
||||
match &app.app_settings.display_mode {
|
||||
DisplayMode::Default(None) => format!("{:>2}: {}", i, *m),
|
||||
DisplayMode::Default(Some(c)) => fmt_separated(i, *m, *c),
|
||||
DisplayMode::Scientific(precision) => fmt_scientific(i, *m, *precision),
|
||||
DisplayMode::Engineering => {
|
||||
format!("{:>2}: {}", i, m)
|
||||
}
|
||||
},
|
||||
))];
|
||||
ListItem::new(content)
|
||||
})
|
||||
.collect();
|
||||
@ -134,6 +169,22 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
);
|
||||
|
||||
match (&app.state, app.calculator.get_state()) {
|
||||
(AppState::AppSettings, _) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
title: "App Settings",
|
||||
msg: "\
|
||||
d => Default\n\
|
||||
, => Default (comma separated)\n\
|
||||
s => Scientific\n\
|
||||
S => Scientific (stack precision)\n\
|
||||
e => Engineering\n\
|
||||
E => Engineering (stack precision)\n\
|
||||
",
|
||||
},
|
||||
f,
|
||||
);
|
||||
}
|
||||
(AppState::Help, _) => {
|
||||
draw_clippy_rect(
|
||||
ClippyRectangle {
|
||||
@ -248,6 +299,9 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<bool
|
||||
Key::Char('h') => {
|
||||
app.state = AppState::Help;
|
||||
}
|
||||
Key::Ctrl('s') => {
|
||||
app.state = AppState::AppSettings;
|
||||
}
|
||||
Key::Char('\n') | Key::Char(' ') => {
|
||||
app.calculator.take_input(' ')?;
|
||||
}
|
||||
@ -265,6 +319,20 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<bool
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
(AppState::AppSettings, _) => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
app.state = AppState::Calculator;
|
||||
app.calculator.cancel()?;
|
||||
}
|
||||
Key::Char('d') => app.app_settings.display_mode = DisplayMode::Default(None),
|
||||
Key::Char(',') => app.app_settings.display_mode = DisplayMode::Default(Some(',')),
|
||||
Key::Char('s') => app.app_settings.display_mode = DisplayMode::Scientific(3),
|
||||
Key::Char('S') => {
|
||||
app.app_settings.display_mode = DisplayMode::Scientific(app.calculator.pop_usize()?)
|
||||
}
|
||||
Key::Char('e') => app.app_settings.display_mode = DisplayMode::Engineering,
|
||||
_ => {}
|
||||
},
|
||||
(AppState::Help, _) => match key {
|
||||
Key::Esc | Key::Char('q') => {
|
||||
app.state = AppState::Calculator;
|
||||
@ -336,3 +404,33 @@ fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<Termion
|
||||
.block(Block::default().borders(Borders::ALL).title(c.title));
|
||||
f.render_widget(help_message, area);
|
||||
}
|
||||
|
||||
fn fmt_scientific(i: usize, f: f64, precision: usize) -> String {
|
||||
let mut ret = format!("{:.precision$e}", f, precision = precision);
|
||||
let exp = ret.split_off(ret.find('e').unwrap_or(0));
|
||||
let (pow_sign, exp) = if exp.starts_with("e-") {
|
||||
('-', &exp[2..])
|
||||
} else {
|
||||
('+', &exp[1..])
|
||||
};
|
||||
let sign = if !ret.starts_with('-') { " " } else { "" };
|
||||
format!(
|
||||
"{:>2}: {}{}e{}{:0>pad$}",
|
||||
i,
|
||||
sign,
|
||||
ret,
|
||||
pow_sign,
|
||||
exp,
|
||||
pad = 2
|
||||
)
|
||||
}
|
||||
|
||||
fn fmt_separated(i: usize, f: f64, sep: char) -> String {
|
||||
let mut ret = f.to_string();
|
||||
let start = if ret.starts_with('-') { 1 } else { 0 };
|
||||
let end = ret.find('.').unwrap_or(ret.len());
|
||||
for i in 0..((end - start).div_euclid(3)) {
|
||||
ret.insert(end - start - (i + 1) * 3, sep);
|
||||
}
|
||||
format!("{:>2}: {}", i, ret)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user