diff --git a/src/book/mod.rs b/src/book/mod.rs index b248971..f93a37d 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -3,7 +3,10 @@ use std::cmp::max; use anyhow::{anyhow, Result}; use ironcalc::{ base::{ - expressions::types::Area, types::{Border, Col, Fill, Font, Row, SheetData, Style, Worksheet}, worksheet::WorksheetDimension, Model, UserModel + expressions::types::Area, + types::{Border, Col, Fill, Font, Row, SheetData, Style, Worksheet}, + worksheet::WorksheetDimension, + Model, UserModel, }, export::save_xlsx_to_writer, import::load_from_xlsx, @@ -141,7 +144,9 @@ impl Book { } pub fn set_sheet_name(&mut self, idx: u32, sheet_name: &str) -> Result<()> { - self.model.rename_sheet(idx, sheet_name).map_err(|e| anyhow!(e))?; + self.model + .rename_sheet(idx, sheet_name) + .map_err(|e| anyhow!(e))?; Ok(()) } @@ -151,7 +156,9 @@ impl Book { if let Some(name) = sheet_name { self.set_sheet_name(idx, name)?; } - self.model.set_selected_sheet(self.current_sheet).map_err(|e| anyhow!(e))?; + self.model + .set_selected_sheet(self.current_sheet) + .map_err(|e| anyhow!(e))?; Ok(()) } @@ -249,7 +256,8 @@ impl Book { pub fn clear_cell_range_all(&mut self, sheet: u32, start: Address, end: Address) -> Result<()> { let area = calculate_area(sheet, start, end); - self.model.range_clear_all(&area) + self.model + .range_clear_all(&area) .map_err(|s| anyhow!("Unable to clear cell contents {}", s))?; Ok(()) } @@ -263,7 +271,10 @@ impl Book { // TODO(jwall): This is modeled a little weird. We should probably record // the error *somewhere* but for the user there is nothing to be done except // not use a style. - match self.model.get_model().get_style_for_cell(sheet, cell.row as i32, cell.col as i32) + match self + .model + .get_model() + .get_style_for_cell(sheet, cell.row as i32, cell.col as i32) { Err(_) => None, Ok(s) => Some(s), @@ -271,13 +282,25 @@ impl Book { } fn get_column(&self, sheet: u32, col: usize) -> Result> { - Ok(self.model.get_model().workbook.worksheet(sheet) - .map_err(|e| anyhow!("{}", e))?.cols.get(col)) + Ok(self + .model + .get_model() + .workbook + .worksheet(sheet) + .map_err(|e| anyhow!("{}", e))? + .cols + .get(col)) } fn get_row(&self, sheet: u32, col: usize) -> Result> { - Ok(self.model.get_model().workbook.worksheet(sheet) - .map_err(|e| anyhow!("{}", e))?.rows.get(col)) + Ok(self + .model + .get_model() + .workbook + .worksheet(sheet) + .map_err(|e| anyhow!("{}", e))? + .rows + .get(col)) } pub fn get_column_style(&self, sheet: u32, col: usize) -> Result> { @@ -336,7 +359,8 @@ impl Book { pub fn set_cell_style(&mut self, style: &[(&str, &str)], area: &Area) -> Result<()> { for (path, val) in style { - self.model.update_range_style(area, path, val) + self.model + .update_range_style(area, path, val) .map_err(|s| anyhow!("Unable to format cell {}", s))?; } Ok(()) @@ -458,8 +482,14 @@ impl Book { self.get_column_size_for_sheet(self.current_sheet, idx) } - pub fn get_column_size_for_sheet(&self, sheet: u32, idx: usize) -> std::result::Result { - Ok((self.model.get_column_width(sheet, idx as i32) + pub fn get_column_size_for_sheet( + &self, + sheet: u32, + idx: usize, + ) -> std::result::Result { + Ok((self + .model + .get_column_width(sheet, idx as i32) .map_err(|e| anyhow!("Error getting column width: {:?}", e))? / COL_PIXELS) as usize) } @@ -468,8 +498,14 @@ impl Book { self.set_column_size_for_sheet(self.current_sheet, col, width) } - pub fn set_column_size_for_sheet(&mut self, sheet: u32, col: usize, width: usize) -> std::result::Result<(), anyhow::Error> { - self.model.set_column_width(sheet, col as i32, width as f64 * COL_PIXELS) + pub fn set_column_size_for_sheet( + &mut self, + sheet: u32, + col: usize, + width: usize, + ) -> std::result::Result<(), anyhow::Error> { + self.model + .set_column_width(sheet, col as i32, width as f64 * COL_PIXELS) .map_err(|e| anyhow!("Error setting column width: {:?}", e))?; Ok(()) } @@ -491,7 +527,8 @@ impl Book { /// Select a sheet by name. pub fn select_sheet_by_name(&mut self, name: &str) -> bool { if let Some((idx, _sheet)) = self - .model.get_model() + .model + .get_model() .workbook .worksheets .iter() @@ -515,7 +552,9 @@ impl Book { if next == len { next = 0; } - self.model.set_selected_sheet(next).expect("Unexpected error selecting sheet"); + self.model + .set_selected_sheet(next) + .expect("Unexpected error selecting sheet"); self.current_sheet = next; } @@ -526,21 +565,26 @@ impl Book { } else { self.current_sheet - 1 }; - self.model.set_selected_sheet(next).expect("Unexpected error selecting sheet"); + self.model + .set_selected_sheet(next) + .expect("Unexpected error selecting sheet"); self.current_sheet = next; } /// Select a sheet by id. pub fn select_sheet_by_id(&mut self, id: u32) -> bool { if let Some((idx, _sheet)) = self - .model.get_model() + .model + .get_model() .workbook .worksheets .iter() .enumerate() .find(|(_idx, sheet)| sheet.sheet_id == id) { - self.model.set_selected_sheet(idx as u32).expect("Unexpected error selecting sheet"); + self.model + .set_selected_sheet(idx as u32) + .expect("Unexpected error selecting sheet"); self.current_sheet = idx as u32; return true; } @@ -553,7 +597,8 @@ impl Book { // Looks like it should be done with: // https://docs.rs/ironcalc_base/latest/ironcalc_base/struct.UserModel.html#method.get_worksheets_properties Ok(self - .model.get_model() + .model + .get_model() .workbook .worksheet(self.current_sheet) .map_err(|s| anyhow!("Invalid Worksheet id: {}: error: {}", self.current_sheet, s))?) @@ -564,7 +609,8 @@ impl Book { // Looks like it should be done with: // https://docs.rs/ironcalc_base/latest/ironcalc_base/struct.UserModel.html#method.get_worksheets_properties Ok(&self - .model.get_model() + .model + .get_model() .workbook .worksheet(idx as u32) .map_err(|s| anyhow!("Invalid Worksheet: {}", s))? diff --git a/src/ui/cmd.rs b/src/ui/cmd.rs index 2a8b2a1..fed68d1 100644 --- a/src/ui/cmd.rs +++ b/src/ui/cmd.rs @@ -382,7 +382,7 @@ pub(crate) fn parse_color(color: &str) -> Result { return Err("Invalid color"); } } else { - return Err("Invalid color"); + return Err("Invalid color"); } } }; diff --git a/src/ui/mod.rs b/src/ui/mod.rs index aa02384..042c1a8 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -244,10 +244,13 @@ impl<'ws> Workspace<'ws> { /// Move to the top row without changing columns pub fn move_to_top(&mut self) -> Result<()> { - self.book.move_to(&Address { row: 1, col: self.book.location.col })?; + self.book.move_to(&Address { + row: 1, + col: self.book.location.col, + })?; Ok(()) } - + /// Move a row up in the current sheet. pub fn move_up(&mut self) -> Result<()> { let mut loc = self.book.location.clone(); @@ -320,7 +323,8 @@ impl<'ws> Workspace<'ws> { "Edit Mode:".to_string(), "* ENTER/RETURN: Exit edit mode and save changes".to_string(), "* Ctrl-r: Enter Range Selection mode".to_string(), - "* v: Enter Range Selection mode with the start of the range already selected".to_string(), + "* v: Enter Range Selection mode with the start of the range already selected" + .to_string(), "* ESC: Exit edit mode and discard changes".to_string(), "Otherwise edit as normal".to_string(), ], @@ -448,8 +452,7 @@ impl<'ws> Workspace<'ws> { self.book.set_sheet_name(idx as u32, name)?; } _ => { - self.book - .set_sheet_name(self.book.current_sheet, name)?; + self.book.set_sheet_name(self.book.current_sheet, name)?; } } Ok(None) @@ -462,22 +465,28 @@ impl<'ws> Workspace<'ws> { self.book.select_sheet_by_name(name); Ok(None) } - Ok(Some(Cmd::Quit)) => { - Ok(Some(ExitCode::SUCCESS)) - } + Ok(Some(Cmd::Quit)) => Ok(Some(ExitCode::SUCCESS)), Ok(Some(Cmd::ColorRows(_count, color))) => { let row_count = _count.unwrap_or(1); let row = self.book.location.row; - for r in row..(row+row_count) { - self.book.set_row_style(&[("fill.bg_color", &color)], self.book.current_sheet, r)?; + for r in row..(row + row_count) { + self.book.set_row_style( + &[("fill.bg_color", &color)], + self.book.current_sheet, + r, + )?; } Ok(None) } Ok(Some(Cmd::ColorColumns(_count, color))) => { let col_count = _count.unwrap_or(1); let col = self.book.location.col; - for c in col..(col+col_count) { - self.book.set_col_style(&[("fill.bg_color", &color)], self.book.current_sheet, c)?; + for c in col..(col + col_count) { + self.book.set_col_style( + &[("fill.bg_color", &color)], + self.book.current_sheet, + c, + )?; } Ok(None) } @@ -489,7 +498,7 @@ impl<'ws> Workspace<'ws> { row: start.row as i32, column: start.col as i32, width: (end.col - start.col + 1) as i32, - height: (end.row - start.row + 1) as i32 + height: (end.row - start.row + 1) as i32, } } else { let address = self.book.location.clone(); @@ -498,10 +507,11 @@ impl<'ws> Workspace<'ws> { row: address.row as i32, column: address.col as i32, width: 1, - height: 1 + height: 1, } }; - self.book.set_cell_style(&[("fill.bg_color", &color)], &area)?; + self.book + .set_cell_style(&[("fill.bg_color", &color)], &area)?; Ok(None) } Ok(None) => { @@ -611,11 +621,7 @@ impl<'ws> Workspace<'ws> { })?; self.state.range_select.sheet = Some(self.book.current_sheet); } - KeyCode::Char('C') - if key - .modifiers - .contains(KeyModifiers::CONTROL) => - { + KeyCode::Char('C') if key.modifiers.contains(KeyModifiers::CONTROL) => { self.copy_range(true)?; self.exit_range_select_mode()?; } @@ -632,7 +638,10 @@ impl<'ws> Workspace<'ws> { self.exit_range_select_mode()?; } KeyCode::Char('x') => { - if let (Some(from), Some(to)) = (self.state.range_select.start.as_ref(), self.state.range_select.end.as_ref()) { + if let (Some(from), Some(to)) = ( + self.state.range_select.start.as_ref(), + self.state.range_select.end.as_ref(), + ) { self.book.extend_to(from, to)?; } self.exit_range_select_mode()?; @@ -651,20 +660,15 @@ impl<'ws> Workspace<'ws> { fn copy_range(&mut self, formatted: bool) -> Result<(), anyhow::Error> { self.update_range_selection()?; match &self.state.range_select.get_range() { - Some(( - start, - end, - )) => { + Some((start, end)) => { let mut rows = Vec::new(); - for row in (AddressRange { start, end, }).as_rows() { + for row in (AddressRange { start, end }).as_rows() { let mut cols = Vec::new(); for cell in row { cols.push(if formatted { - self.book - .get_cell_addr_rendered(&cell)? + self.book.get_cell_addr_rendered(&cell)? } else { - self.book - .get_cell_addr_contents(&cell)? + self.book.get_cell_addr_contents(&cell)? }); } rows.push(cols); @@ -673,11 +677,9 @@ impl<'ws> Workspace<'ws> { } None => { self.state.clipboard = Some(ClipboardContents::Cell(if formatted { - self.book - .get_current_cell_rendered()? + self.book.get_current_cell_rendered()? } else { - self.book - .get_current_cell_contents()? + self.book.get_current_cell_contents()? })); } } @@ -743,11 +745,7 @@ impl<'ws> Workspace<'ws> { self.book.get_current_cell_rendered()?, )); } - KeyCode::Char('C') - if key - .modifiers - .contains(KeyModifiers::CONTROL) => - { + KeyCode::Char('C') if key.modifiers.contains(KeyModifiers::CONTROL) => { self.state.clipboard = Some(ClipboardContents::Cell( self.book.get_current_cell_rendered()?, )); @@ -861,7 +859,13 @@ impl<'ws> Workspace<'ws> { } KeyCode::Char('g') => { // TODO(zaphar): This really needs a better state machine. - if self.state.char_queue.first().map(|c| *c == 'g').unwrap_or(false) { + if self + .state + .char_queue + .first() + .map(|c| *c == 'g') + .unwrap_or(false) + { self.state.char_queue.pop(); self.move_to_top()?; } else { diff --git a/src/ui/render/test.rs b/src/ui/render/test.rs index 68f0ecd..aed6856 100644 --- a/src/ui/render/test.rs +++ b/src/ui/render/test.rs @@ -14,8 +14,8 @@ fn test_viewport_get_visible_columns() { let default_size = book.get_col_size(1).expect("Failed to get column size"); let width = dbg!(dbg!(default_size) * 12 / 2); let app_state = AppState::default(); - let viewport = - Viewport::new(&book, Some(&app_state.range_select)).with_selected(Address { row: 1, col: 17 }); + let viewport = Viewport::new(&book, Some(&app_state.range_select)) + .with_selected(Address { row: 1, col: 17 }); let cols = viewport .get_visible_columns((width + 5) as u16, &mut state) .expect("Failed to get visible columns"); @@ -31,8 +31,8 @@ fn test_viewport_get_visible_rows() { ); let height = 6; let app_state = AppState::default(); - let viewport = - Viewport::new(&book, Some(&app_state.range_select)).with_selected(Address { row: 17, col: 1 }); + let viewport = Viewport::new(&book, Some(&app_state.range_select)) + .with_selected(Address { row: 17, col: 1 }); let rows = dbg!(viewport.get_visible_rows(height as u16, &mut state)); assert_eq!(height - 1, rows.len()); assert_eq!( @@ -65,8 +65,8 @@ fn test_viewport_visible_columns_after_length_change() { .expect("Failed to set column size"); { let app_state = AppState::default(); - let viewport = - Viewport::new(&book, Some(&app_state.range_select)).with_selected(Address { row: 1, col: 1 }); + let viewport = Viewport::new(&book, Some(&app_state.range_select)) + .with_selected(Address { row: 1, col: 1 }); let cols = viewport .get_visible_columns((width + 5) as u16, &mut state) .expect("Failed to get visible columns"); @@ -97,7 +97,9 @@ fn test_color_mapping() { ("darkgrey", Color::DarkGray), ("darkgray", Color::DarkGray), ("#35f15b", Color::Rgb(53, 241, 91)), - ].map(|(s, c)| (Some(s.to_string()), c)) { + ] + .map(|(s, c)| (Some(s.to_string()), c)) + { assert_eq!(super::viewport::map_color(s.as_ref(), Color::Gray), c); } } diff --git a/src/ui/test.rs b/src/ui/test.rs index 11fb9b5..ffbeb02 100644 --- a/src/ui/test.rs +++ b/src/ui/test.rs @@ -304,7 +304,6 @@ fn test_cmd_color_columns_with_idx_and_color() { assert_eq!(cmd, Cmd::ColorColumns(Some(1), parse_color("red").unwrap())); } - #[test] fn test_input_navitation_enter_key() { let mut ws = new_workspace(); @@ -1004,8 +1003,7 @@ macro_rules! assert_range_clear { .run(&mut ws) .expect("Failed to handle script"); assert_eq!(Some(&Modality::RangeSelect), ws.state.modality_stack.last()); - $script.run(&mut ws) - .expect("Failed to handle script"); + $script.run(&mut ws).expect("Failed to handle script"); assert_eq!( "".to_string(), ws.book @@ -1023,18 +1021,21 @@ macro_rules! assert_range_clear { #[test] fn test_range_select_clear_upper_d() { - assert_range_clear!(script() - .char('j') - .char('l') - .char('D')); + assert_range_clear!(script().char('j').char('l').char('D')); } #[test] fn test_range_select_movement() { let mut ws = new_workspace(); - ws.book.new_sheet(Some("s2")).expect("Unable create s2 sheet"); - ws.book.new_sheet(Some("s3")).expect("Unable create s3 sheet"); - script().ctrl('r').run(&mut ws) + ws.book + .new_sheet(Some("s2")) + .expect("Unable create s2 sheet"); + ws.book + .new_sheet(Some("s3")) + .expect("Unable create s3 sheet"); + script() + .ctrl('r') + .run(&mut ws) .expect("failed to run script"); assert_eq!(Some(&Modality::RangeSelect), ws.state.modality_stack.last()); script() @@ -1064,10 +1065,7 @@ fn test_range_select_movement() { #[test] fn test_range_select_clear_lower_d() { - assert_range_clear!(script() - .char('j') - .char('l') - .char('d')); + assert_range_clear!(script().char('j').char('l').char('d')); } macro_rules! assert_range_copy { @@ -1075,8 +1073,12 @@ macro_rules! assert_range_copy { let mut ws = new_workspace(); let top_left_addr = Address { row: 2, col: 2 }; let bot_right_addr = Address { row: 4, col: 4 }; - ws.book.update_cell(&top_left_addr, "top_left").expect("Failed to update top left"); - ws.book.update_cell(&bot_right_addr, "bot_right").expect("Failed to update top left"); + ws.book + .update_cell(&top_left_addr, "top_left") + .expect("Failed to update top left"); + ws.book + .update_cell(&bot_right_addr, "bot_right") + .expect("Failed to update top left"); assert!(ws.state.clipboard.is_none()); script() .ctrl('r') @@ -1085,7 +1087,14 @@ macro_rules! assert_range_copy { .char(' ') .run(&mut ws) .expect("failed to run script"); - assert_eq!(&top_left_addr, ws.state.range_select.start.as_ref().expect("Didn't find a start of range")); + assert_eq!( + &top_left_addr, + ws.state + .range_select + .start + .as_ref() + .expect("Didn't find a start of range") + ); script() .char('2') .char('j') @@ -1093,27 +1102,53 @@ macro_rules! assert_range_copy { .char('l') .run(&mut ws) .expect("failed to run script"); - assert_eq!(&bot_right_addr, ws.state.range_select.end.as_ref().expect("Didn't find a start of range")); - assert_eq!(&Address { row: 1, col: 1}, ws.state.range_select.original_location - .as_ref().expect("Expected an original location")); - assert_eq!(0, ws.state.range_select.original_sheet. - expect("Expected an original sheet")); - assert_eq!(Some(&Modality::RangeSelect), ws.state.modality_stack.iter().last()); + assert_eq!( + &bot_right_addr, + ws.state + .range_select + .end + .as_ref() + .expect("Didn't find a start of range") + ); + assert_eq!( + &Address { row: 1, col: 1 }, + ws.state + .range_select + .original_location + .as_ref() + .expect("Expected an original location") + ); + assert_eq!( + 0, + ws.state + .range_select + .original_sheet + .expect("Expected an original sheet") + ); + assert_eq!( + Some(&Modality::RangeSelect), + ws.state.modality_stack.iter().last() + ); dbg!(ws.state.range_select.get_range()); - $script.run(&mut ws) - .expect("failed to run script"); + $script.run(&mut ws).expect("failed to run script"); assert!(ws.state.clipboard.is_some()); match ws.state.clipboard.unwrap() { crate::ui::ClipboardContents::Cell(_) => assert!(false, "Not rows in Clipboard"), crate::ui::ClipboardContents::Range(rows) => { - assert_eq!(vec![ - vec!["top_left".to_string(), "".to_string(), "".to_string()], - vec!["".to_string(), "".to_string(), "".to_string()], - vec!["".to_string(), "".to_string(), "bot_right".to_string()], - ], rows); - }, + assert_eq!( + vec![ + vec!["top_left".to_string(), "".to_string(), "".to_string()], + vec!["".to_string(), "".to_string(), "".to_string()], + vec!["".to_string(), "".to_string(), "bot_right".to_string()], + ], + rows + ); + } } - assert_eq!(Some(&Modality::Navigate), ws.state.modality_stack.iter().last()); + assert_eq!( + Some(&Modality::Navigate), + ws.state.modality_stack.iter().last() + ); }}; } @@ -1140,7 +1175,9 @@ fn test_range_select_copy_capital_c() { #[test] fn test_extend_to_range() { let mut ws = new_workspace(); - ws.book.edit_current_cell("=B1+1").expect("Failed to edit cell"); + ws.book + .edit_current_cell("=B1+1") + .expect("Failed to edit cell"); ws.book.evaluate(); script() .char('v') @@ -1148,7 +1185,9 @@ fn test_extend_to_range() { .char('x') .run(&mut ws) .expect("Unable to run script"); - let extended_cell = ws.book.get_cell_addr_contents(&Address { row: 2, col: 1 }) + let extended_cell = ws + .book + .get_cell_addr_contents(&Address { row: 2, col: 1 }) .expect("Failed to get cell contents"); assert_eq!("=B2+1".to_string(), extended_cell); } @@ -1166,8 +1205,18 @@ fn test_color_cells() { .expect("Unable to run script"); for ri in 1..=3 { for ci in 1..=3 { - let style = ws.book.get_cell_style(ws.book.current_sheet, &Address { row: ri, col: ci }).expect("failed to get style"); - assert_eq!("#800000", style.fill.bg_color.expect(&format!("No background color set for {}:{}", ri, ci)).as_str()); + let style = ws + .book + .get_cell_style(ws.book.current_sheet, &Address { row: ri, col: ci }) + .expect("failed to get style"); + assert_eq!( + "#800000", + style + .fill + .bg_color + .expect(&format!("No background color set for {}:{}", ri, ci)) + .as_str() + ); } } }