Skip to content

Commit

Permalink
status-bar: Remove panics from code
Browse files Browse the repository at this point in the history
by passing errors up to parent functions and attaching some error
context on the way.
  • Loading branch information
har7an committed Aug 18, 2022
1 parent a6ca18d commit ca51774
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 78 deletions.
2 changes: 1 addition & 1 deletion default-plugins/status-bar/src/first_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ mod tests {
fn unstyle(line_part: LinePart) -> String {
let string = line_part.to_string();

let re = regex::Regex::new(r"\x1b\[[0-9;]*m").unwrap();
let re = regex::Regex::new(r"\x1b\[[0-9;]*m").expect("Test failed");
let string = re.replace_all(&string, "".to_string());

string.to_string()
Expand Down
20 changes: 12 additions & 8 deletions default-plugins/status-bar/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,10 @@ fn color_elements(palette: Palette, different_color_alternates: bool) -> Colored
}

impl ZellijPlugin for State {
fn load(&mut self) {
fn load(&mut self) -> Result<()> {
// TODO: Should be able to choose whether to use the cache through config.
self.tip_name = get_cached_tip_name();
self.tip_name =
get_cached_tip_name().context("status bar: Failed to acquire a tip to display")?;
set_selectable(false);
subscribe(&[
EventType::ModeUpdate,
Expand All @@ -180,10 +181,9 @@ impl ZellijPlugin for State {
EventType::InputReceived,
EventType::SystemClipboardFailure,
])
.expect(errors::TODO_HANDLING);
}

fn update(&mut self, event: Event) {
fn update(&mut self, event: Event) -> Result<()> {
match event {
Event::ModeUpdate(mode_info) => {
self.mode_info = mode_info;
Expand All @@ -203,9 +203,10 @@ impl ZellijPlugin for State {
},
_ => {},
}
Ok(())
}

fn render(&mut self, _rows: usize, cols: usize) {
fn render(&mut self, _rows: usize, cols: usize) -> Result<()> {
let supports_arrow_fonts = !self.mode_info.capabilities.arrow_fonts;
let separator = if supports_arrow_fonts {
ARROW_SEPARATOR
Expand All @@ -214,7 +215,9 @@ impl ZellijPlugin for State {
};

let first_line = first_line(&self.mode_info, cols, separator);
let second_line = self.second_line(cols);
let second_line = self
.second_line(cols)
.context("status bar: Failed to generate second line of output")?;

let background = match self.mode_info.style.colors.theme_hue {
ThemeHue::Dark => self.mode_info.style.colors.black,
Expand All @@ -232,11 +235,12 @@ impl ZellijPlugin for State {
},
}
println!("\u{1b}[m{}\u{1b}[0K", second_line);
Ok(())
}
}

impl State {
fn second_line(&self, cols: usize) -> LinePart {
fn second_line(&self, cols: usize) -> Result<LinePart> {
let active_tab = self.tabs.iter().find(|t| t.active);

if let Some(copy_destination) = self.text_copy_destination {
Expand Down Expand Up @@ -268,7 +272,7 @@ impl State {
keybinds(&self.mode_info, &self.tip_name, cols)
}
} else {
LinePart::default()
Ok(LinePart::default())
}
}
}
Expand Down
104 changes: 56 additions & 48 deletions default-plugins/status-bar/src/second_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ fn full_length_shortcut(
}
}

fn locked_interface_indication(palette: Palette) -> LinePart {
fn locked_interface_indication(palette: Palette) -> Result<LinePart> {
let locked_text = " -- INTERFACE LOCKED -- ";
let locked_text_len = locked_text.chars().count();
let text_color = palette_match!(match palette.theme_hue {
ThemeHue::Dark => palette.white,
ThemeHue::Light => palette.black,
});
let locked_styled_text = Style::new().fg(text_color).bold().paint(locked_text);
LinePart {
Ok(LinePart {
part: locked_styled_text.to_string(),
len: locked_text_len,
}
})
}

fn add_shortcut(help: &ModeInfo, linepart: &LinePart, text: &str, keys: Vec<Key>) -> LinePart {
Expand All @@ -75,7 +75,6 @@ fn add_shortcut(help: &ModeInfo, linepart: &LinePart, text: &str, keys: Vec<Key>
fn full_shortcut_list_nonstandard_mode(help: &ModeInfo) -> LinePart {
let mut line_part = LinePart::default();
let keys_and_hints = get_keys_and_hints(help);

for (long, _short, keys) in keys_and_hints.into_iter() {
line_part = add_shortcut(help, &line_part, &long, keys.to_vec());
}
Expand Down Expand Up @@ -130,7 +129,11 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<Key>)> {
// Sort and deduplicate the keybindings first. We sort after the `Key`s, and deduplicate by
// their `Action` vectors. An unstable sort is fine here because if the user maps anything to
// the same key again, anything will happen...
old_keymap.sort_unstable_by(|(keya, _), (keyb, _)| keya.partial_cmp(keyb).unwrap());
old_keymap.sort_unstable_by(
|(keya, _), (keyb, _)| keya
.partial_cmp(keyb)
.unwrap_or(std::cmp::Ordering::Equal)
);

let mut known_actions: Vec<Vec<Action>> = vec![];
let mut km = vec![];
Expand Down Expand Up @@ -256,33 +259,32 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<Key>)> {
]} else { vec![] }
}

fn full_shortcut_list(help: &ModeInfo, tip: TipFn) -> LinePart {
fn full_shortcut_list(help: &ModeInfo, tip: TipFn) -> Result<LinePart> {
match help.mode {
InputMode::Normal => tip(help),
InputMode::Normal => Ok(tip(help)),
InputMode::Locked => locked_interface_indication(help.style.colors),
_ => full_shortcut_list_nonstandard_mode(help),
_ => Ok(full_shortcut_list_nonstandard_mode(help)),
}
}

fn shortened_shortcut_list_nonstandard_mode(help: &ModeInfo) -> LinePart {
let mut line_part = LinePart::default();
let keys_and_hints = get_keys_and_hints(help);

for (_, short, keys) in keys_and_hints.into_iter() {
line_part = add_shortcut(help, &line_part, &short, keys.to_vec());
}
line_part
}

fn shortened_shortcut_list(help: &ModeInfo, tip: TipFn) -> LinePart {
fn shortened_shortcut_list(help: &ModeInfo, tip: TipFn) -> Result<LinePart> {
match help.mode {
InputMode::Normal => tip(help),
InputMode::Normal => Ok(tip(help)),
InputMode::Locked => locked_interface_indication(help.style.colors),
_ => shortened_shortcut_list_nonstandard_mode(help),
_ => Ok(shortened_shortcut_list_nonstandard_mode(help)),
}
}

fn best_effort_shortcut_list_nonstandard_mode(help: &ModeInfo, max_len: usize) -> LinePart {
fn best_effort_shortcut_list_nonstandard_mode(help: &ModeInfo, max_len: usize) -> Result<LinePart> {
let mut line_part = LinePart::default();
let keys_and_hints = get_keys_and_hints(help);

Expand All @@ -295,49 +297,52 @@ fn best_effort_shortcut_list_nonstandard_mode(help: &ModeInfo, max_len: usize) -
}
line_part = new_line_part;
}
line_part
Ok(line_part)
}

fn best_effort_shortcut_list(help: &ModeInfo, tip: TipFn, max_len: usize) -> LinePart {
fn best_effort_shortcut_list(help: &ModeInfo, tip: TipFn, max_len: usize) -> Result<LinePart> {
match help.mode {
InputMode::Normal => {
let line_part = tip(help);
if line_part.len <= max_len {
line_part
Ok(line_part)
} else {
LinePart::default()
Ok(LinePart::default())
}
},
InputMode::Locked => {
let line_part = locked_interface_indication(help.style.colors);
let line_part = locked_interface_indication(help.style.colors)?;
if line_part.len <= max_len {
line_part
Ok(line_part)
} else {
LinePart::default()
Ok(LinePart::default())
}
},
_ => best_effort_shortcut_list_nonstandard_mode(help, max_len),
}
}

pub fn keybinds(help: &ModeInfo, tip_name: &str, max_width: usize) -> LinePart {
pub fn keybinds(help: &ModeInfo, tip_name: &str, max_width: usize) -> Result<LinePart> {
// It is assumed that there is at least one TIP data in the TIPS HasMap.
let tip_body = TIPS
.get(tip_name)
.unwrap_or_else(|| TIPS.get("quicknav").unwrap());
.or_else(|| TIPS.get("quicknav"))
.unwrap_or(crate::tip::NO_TIPS_FOUND);

let full_shortcut_list = full_shortcut_list(help, tip_body.full);
let full_shortcut_list = full_shortcut_list(help, tip_body.full)
.context("status bar: Failed to assemble second line")?;
if full_shortcut_list.len <= max_width {
return full_shortcut_list;
return Ok(full_shortcut_list);
}
let shortened_shortcut_list = shortened_shortcut_list(help, tip_body.medium);
let shortened_shortcut_list = shortened_shortcut_list(help, tip_body.medium)
.context("status bar: Failed to assemble second line")?;
if shortened_shortcut_list.len <= max_width {
return shortened_shortcut_list;
return Ok(shortened_shortcut_list);
}
best_effort_shortcut_list(help, tip_body.short, max_width)
}

pub fn text_copied_hint(palette: &Palette, copy_destination: CopyDestination) -> LinePart {
pub fn text_copied_hint(palette: &Palette, copy_destination: CopyDestination) -> Result<LinePart> {
let green_color = palette_match!(palette.green);
let hint = match copy_destination {
CopyDestination::Command => "Text piped to external command",
Expand All @@ -347,22 +352,22 @@ pub fn text_copied_hint(palette: &Palette, copy_destination: CopyDestination) ->
CopyDestination::Primary => "Text copied to system clipboard",
CopyDestination::System => "Text copied to system clipboard",
};
LinePart {
Ok(LinePart {
part: Style::new().fg(green_color).bold().paint(hint).to_string(),
len: hint.len(),
}
})
}

pub fn system_clipboard_error(palette: &Palette) -> LinePart {
pub fn system_clipboard_error(palette: &Palette) -> Result<LinePart> {
let hint = " Error using the system clipboard.";
let red_color = palette_match!(palette.red);
LinePart {
Ok(LinePart {
part: Style::new().fg(red_color).bold().paint(hint).to_string(),
len: hint.len(),
}
})
}

pub fn fullscreen_panes_to_hide(palette: &Palette, panes_to_hide: usize) -> LinePart {
pub fn fullscreen_panes_to_hide(palette: &Palette, panes_to_hide: usize) -> Result<LinePart> {
let text_color = palette_match!(match palette.theme_hue {
ThemeHue::Dark => palette.white,
ThemeHue::Light => palette.black,
Expand All @@ -380,7 +385,7 @@ pub fn fullscreen_panes_to_hide(palette: &Palette, panes_to_hide: usize) -> Line
+ panes.chars().count()
+ hide.chars().count()
+ 5; // 3 for ():'s around shortcut, 2 for the space
LinePart {
Ok(LinePart {
part: format!(
"{}{}{}{}{}{}",
shortcut_left_separator,
Expand All @@ -391,10 +396,10 @@ pub fn fullscreen_panes_to_hide(palette: &Palette, panes_to_hide: usize) -> Line
Style::new().fg(text_color).bold().paint(hide)
),
len,
}
})
}

pub fn floating_panes_are_visible(mode_info: &ModeInfo) -> LinePart {
pub fn floating_panes_are_visible(mode_info: &ModeInfo) -> Result<LinePart> {
let palette = mode_info.style.colors;
let km = &mode_info.get_mode_keybinds();
let white_color = match palette.white {
Expand Down Expand Up @@ -442,7 +447,7 @@ pub fn floating_panes_are_visible(mode_info: &ModeInfo) -> LinePart {
+ p_right_separator.chars().count()
+ to_hide.chars().count()
+ 5; // 3 for ():'s around floating_panes, 2 for the space
LinePart {
Ok(LinePart {
part: format!(
"{}{}{}{}{}{}{}{}{}{}",
shortcut_left_separator,
Expand All @@ -457,10 +462,13 @@ pub fn floating_panes_are_visible(mode_info: &ModeInfo) -> LinePart {
Style::new().fg(white_color).bold().paint(to_hide),
),
len,
}
})
}

pub fn locked_fullscreen_panes_to_hide(palette: &Palette, panes_to_hide: usize) -> LinePart {
pub fn locked_fullscreen_panes_to_hide(
palette: &Palette,
panes_to_hide: usize,
) -> Result<LinePart> {
let text_color = palette_match!(match palette.theme_hue {
ThemeHue::Dark => palette.white,
ThemeHue::Light => palette.black,
Expand All @@ -480,7 +488,7 @@ pub fn locked_fullscreen_panes_to_hide(palette: &Palette, panes_to_hide: usize)
+ panes.chars().count()
+ hide.chars().count()
+ 5; // 3 for ():'s around shortcut, 2 for the space
LinePart {
Ok(LinePart {
part: format!(
"{}{}{}{}{}{}{}",
Style::new().fg(text_color).bold().paint(locked_text),
Expand All @@ -492,10 +500,10 @@ pub fn locked_fullscreen_panes_to_hide(palette: &Palette, panes_to_hide: usize)
Style::new().fg(text_color).bold().paint(hide)
),
len,
}
})
}

pub fn locked_floating_panes_are_visible(palette: &Palette) -> LinePart {
pub fn locked_floating_panes_are_visible(palette: &Palette) -> Result<LinePart> {
let white_color = match palette.white {
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
PaletteColor::EightBit(color) => Fixed(color),
Expand All @@ -510,7 +518,7 @@ pub fn locked_floating_panes_are_visible(palette: &Palette) -> LinePart {
let floating_panes = "FLOATING PANES VISIBLE";

let len = locked_text.chars().count() + floating_panes.chars().count();
LinePart {
Ok(LinePart {
part: format!(
"{}{}{}{}",
Style::new().fg(white_color).bold().paint(locked_text),
Expand All @@ -519,7 +527,7 @@ pub fn locked_floating_panes_are_visible(palette: &Palette) -> LinePart {
shortcut_right_separator,
),
len,
}
})
}

#[cfg(test)]
Expand All @@ -536,7 +544,7 @@ mod tests {
fn unstyle(line_part: LinePart) -> String {
let string = line_part.to_string();

let re = regex::Regex::new(r"\x1b\[[0-9;]*m").unwrap();
let re = regex::Regex::new(r"\x1b\[[0-9;]*m").expect("Test failed");
let string = re.replace_all(&string, "".to_string());

string.to_string()
Expand Down Expand Up @@ -684,7 +692,7 @@ mod tests {
..ModeInfo::default()
};

let ret = keybinds(&mode_info, "quicknav", 500);
let ret = keybinds(&mode_info, "quicknav", 500).expect("Test failed");
let ret = unstyle(ret);

assert_eq!(
Expand Down Expand Up @@ -719,7 +727,7 @@ mod tests {
..ModeInfo::default()
};

let ret = keybinds(&mode_info, "quicknav", 35);
let ret = keybinds(&mode_info, "quicknav", 35).expect("Test failed");
let ret = unstyle(ret);

assert_eq!(ret, " <←↓↑→> Move / <n> New ... ");
Expand Down Expand Up @@ -756,7 +764,7 @@ mod tests {
..ModeInfo::default()
};

let ret = keybinds(&mode_info, "quicknav", 500);
let ret = keybinds(&mode_info, "quicknav", 500).expect("Test failed");
let ret = unstyle(ret);

assert_eq!(ret, " Ctrl + <a|ENTER|1|SPACE> Move focus / <BACKSPACE> New / <ESC> Close / <END> Fullscreen");
Expand Down
Loading

0 comments on commit ca51774

Please sign in to comment.