Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor various components of Rust code #490

Merged
merged 10 commits into from
Sep 19, 2024
46 changes: 21 additions & 25 deletions tui/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ pub struct Shortcut {
pub desc: &'static str,
}

fn add_spacing(list: Vec<Vec<Span>>) -> Line {
list.into_iter()
.flat_map(|mut s| {
s.push(Span::default().content(" "));
s
})
.collect()
}

pub fn span_vec_len(span_vec: &[Span]) -> usize {
span_vec.iter().rfold(0, |init, s| init + s.width())
}
Expand All @@ -29,15 +38,14 @@ impl ShortcutList {
.title(self.scope_name)
.borders(Borders::all());
let inner_area = area.inner(Margin::new(1, 1));
let mut shortcut_list: Vec<Vec<Span>> = self.hints.iter().map(|h| h.to_spans()).collect();
let shortcut_spans: Vec<Vec<Span>> = self.hints.iter().map(|h| h.to_spans()).collect();

let mut lines = vec![Line::default(); SHORTCUT_LINES];
let mut idx = 0;
let mut lines: Vec<Line> = Vec::with_capacity(SHORTCUT_LINES);

while idx < SHORTCUT_LINES - 1 {
let split_idx = shortcut_list
let shortcut_list = (0..SHORTCUT_LINES - 1).fold(shortcut_spans, |mut acc, _| {
let split_idx = acc
.iter()
.scan(0usize, |total_len, s| {
.scan(0_usize, |total_len, s| {
*total_len += span_vec_len(s);
if *total_len > inner_area.width as usize {
None
Expand All @@ -47,25 +55,13 @@ impl ShortcutList {
}
})
.count();
let new_shortcut_list = shortcut_list.split_off(split_idx);
let line: Vec<_> = shortcut_list
.into_iter()
.flat_map(|mut s| {
s.push(Span::default().content(" "));
s
})
.collect();
shortcut_list = new_shortcut_list;
lines[idx] = line.into();
idx += 1;
}
lines[idx] = shortcut_list
.into_iter()
.flat_map(|mut s| {
s.push(Span::default().content(" "));
s
})
.collect();

let new_shortcut_list = acc.split_off(split_idx);
lines.push(add_spacing(acc));

new_shortcut_list
});
lines.push(add_spacing(shortcut_list));

let p = Paragraph::new(lines).block(block);
frame.render_widget(p, area);
Expand Down
97 changes: 32 additions & 65 deletions tui/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ use ratatui::{
Frame,
};

const MIN_WIDTH: u16 = 77;
const MIN_HEIGHT: u16 = 19;

pub struct AppState {
/// Selected theme
theme: Theme,
Expand Down Expand Up @@ -68,16 +71,14 @@ impl AppState {
}
pub fn draw(&mut self, frame: &mut Frame) {
let terminal_size = frame.area();
let min_width = 77; // Minimum width threshold
let min_height = 19; // Minimum height threshold
lj3954 marked this conversation as resolved.
Show resolved Hide resolved

if terminal_size.width < min_width || terminal_size.height < min_height {
if terminal_size.width < MIN_WIDTH || terminal_size.height < MIN_HEIGHT {
let size_warning_message = format!(
"Terminal size too small:\nWidth = {} Height = {}\n\nMinimum size:\nWidth = {} Height = {}",
terminal_size.width,
terminal_size.height,
min_width,
min_height,
MIN_WIDTH,
MIN_HEIGHT,
);

let warning_paragraph = Paragraph::new(size_warning_message.clone())
Expand Down Expand Up @@ -209,13 +210,15 @@ impl AppState {
},
));

let style = if let Focus::List = self.focus {
Style::default().reversed()
} else {
Style::new()
};

// Create the list widget with items
let list = List::new(items)
.highlight_style(if let Focus::List = self.focus {
Style::default().reversed()
} else {
Style::new()
})
.highlight_style(style)
.block(
Block::default()
.borders(Borders::ALL)
Expand All @@ -234,12 +237,12 @@ impl AppState {
pub fn handle_key(&mut self, key: &KeyEvent) -> bool {
// This should be defined first to allow closing
// the application even when not drawable ( If terminal is small )
if matches!(self.focus, Focus::TabList | Focus::List) {
if key.code == KeyCode::Char('q')
|| key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL)
{
return false;
}
// Exit on 'q' or 'Ctrl-c' input
if matches!(self.focus, Focus::TabList | Focus::List)
&& (key.code == KeyCode::Char('q')
|| key.modifiers.contains(KeyModifiers::CONTROL) && key.code == KeyCode::Char('c'))
{
return false;
}

// If UI is not drawable returning true will mark as the key handled
Expand All @@ -253,20 +256,11 @@ impl AppState {
self.focus = Focus::List;
}
}

Focus::Search => match self.filter.handle_key(key) {
SearchAction::Exit => self.exit_search(),
SearchAction::Update => self.update_items(),
_ => {}
},

_ if key.code == KeyCode::Char('q')
|| key.code == KeyCode::Char('c')
&& key.modifiers.contains(KeyModifiers::CONTROL) =>
{
return false;
}

Focus::TabList => match key.code {
KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right | KeyCode::Tab => {
self.focus = Focus::List
Expand All @@ -289,7 +283,6 @@ impl AppState {
KeyCode::Char('T') => self.theme.prev(),
_ => {}
},

Focus::List if key.kind != KeyEventKind::Release => match key.code {
KeyCode::Char('j') | KeyCode::Down => self.selection.select_next(),
KeyCode::Char('k') | KeyCode::Up => self.selection.select_previous(),
Expand All @@ -309,7 +302,6 @@ impl AppState {
KeyCode::Char('T') => self.theme.prev(),
_ => {}
},

_ => (),
};
true
Expand All @@ -335,7 +327,7 @@ impl AppState {
self.selection.select(Some(0));
self.update_items();
}
pub fn get_selected_command(&self) -> Option<Command> {
fn get_selected_node(&self) -> Option<&ListNode> {
let mut selected_index = self.selection.selected().unwrap_or(0);

if !self.at_root() && selected_index == 0 {
Expand All @@ -347,27 +339,17 @@ impl AppState {

if let Some(item) = self.filter.item_list().get(selected_index) {
if !item.has_children {
return Some(item.node.command.clone());
return Some(&item.node);
}
}
None
}
fn get_selected_description(&mut self) -> Option<String> {
let mut selected_index = self.selection.selected().unwrap_or(0);

if !self.at_root() && selected_index == 0 {
return None;
}
if !self.at_root() {
selected_index = selected_index.saturating_sub(1);
}

if let Some(item) = self.filter.item_list().get(selected_index) {
if !item.has_children {
return Some(item.node.description.clone());
}
}
None
pub fn get_selected_command(&self) -> Option<Command> {
self.get_selected_node().map(|node| node.command.clone())
}
fn get_selected_description(&self) -> Option<String> {
self.get_selected_node()
.map(|node| node.description.clone())
}
pub fn go_to_selected_dir(&mut self) {
let mut selected_index = self.selection.selected().unwrap_or(0);
Expand Down Expand Up @@ -400,29 +382,14 @@ impl AppState {
selected_index = selected_index.saturating_sub(1);
}

if let Some(item) = self.filter.item_list().get(selected_index) {
item.has_children
} else {
false
}
self.filter
.item_list()
.get(selected_index)
.map_or(false, |item| item.has_children)
}

pub fn selected_item_is_cmd(&self) -> bool {
let mut selected_index = self.selection.selected().unwrap_or(0);

if !self.at_root() && selected_index == 0 {
return false;
}

if !self.at_root() {
selected_index = selected_index.saturating_sub(1);
}

if let Some(item) = self.filter.item_list().get(selected_index) {
!item.has_children
} else {
false
}
!self.selected_item_is_dir()
}
pub fn selected_item_is_up_dir(&self) -> bool {
let selected_index = self.selection.selected().unwrap_or(0);
Expand Down