refactor: Revert tui upgrade to 0.10

Reverts tui upgrade, there are some bugs and issues - namely, issues with rendering text.
We can revert this commit when those bugs are dealt with (should be fine after 0.10.1, tested building from the repo).
This commit is contained in:
Clement Tsang 2020-08-16 01:25:59 -07:00 committed by GitHub
parent 9068108d0f
commit 08e49b63c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 546 additions and 424 deletions

6
Cargo.lock generated
View file

@ -1345,13 +1345,15 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
[[package]]
name = "tui"
version = "0.10.0"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a977b0bb2e2033a6fef950f218f13622c3c34e59754b704ce3492dedab1dfe95"
checksum = "9533d39bef0ae8f510e8a99d78702e68d1bbf0b98a78ec9740509d287010ae1e"
dependencies = [
"bitflags",
"cassowary",
"crossterm",
"either",
"itertools",
"unicode-segmentation",
"unicode-width",
]

View file

@ -39,7 +39,7 @@ serde = {version = "1.0", features = ["derive"] }
unicode-segmentation = "1.6.0"
unicode-width = "0.1.7"
# tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"}
tui = {version = "0.10.0", features = ["crossterm"], default-features = false }
tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
# For debugging only...
fern = "0.6.0"

View file

@ -4,7 +4,7 @@ use std::collections::HashMap;
use tui::{
backend::Backend,
layout::{Constraint, Direction, Layout, Rect},
text::{Span, Spans},
widgets::Text,
Frame, Terminal,
};
@ -55,7 +55,7 @@ pub struct Painter {
pub colours: CanvasColours,
height: u16,
width: u16,
styled_help_text: Vec<Spans<'static>>,
styled_help_text: Vec<Text<'static>>,
is_mac_os: bool,
row_constraints: Vec<Constraint>,
col_constraints: Vec<Vec<Constraint>>,
@ -163,27 +163,28 @@ impl Painter {
styled_help_spans.extend(
section
.iter()
.map(|&text| Span::styled(text, self.colours.text_style))
.map(|&text| Text::styled(text, self.colours.text_style))
.collect::<Vec<_>>(),
);
} else {
// Not required check but it runs only a few times... so whatever ig, prevents me from
// being dumb and leaving a help text section only one line long.
if section.len() > 1 {
styled_help_spans.push(Span::from(""));
styled_help_spans.push(Text::raw("\n\n"));
styled_help_spans
.push(Span::styled(section[0], self.colours.table_header_style));
.push(Text::styled(section[0], self.colours.table_header_style));
styled_help_spans.extend(
section[1..]
.iter()
.map(|&text| Span::styled(text, self.colours.text_style))
.map(|&text| Text::styled(text, self.colours.text_style))
.collect::<Vec<_>>(),
);
}
}
});
self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect();
// self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect();
self.styled_help_text = styled_help_spans;
}
pub fn draw_data<B: Backend>(
@ -251,36 +252,44 @@ impl Painter {
let dd_text = self.get_dd_spans(app_state);
let (text_width, text_height) = if let Some(dd_text) = &dd_text {
let width = if f.size().width < 100 {
let (text_width, text_height) = (
if f.size().width < 100 {
f.size().width * 90 / 100
} else {
let min_possible_width = (f.size().width * 50 / 100) as usize;
let mut width = dd_text.width();
f.size().width * 50 / 100
},
7,
);
// let (text_width, text_height) = if let Some(dd_text) = &dd_text {
// let width = if f.size().width < 100 {
// f.size().width * 90 / 100
// } else {
// let min_possible_width = (f.size().width * 50 / 100) as usize;
// let mut width = dd_text.width();
// This should theoretically never allow width to be 0... we can be safe and do an extra check though.
while width > (f.size().width as usize) && width / 2 > min_possible_width {
width /= 2;
}
// // This should theoretically never allow width to be 0... we can be safe and do an extra check though.
// while width > (f.size().width as usize) && width / 2 > min_possible_width {
// width /= 2;
// }
std::cmp::max(width, min_possible_width) as u16
};
// std::cmp::max(width, min_possible_width) as u16
// };
(
width,
(dd_text.height() + 2 + (dd_text.width() / width as usize)) as u16,
)
} else {
// AFAIK this shouldn't happen, unless something went wrong...
(
if f.size().width < 100 {
f.size().width * 90 / 100
} else {
f.size().width * 50 / 100
},
7,
)
};
// (
// width,
// (dd_text.height() + 2 + (dd_text.width() / width as usize)) as u16,
// )
// } else {
// // AFAIK this shouldn't happen, unless something went wrong...
// (
// if f.size().width < 100 {
// f.size().width * 90 / 100
// } else {
// f.size().width * 50 / 100
// },
// 7,
// )
// };
let vertical_bordering = f.size().height.saturating_sub(text_height) / 2;
let vertical_dialog_chunk = Layout::default()

View file

@ -85,7 +85,7 @@ impl CanvasColours {
}
pub fn set_table_header_colour(&mut self, colour: &str) -> error::Result<()> {
self.table_header_style = get_style_from_config(colour)?.add_modifier(Modifier::BOLD);
self.table_header_style = get_style_from_config(colour)?.modifier(Modifier::BOLD);
Ok(())
}

View file

@ -2,8 +2,7 @@ use tui::{
backend::Backend,
layout::{Alignment, Rect},
terminal::Frame,
text::{Span, Spans, Text},
widgets::{Block, Borders, Paragraph, Wrap},
widgets::{Block, Borders, Paragraph, Text},
};
use crate::{app::App, canvas::Painter};
@ -12,61 +11,58 @@ const DD_BASE: &str = " Confirm Kill Process ── Esc to close ";
const DD_ERROR_BASE: &str = " Error ── Esc to close ";
pub trait KillDialog {
fn get_dd_spans(&self, app_state: &App) -> Option<Text<'_>>;
fn get_dd_spans(&self, app_state: &App) -> Option<Vec<Text<'_>>>;
fn draw_dd_dialog<B: Backend>(
&self, f: &mut Frame<'_, B>, dd_text: Option<Text<'_>>, app_state: &App, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, dd_text: Option<Vec<Text<'_>>>, app_state: &App,
draw_loc: Rect,
) -> bool;
}
impl KillDialog for Painter {
fn get_dd_spans(&self, app_state: &App) -> Option<Text<'_>> {
fn get_dd_spans(&self, app_state: &App) -> Option<Vec<Text<'_>>> {
if let Some(dd_err) = &app_state.dd_err {
return Some(Text::from(Spans::from(format!(
"Failure to properly kill the process - {}",
dd_err
))));
return Some(vec![
Text::raw("\n"),
Text::raw(format!("Failure to properly kill the process - {}", dd_err)),
]);
} else if let Some(to_kill_processes) = app_state.get_to_delete_processes() {
if let Some(first_pid) = to_kill_processes.1.first() {
return Some(Text::from(vec![
Spans::from(vec![]),
Spans::from(vec![
if app_state.is_grouped(app_state.current_widget.widget_id) {
if to_kill_processes.1.len() != 1 {
Span::from(format!(
"Kill {} processes with the name \"{}\"?",
to_kill_processes.1.len(),
to_kill_processes.0
))
} else {
Span::from(format!(
"Kill 1 process with the name \"{}\"?",
to_kill_processes.0
))
}
} else {
Span::from(format!(
"Kill process \"{}\" with PID {}?",
to_kill_processes.0, first_pid
return Some(vec![
Text::raw("\n"),
if app_state.is_grouped(app_state.current_widget.widget_id) {
if to_kill_processes.1.len() != 1 {
Text::raw(format!(
"Kill {} processes with the name \"{}\"?",
to_kill_processes.1.len(),
to_kill_processes.0
))
},
]),
Spans::from(vec![]),
Spans::from(vec![
if app_state.delete_dialog_state.is_on_yes {
Span::styled("Yes", self.colours.currently_selected_text_style)
} else {
Span::from("Yes")
},
Span::from(" "),
if app_state.delete_dialog_state.is_on_yes {
Span::from("No")
} else {
Span::styled("No", self.colours.currently_selected_text_style)
},
]),
Spans::from(vec![]),
]));
Text::raw(format!(
"Kill 1 process with the name \"{}\"?",
to_kill_processes.0
))
}
} else {
Text::raw(format!(
"Kill process \"{}\" with PID {}?",
to_kill_processes.0, first_pid
))
},
Text::raw("\n\n"),
if app_state.delete_dialog_state.is_on_yes {
Text::styled("Yes", self.colours.currently_selected_text_style)
} else {
Text::raw("Yes")
},
Text::raw(" "),
if app_state.delete_dialog_state.is_on_yes {
Text::raw("No")
} else {
Text::styled("No", self.colours.currently_selected_text_style)
},
Text::raw("\n"),
]);
}
}
@ -74,44 +70,63 @@ impl KillDialog for Painter {
}
fn draw_dd_dialog<B: Backend>(
&self, f: &mut Frame<'_, B>, dd_text: Option<Text<'_>>, app_state: &App, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, dd_text: Option<Vec<Text<'_>>>, app_state: &App,
draw_loc: Rect,
) -> bool {
if let Some(dd_text) = dd_text {
// let dd_title = if app_state.dd_err.is_some() {
// Text::styled(
// format!(
// " Error ─{}─ Esc to close ",
// "─".repeat(
// usize::from(draw_loc.width)
// .saturating_sub(DD_ERROR_BASE.chars().count() + 2)
// )
// ),
// self.colours.border_style,
// )
// } else {
// Text::styled(
// format!(
// " Confirm Kill Process ─{}─ Esc to close ",
// "─".repeat(
// usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
// )
// ),
// self.colours.border_style,
// )
// };
let dd_title = if app_state.dd_err.is_some() {
Span::styled(
format!(
" Error ─{}─ Esc to close ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(DD_ERROR_BASE.chars().count() + 2)
)
),
self.colours.border_style,
format!(
" Error ─{}─ Esc to close ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(DD_ERROR_BASE.chars().count() + 2)
)
)
} else {
Span::styled(
format!(
" Confirm Kill Process ─{}─ Esc to close ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
)
),
self.colours.border_style,
format!(
" Confirm Kill Process ─{}─ Esc to close ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
)
)
};
f.render_widget(
Paragraph::new(dd_text)
Paragraph::new(dd_text.iter())
.block(
Block::default()
.title(dd_title)
.title(&dd_title)
.title_style(self.colours.border_style)
.style(self.colours.border_style)
.borders(Borders::ALL)
.border_style(self.colours.border_style),
)
.style(self.colours.text_style)
.alignment(Alignment::Center)
.wrap(Wrap { trim: true }),
.wrap(true),
draw_loc,
);

View file

@ -4,8 +4,7 @@ use tui::{
backend::Backend,
layout::{Alignment, Rect},
terminal::Frame,
text::Span,
widgets::{Block, Borders, Paragraph, Wrap},
widgets::{Block, Borders, Paragraph},
};
use crate::{app::App, canvas::Painter, constants};
@ -22,14 +21,19 @@ impl HelpDialog for Painter {
fn draw_help_dialog<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect,
) {
let help_title = Span::styled(
format!(
" Help ─{}─ Esc to close ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2)
)
),
self.colours.border_style,
// let help_title = Text::styled(
// format!(
// " Help ─{}─ Esc to close ",
// "─".repeat(
// usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2)
// )
// ),
// self.colours.border_style,
// );
let help_title = format!(
" Help ─{}─ Esc to close ",
"".repeat(usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2))
);
if app_state.is_force_redraw {
@ -95,24 +99,24 @@ impl HelpDialog for Painter {
}
f.render_widget(
Paragraph::new(self.styled_help_text.clone())
Paragraph::new(self.styled_help_text.iter())
.block(
Block::default()
.title(help_title)
.title(&help_title)
.title_style(self.colours.border_style)
.style(self.colours.border_style)
.borders(Borders::ALL)
.border_style(self.colours.border_style),
)
.style(self.colours.text_style)
.alignment(Alignment::Left)
.wrap(Wrap { trim: true })
.scroll((
.wrap(true)
.scroll(
app_state
.help_dialog_state
.scroll_state
.current_scroll_index,
0,
)),
),
draw_loc,
);
}

View file

@ -10,8 +10,7 @@ use tui::{
backend::Backend,
layout::{Constraint, Layout, Rect},
terminal::Frame,
text::{Span, Spans},
widgets::{Block, Paragraph},
widgets::{Block, Paragraph, Text},
};
pub trait BasicTableArrows {
@ -98,12 +97,10 @@ impl BasicTableArrows for Painter {
usize::from(draw_loc.width).saturating_sub(6 + left_name.len() + right_name.len());
let arrow_text = vec![
Spans::from(Span::from(String::default())),
Spans::from(vec![
Span::styled(format!("{}", left_name), self.colours.text_style),
Span::from(" ".repeat(num_spaces)),
Span::styled(format!("{}", right_name), self.colours.text_style),
]),
Text::raw("\n"),
Text::styled(format!("{}", left_name), self.colours.text_style),
Text::raw(" ".repeat(num_spaces)),
Text::styled(format!("{}", right_name), self.colours.text_style),
];
let margined_draw_loc = Layout::default()
@ -112,7 +109,7 @@ impl BasicTableArrows for Painter {
.split(draw_loc);
f.render_widget(
Paragraph::new(arrow_text).block(Block::default()),
Paragraph::new(arrow_text.iter()).block(Block::default()),
margined_draw_loc[0],
);
}

View file

@ -8,8 +8,7 @@ use tui::{
backend::Backend,
layout::{Constraint, Rect},
terminal::Frame,
text::{Span, Spans},
widgets::{Block, Borders, Paragraph, Row, Table, Tabs},
widgets::{Block, Borders, Paragraph, Row, Table, Tabs, Text},
};
pub trait BatteryDisplayWidget {
@ -34,25 +33,45 @@ impl BatteryDisplayWidget for Painter {
self.colours.border_style
};
// let title = if app_state.is_expanded {
// const TITLE_BASE: &str = " Battery ── Esc to go back ";
// Span::styled(
// format!(
// " Battery ─{}─ Esc to go back ",
// "─".repeat(
// usize::from(draw_loc.width)
// .saturating_sub(TITLE_BASE.chars().count() + 2)
// )
// ),
// border_and_title_style,
// )
// } else {
// Span::styled(" Battery ".to_string(), self.colours.widget_title_style)
// };
let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Battery ── Esc to go back ";
Span::styled(
format!(
" Battery ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
border_and_title_style,
format!(
" Battery ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else {
Span::styled(" Battery ".to_string(), self.colours.widget_title_style)
" Battery ".to_string()
};
let title_style = if app_state.is_expanded {
border_and_title_style
} else {
self.colours.widget_title_style
};
let battery_block = if draw_border {
Block::default()
.title(title)
.title(&title)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(border_and_title_style)
} else if is_on_widget {
@ -63,22 +82,32 @@ impl BatteryDisplayWidget for Painter {
Block::default().borders(Borders::NONE)
};
f.render_widget(
Tabs::new(
(app_state
.canvas_data
.battery_data
.iter()
.map(|battery| Spans::from(battery.battery_name.clone())))
.collect::<Vec<_>>(),
)
.block(battery_block.clone())
.divider(tui::symbols::line::VERTICAL)
.style(self.colours.text_style)
.highlight_style(self.colours.currently_selected_text_style)
.select(battery_widget_state.currently_selected_battery_index),
draw_loc,
);
// f.render_widget(
// // Tabs::new(
// // (app_state
// // .canvas_data
// // .battery_data
// // .iter()
// // .map(|battery| Spans::from(battery.battery_name.clone())))
// // .collect::<Vec<_>>(),
// // )
// Tabs::default()
// .titles(
// app_state
// .canvas_data
// .battery_data
// .iter()
// .map(|battery| &battery.battery_name)
// .collect::<Vec<_>>()
// .as_ref(),
// )
// .block(battery_block)
// .divider(tui::symbols::line::VERTICAL)
// .style(self.colours.text_style)
// .highlight_style(self.colours.currently_selected_text_style)
// .select(battery_widget_state.currently_selected_battery_index),
// draw_loc,
// );
if let Some(battery_details) = app_state
.canvas_data
@ -134,21 +163,52 @@ impl BatteryDisplayWidget for Painter {
// Draw
f.render_widget(
Table::new([""].iter(), battery_rows)
.block(battery_block.clone())
.block(battery_block)
.header_style(self.colours.table_header_style)
.widths([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()),
draw_loc,
);
} else {
f.render_widget(
Paragraph::new(Spans::from(Span::styled(
"No data found for this battery",
self.colours.text_style,
)))
Paragraph::new(
[Text::styled(
"No data found for this battery",
self.colours.text_style,
)]
.iter(),
)
.block(battery_block),
draw_loc,
);
}
// Has to be placed AFTER for tui 0.9, place BEFORE for 0.10.
f.render_widget(
// Tabs::new(
// (app_state
// .canvas_data
// .battery_data
// .iter()
// .map(|battery| Spans::from(battery.battery_name.clone())))
// .collect::<Vec<_>>(),
// )
Tabs::default()
.titles(
app_state
.canvas_data
.battery_data
.iter()
.map(|battery| &battery.battery_name)
.collect::<Vec<_>>()
.as_ref(),
)
.block(battery_block)
.divider(tui::symbols::line::VERTICAL)
.style(self.colours.text_style)
.highlight_style(self.colours.currently_selected_text_style)
.select(battery_widget_state.currently_selected_battery_index),
draw_loc,
);
}
}
}

View file

@ -11,8 +11,7 @@ use tui::{
backend::Backend,
layout::{Constraint, Direction, Layout, Rect},
terminal::Frame,
text::{Span, Spans},
widgets::{Block, Paragraph},
widgets::{Block, Paragraph, Text},
};
pub trait CpuBasicWidget {
@ -77,10 +76,10 @@ impl CpuBasicWidget for Painter {
let num_bars = calculate_basic_use_bars(use_percentage, bar_length);
format!(
"{:3}[{}{}{:3.0}%]",
"{:3}[{}{}{:3.0}%]\n",
if app_state.app_config_fields.show_average_cpu {
if cpu_index == 0 {
" AVG".to_string()
"AVG".to_string()
} else {
(cpu_index - 1).to_string()
}
@ -109,11 +108,16 @@ impl CpuBasicWidget for Painter {
let end_index = min(start_index + how_many_cpus, num_cpus);
let cpu_column = (start_index..end_index)
.map(|cpu_index| {
Spans::from(Span {
content: (&cpu_bars[cpu_index]).into(),
style: self.colours.cpu_colour_styles
// Spans::from(Span {
// content: (&cpu_bars[cpu_index]).into(),
// style: self.colours.cpu_colour_styles
// [cpu_index % self.colours.cpu_colour_styles.len()],
// })
Text::styled(
&cpu_bars[cpu_index],
self.colours.cpu_colour_styles
[cpu_index % self.colours.cpu_colour_styles.len()],
})
)
})
.collect::<Vec<_>>();
@ -126,7 +130,7 @@ impl CpuBasicWidget for Painter {
.split(*chunk);
f.render_widget(
Paragraph::new(cpu_column).block(Block::default()),
Paragraph::new(cpu_column.iter()).block(Block::default()),
margined_loc[0],
);
}

View file

@ -17,7 +17,6 @@ use tui::{
layout::{Constraint, Direction, Layout, Rect},
symbols::Marker,
terminal::Frame,
text::Span,
widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table},
};
@ -104,12 +103,17 @@ impl CpuGraphWidget for Painter {
if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&widget_id) {
let cpu_data: &mut [ConvertedCpuData] = &mut app_state.canvas_data.cpu_data;
let display_time_labels = vec![
Span::styled(
format!("{}s", cpu_widget_state.current_display_time / 1000),
self.colours.graph_style,
),
Span::styled("0s".to_string(), self.colours.graph_style),
// let display_time_labels = vec![
// Text::styled(
// format!("{}s", cpu_widget_state.current_display_time / 1000),
// self.colours.graph_style,
// ),
// Text::styled("0s".to_string(), self.colours.graph_style),
// ];
let display_time_labels = [
format!("{}s", cpu_widget_state.current_display_time / 1000),
"0s".to_string(),
];
let x_axis = if app_state.app_config_fields.hide_time
@ -124,7 +128,8 @@ impl CpuGraphWidget for Painter {
Axis::default()
.bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style)
.labels(display_time_labels)
.labels(&display_time_labels)
.labels_style(self.colours.graph_style)
} else {
cpu_widget_state.autohide_timer = None;
Axis::default().bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
@ -135,17 +140,16 @@ impl CpuGraphWidget for Painter {
Axis::default()
.bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style)
.labels(display_time_labels)
.labels(&display_time_labels)
.labels_style(self.colours.graph_style)
};
// Note this is offset as otherwise the 0 value is not drawn!
let y_axis = Axis::default()
.style(self.colours.graph_style)
.bounds([-0.5, 100.5])
.labels(vec![
Span::styled("0%", self.colours.graph_style),
Span::styled("100%", self.colours.graph_style),
]);
.labels_style(self.colours.graph_style)
.labels(&["0%", "100%"]);
let use_dot = app_state.app_config_fields.use_dot;
let show_avg_cpu = app_state.app_config_fields.show_average_cpu;
@ -199,17 +203,26 @@ impl CpuGraphWidget for Painter {
self.colours.border_style
};
let title = if app_state.is_expanded {
Span::styled(" CPU ".to_string(), border_style)
// let title = if app_state.is_expanded {
// Span::styled(" CPU ".to_string(), border_style)
// } else {
// Span::styled(" CPU ".to_string(), self.colours.widget_title_style)
// };
let title = " CPU ";
let title_style = if app_state.is_expanded {
border_style
} else {
Span::styled(" CPU ".to_string(), self.colours.widget_title_style)
self.colours.widget_title_style
};
f.render_widget(
Chart::new(dataset_vector)
// Chart::new(dataset_vector)
Chart::default()
.datasets(&dataset_vector)
.block(
Block::default()
.title(title)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(border_style),
)

View file

@ -4,7 +4,6 @@ use tui::{
backend::Backend,
layout::{Constraint, Direction, Layout, Rect},
terminal::Frame,
text::Span,
widgets::{Block, Borders, Row, Table},
};
@ -77,27 +76,48 @@ impl DiskTableWidget for Painter {
(self.colours.border_style, self.colours.text_style)
};
// let title = if app_state.is_expanded {
// const TITLE_BASE: &str = " Disk ── Esc to go back ";
// Span::styled(
// format!(
// " Disk ─{}─ Esc to go back ",
// "─".repeat(
// usize::from(draw_loc.width)
// .saturating_sub(TITLE_BASE.chars().count() + 2)
// )
// ),
// border_and_title_style,
// )
// } else if app_state.app_config_fields.use_basic_mode {
// Span::from(String::new())
// } else {
// Span::styled(" Disk ".to_string(), self.colours.widget_title_style)
// };
let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Disk ── Esc to go back ";
Span::styled(
format!(
" Disk ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
border_and_title_style,
format!(
" Disk ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else if app_state.app_config_fields.use_basic_mode {
Span::from(String::new())
String::new()
} else {
Span::styled(" Disk ".to_string(), self.colours.widget_title_style)
" Disk ".to_string()
};
let title_style = if app_state.is_expanded {
border_and_title_style
} else {
self.colours.widget_title_style
};
let disk_block = if draw_border {
Block::default()
.title(title)
.title(&title)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(border_and_title_style)
} else if is_on_widget {

View file

@ -8,8 +8,7 @@ use tui::{
backend::Backend,
layout::{Constraint, Layout, Rect},
terminal::Frame,
text::{Span, Spans},
widgets::{Block, Paragraph},
widgets::{Block, Paragraph, Text},
};
pub trait MemBasicWidget {
@ -54,7 +53,7 @@ impl MemBasicWidget for Painter {
let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, bar_length);
let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, bar_length);
let mem_label = format!(
"RAM[{}{}{:3.0}%]",
"RAM[{}{}{:3.0}%]\n",
"|".repeat(num_bars_ram),
" ".repeat(bar_length - num_bars_ram),
ram_use_percentage.round(),
@ -66,13 +65,13 @@ impl MemBasicWidget for Painter {
swap_use_percentage.round(),
);
let mem_text = vec![
Spans::from(Span::styled(mem_label, self.colours.ram_style)),
Spans::from(Span::styled(swap_label, self.colours.swap_style)),
let mem_text = [
Text::styled(mem_label, self.colours.ram_style),
Text::styled(swap_label, self.colours.swap_style),
];
f.render_widget(
Paragraph::new(mem_text).block(Block::default()),
Paragraph::new(mem_text.iter()).block(Block::default()),
margined_loc[0],
);
}

View file

@ -5,7 +5,6 @@ use tui::{
layout::{Constraint, Rect},
symbols::Marker,
terminal::Frame,
text::Span,
widgets::{Axis, Block, Borders, Chart, Dataset},
};
@ -23,12 +22,9 @@ impl MemGraphWidget for Painter {
let mem_data: &[(f64, f64)] = &app_state.canvas_data.mem_data;
let swap_data: &[(f64, f64)] = &app_state.canvas_data.swap_data;
let display_time_labels = vec![
Span::styled(
format!("{}s", mem_widget_state.current_display_time / 1000),
self.colours.graph_style,
),
Span::styled("0s".to_string(), self.colours.graph_style),
let display_time_labels = [
format!("{}s", mem_widget_state.current_display_time / 1000),
"0s".to_string(),
];
let x_axis = if app_state.app_config_fields.hide_time
|| (app_state.app_config_fields.autohide_time
@ -42,7 +38,8 @@ impl MemGraphWidget for Painter {
Axis::default()
.bounds([-(mem_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style)
.labels(display_time_labels)
.labels(&display_time_labels)
.labels_style(self.colours.graph_style)
} else {
mem_widget_state.autohide_timer = None;
Axis::default().bounds([-(mem_widget_state.current_display_time as f64), 0.0])
@ -53,17 +50,16 @@ impl MemGraphWidget for Painter {
Axis::default()
.bounds([-(mem_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style)
.labels(display_time_labels)
.labels(&display_time_labels)
.labels_style(self.colours.graph_style)
};
// Offset as the zero value isn't drawn otherwise...
let y_axis = Axis::default()
.style(self.colours.graph_style)
.bounds([-0.5, 100.5])
.labels(vec![
Span::styled("0%", self.colours.graph_style),
Span::styled("100%", self.colours.graph_style),
]);
.labels(&["0%", "100%"])
.labels_style(self.colours.graph_style);
let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![];
@ -95,25 +91,29 @@ impl MemGraphWidget for Painter {
let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Memory ── Esc to go back ";
Span::styled(
format!(
" Memory ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
self.colours.highlighted_border_style,
format!(
" Memory ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else {
Span::styled(" Memory ".to_string(), self.colours.widget_title_style)
" Memory ".to_string()
};
let title_style = if app_state.is_expanded {
self.colours.highlighted_border_style
} else {
self.colours.widget_title_style
};
f.render_widget(
Chart::new(mem_canvas_vec)
// Chart::new(mem_canvas_vec)
Chart::default()
.datasets(&mem_canvas_vec)
.block(
Block::default()
.title(title)
.title(&title)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(if app_state.current_widget.widget_id == widget_id {
self.colours.highlighted_border_style

View file

@ -4,8 +4,7 @@ use tui::{
backend::Backend,
layout::{Constraint, Direction, Layout, Rect},
terminal::Frame,
text::{Span, Spans},
widgets::{Block, Paragraph},
widgets::{Block, Paragraph, Text},
};
pub trait NetworkBasicWidget {
@ -44,25 +43,28 @@ impl NetworkBasicWidget for Painter {
);
}
let rx_label = format!("RX: {}", &app_state.canvas_data.rx_display);
let rx_label = format!("RX: {}\n", &app_state.canvas_data.rx_display);
let tx_label = format!("TX: {}", &app_state.canvas_data.tx_display);
let total_rx_label = format!("Total RX: {}", &app_state.canvas_data.total_rx_display);
let total_rx_label = format!("Total RX: {}\n", &app_state.canvas_data.total_rx_display);
let total_tx_label = format!("Total TX: {}", &app_state.canvas_data.total_tx_display);
let net_text = vec![
Spans::from(Span::styled(rx_label, self.colours.rx_style)),
Spans::from(Span::styled(tx_label, self.colours.tx_style)),
let net_text = [
Text::styled(rx_label, self.colours.rx_style),
Text::styled(tx_label, self.colours.tx_style),
];
let total_net_text = vec![
Spans::from(Span::styled(total_rx_label, self.colours.total_rx_style)),
Spans::from(Span::styled(total_tx_label, self.colours.total_tx_style)),
let total_net_text = [
Text::styled(total_rx_label, self.colours.total_rx_style),
Text::styled(total_tx_label, self.colours.total_tx_style),
];
f.render_widget(Paragraph::new(net_text).block(Block::default()), net_loc[0]);
f.render_widget(
Paragraph::new(total_net_text).block(Block::default()),
Paragraph::new(net_text.iter()).block(Block::default()),
net_loc[0],
);
f.render_widget(
Paragraph::new(total_net_text.iter()).block(Block::default()),
total_loc[0],
);
}

View file

@ -12,7 +12,6 @@ use tui::{
layout::{Constraint, Direction, Layout, Rect},
symbols::Marker,
terminal::Frame,
text::Span,
widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table},
};
@ -72,12 +71,9 @@ impl NetworkGraphWidget for Painter {
let network_data_rx: &[(f64, f64)] = &app_state.canvas_data.network_data_rx;
let network_data_tx: &[(f64, f64)] = &app_state.canvas_data.network_data_tx;
let display_time_labels = vec![
Span::styled(
format!("{}s", network_widget_state.current_display_time / 1000),
self.colours.graph_style,
),
Span::styled("0s".to_string(), self.colours.graph_style),
let display_time_labels = [
format!("{}s", network_widget_state.current_display_time / 1000),
"0s".to_string(),
];
let x_axis = if app_state.app_config_fields.hide_time
|| (app_state.app_config_fields.autohide_time
@ -91,7 +87,8 @@ impl NetworkGraphWidget for Painter {
Axis::default()
.bounds([-(network_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style)
.labels(display_time_labels)
.labels(&display_time_labels)
.labels_style(self.colours.graph_style)
} else {
network_widget_state.autohide_timer = None;
Axis::default()
@ -103,35 +100,33 @@ impl NetworkGraphWidget for Painter {
Axis::default()
.bounds([-(network_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style)
.labels(display_time_labels)
.labels(&display_time_labels)
.labels_style(self.colours.graph_style)
};
// 0 is offset.
let y_axis_labels = vec![
Span::styled("0B", self.colours.graph_style),
Span::styled("1KiB", self.colours.graph_style),
Span::styled("1MiB", self.colours.graph_style),
Span::styled("1GiB", self.colours.graph_style),
];
let y_axis_labels = ["0B", "1KiB", "1MiB", "1GiB"];
let y_axis = Axis::default()
.style(self.colours.graph_style)
.bounds([-0.5, 30_f64])
.labels(y_axis_labels);
.labels(&y_axis_labels)
.labels_style(self.colours.graph_style);
let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Network ── Esc to go back ";
Span::styled(
format!(
" Network ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
self.colours.highlighted_border_style,
format!(
" Network ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else {
Span::styled(" Network ".to_string(), self.colours.widget_title_style)
" Network ".to_string()
};
let title_style = if app_state.is_expanded {
self.colours.highlighted_border_style
} else {
self.colours.widget_title_style
};
let legend_constraints = if hide_legend {
@ -142,7 +137,6 @@ impl NetworkGraphWidget for Painter {
let dataset = if app_state.app_config_fields.use_old_network_legend && !hide_legend {
let mut ret_val = vec![];
ret_val.push(
Dataset::default()
.name(format!("RX: {:7}", app_state.canvas_data.rx_display))
@ -220,10 +214,13 @@ impl NetworkGraphWidget for Painter {
};
f.render_widget(
Chart::new(dataset)
// Chart::new(dataset)
Chart::default()
.datasets(&dataset)
.block(
Block::default()
.title(title)
.title(&title)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(if app_state.current_widget.widget_id == widget_id {
self.colours.highlighted_border_style

View file

@ -13,8 +13,7 @@ use tui::{
backend::Backend,
layout::{Alignment, Constraint, Direction, Layout, Rect},
terminal::Frame,
text::{Span, Spans},
widgets::{Block, Borders, Paragraph, Row, Table},
widgets::{Block, Borders, Paragraph, Row, Table, Text},
};
use unicode_segmentation::{GraphemeIndices, UnicodeSegmentation};
@ -225,26 +224,30 @@ impl ProcessTableWidget for Painter {
&& !proc_widget_state.is_sort_open
{
const TITLE_BASE: &str = " Processes ── Esc to go back ";
Span::styled(
format!(
" Processes ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
border_and_title_style,
format!(
" Processes ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else {
Span::styled(" Processes ".to_string(), self.colours.widget_title_style)
" Processes ".to_string()
}
} else {
Span::from(String::default())
String::default()
};
let title_style = if app_state.is_expanded {
border_and_title_style
} else {
self.colours.widget_title_style
};
let process_block = if draw_border {
Block::default()
.title(title)
.title(&title)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(border_and_title_style)
} else if is_on_widget {
@ -291,7 +294,7 @@ impl ProcessTableWidget for Painter {
is_on_widget: bool, grapheme_indices: GraphemeIndices<'a>, start_position: usize,
cursor_position: usize, query: &str, currently_selected_text_style: tui::style::Style,
text_style: tui::style::Style,
) -> Vec<Span<'a>> {
) -> Vec<Text<'a>> {
let mut current_grapheme_posn = 0;
if is_on_widget {
@ -303,9 +306,9 @@ impl ProcessTableWidget for Painter {
None
} else {
let styled = if grapheme.0 == cursor_position {
Span::styled(grapheme.1, currently_selected_text_style)
Text::styled(grapheme.1, currently_selected_text_style)
} else {
Span::styled(grapheme.1, text_style)
Text::styled(grapheme.1, text_style)
};
Some(styled)
}
@ -313,7 +316,7 @@ impl ProcessTableWidget for Painter {
.collect::<Vec<_>>();
if cursor_position >= query.len() {
res.push(Span::styled(" ", currently_selected_text_style))
res.push(Text::styled(" ", currently_selected_text_style))
}
res
@ -327,7 +330,7 @@ impl ProcessTableWidget for Painter {
if current_grapheme_posn <= start_position {
None
} else {
let styled = Span::styled(grapheme.1, text_style);
let styled = Text::styled(grapheme.1, text_style);
Some(styled)
}
})
@ -373,8 +376,8 @@ impl ProcessTableWidget for Painter {
self.colours.text_style,
);
let mut search_text = vec![Spans::from({
let mut search_vec = vec![Span::styled(
let mut search_text = {
let mut search_vec = vec![Text::styled(
search_title,
if is_on_widget {
self.colours.table_header_style
@ -384,7 +387,7 @@ impl ProcessTableWidget for Painter {
)];
search_vec.extend(query_with_cursor);
search_vec
})];
};
// Text options shamelessly stolen from VS Code.
let case_style = if !proc_widget_state.process_search_state.is_ignoring_case {
@ -411,24 +414,25 @@ impl ProcessTableWidget for Painter {
self.colours.text_style
};
let option_text = Spans::from(vec![
Span::styled(
let option_text = vec![
Text::raw("\n"),
Text::styled(
format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" }),
case_style,
),
Span::from(" "),
Span::styled(
Text::raw(" "),
Text::styled(
format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" }),
whole_word_style,
),
Span::from(" "),
Span::styled(
Text::raw(" "),
Text::styled(
format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" }),
regex_style,
),
]);
];
search_text.push(Spans::from(Span::styled(
search_text.push(Text::styled(
if let Some(err) = &proc_widget_state
.process_search_state
.search_state
@ -439,8 +443,8 @@ impl ProcessTableWidget for Painter {
""
},
self.colours.invalid_query_style,
)));
search_text.push(option_text);
));
search_text.extend(option_text);
let current_border_style = if proc_widget_state
.process_search_state
@ -459,17 +463,15 @@ impl ProcessTableWidget for Painter {
let repeat_num =
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2);
Span::styled(
format!("{} Esc to close ", "".repeat(repeat_num)),
current_border_style,
)
format!("{} Esc to close ", "".repeat(repeat_num))
} else {
Span::from(String::new())
String::new()
};
let process_search_block = if draw_border {
Block::default()
.title(title)
.title(&title)
.title_style(current_border_style)
.borders(Borders::ALL)
.border_style(current_border_style)
} else if is_on_widget {
@ -487,7 +489,7 @@ impl ProcessTableWidget for Painter {
.split(draw_loc);
f.render_widget(
Paragraph::new(search_text)
Paragraph::new(search_text.iter())
.block(process_search_block)
.style(self.colours.text_style)
.alignment(Alignment::Left),

View file

@ -5,7 +5,6 @@ use tui::{
backend::Backend,
layout::{Constraint, Direction, Layout, Rect},
terminal::Frame,
text::Span,
widgets::{Block, Borders, Row, Table},
};
@ -79,28 +78,27 @@ impl TempTableWidget for Painter {
let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Temperatures ── Esc to go back ";
Span::styled(
format!(
" Temperatures ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width)
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
border_and_title_style,
format!(
" Temperatures ─{}─ Esc to go back ",
"".repeat(
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
)
)
} else if app_state.app_config_fields.use_basic_mode {
Span::from(String::new())
String::new()
} else {
Span::styled(
" Temperatures ".to_string(),
self.colours.widget_title_style,
)
" Temperatures ".to_string()
};
let title_style = if app_state.is_expanded {
border_and_title_style
} else {
self.colours.widget_title_style
};
let temp_block = if draw_border {
Block::default()
.title(title)
.title(&title)
.title_style(title_style)
.borders(Borders::ALL)
.border_style(border_and_title_style)
} else if is_on_widget {

View file

@ -43,126 +43,126 @@ lazy_static! {
// Help text
pub const HELP_CONTENTS_TEXT: [&str; 7] = [
"Press the corresponding numbers to jump to the section, or scroll:",
"1 - General",
"2 - CPU widget",
"3 - Process widget",
"4 - Process search widget",
"5 - Process sort widget",
"Press the corresponding numbers to jump to the section, or scroll:\n",
"1 - General\n",
"2 - CPU widget\n",
"3 - Process widget\n",
"4 - Process search widget\n",
"5 - Process sort widget\n",
"6 - Battery widget",
];
pub const GENERAL_HELP_TEXT: [&str; 29] = [
"1 - General",
"q, Ctrl-c Quit",
"Esc Close dialog windows, search, widgets, or exit expanded mode",
"Ctrl-r Reset display and any collected data",
"f Freeze/unfreeze updating with new data",
"Ctrl-Left, ",
"Shift-Left, Move widget selection left",
"H, A ",
"Ctrl-Right, ",
"Shift-Right, Move widget selection right",
"L, D ",
"Ctrl-Up, ",
"Shift-Up, Move widget selection up",
"K, W ",
"Ctrl-Down, ",
"Shift-Down, Move widget selection down",
"J, S ",
"Left, h Move left within widget",
"Down, j Move down within widget",
"Up, k Move up within widget",
"Right, l Move right within widget",
"? Open help menu",
"gg Jump to the first entry",
"G Jump to the last entry",
"e Expand the currently selected widget",
"+ Zoom in on chart (decrease time range)",
"- Zoom out on chart (increase time range)",
"= Reset zoom",
"1 - General\n",
"q, Ctrl-c Quit\n",
"Esc Close dialog windows, search, widgets, or exit expanded mode\n",
"Ctrl-r Reset display and any collected data\n",
"f Freeze/unfreeze updating with new data\n",
"Ctrl-Left, \n",
"Shift-Left, Move widget selection left\n",
"H, A \n",
"Ctrl-Right, \n",
"Shift-Right, Move widget selection right\n",
"L, D \n",
"Ctrl-Up, \n",
"Shift-Up, Move widget selection up\n",
"K, W \n",
"Ctrl-Down, \n",
"Shift-Down, Move widget selection down\n",
"J, S \n",
"Left, h Move left within widget\n",
"Down, j Move down within widget\n",
"Up, k Move up within widget\n",
"Right, l Move right within widget\n",
"? Open help menu\n",
"gg Jump to the first entry\n",
"G Jump to the last entry\n",
"e Expand the currently selected widget\n",
"+ Zoom in on chart (decrease time range)\n",
"- Zoom out on chart (increase time range)\n",
"= Reset zoom\n",
"Mouse scroll Scroll through the tables or zoom in/out of charts by scrolling up/down",
];
pub const CPU_HELP_TEXT: [&str; 2] = [
"2 - CPU widget",
"2 - CPU widget\n",
"Mouse scroll Scrolling over an CPU core/average shows only that entry on the chart",
];
// TODO [Help]: Search in help?
// TODO [Help]: Move to using tables for easier formatting?
pub const PROCESS_HELP_TEXT: [&str; 11] = [
"3 - Process widget",
"dd Kill the selected process",
"c Sort by CPU usage, press again to reverse sorting order",
"m Sort by memory usage, press again to reverse sorting order",
"p Sort by PID name, press again to reverse sorting order",
"n Sort by process name, press again to reverse sorting order",
"Tab Group/un-group processes with the same name",
"Ctrl-f, / Open process search widget",
"P Toggle between showing the full path or just the process name",
"s, F6 Open process sort widget",
"3 - Process widget\n",
"dd Kill the selected process\n",
"c Sort by CPU usage, press again to reverse sorting order\n",
"m Sort by memory usage, press again to reverse sorting order\n",
"p Sort by PID name, press again to reverse sorting order\n",
"n Sort by process name, press again to reverse sorting order\n",
"Tab Group/un-group processes with the same name\n",
"Ctrl-f, / Open process search widget\n",
"P Toggle between showing the full path or just the process name\n",
"s, F6 Open process sort widget\n",
"I Invert current sort",
];
pub const SEARCH_HELP_TEXT: [&str; 43] = [
"4 - Process search widget",
"Tab Toggle between searching for PID and name",
"Esc Close the search widget (retains the filter)",
"Ctrl-a Skip to the start of the search query",
"Ctrl-e Skip to the end of the search query",
"Ctrl-u Clear the current search query",
"Backspace Delete the character behind the cursor",
"Delete Delete the character at the cursor",
"Alt-c/F1 Toggle matching case",
"Alt-w/F2 Toggle matching the entire word",
"Alt-r/F3 Toggle using regex",
"Left, Alt-h Move cursor left",
"Right, Alt-l Move cursor right",
"",
"Search keywords:",
"pid ex: pid 825",
"cpu ex: cpu > 4.2",
"mem ex: mem < 4.2",
"read ex: read >= 1 b",
"write ex: write <= 1 tb",
"tread ex: tread = 1",
"twrite ex: twrite = 1",
"",
"Comparison operators:",
"= ex: cpu = 1",
"> ex: cpu > 1",
"< ex: cpu < 1",
">= ex: cpu >= 1",
"<= ex: cpu <= 1",
"",
"Logical operators:",
"and/&&/<Space> ex: btm and cpu > 1 and mem > 1",
"or/|| ex: btm or firefox",
"",
"Supported units:",
"B ex: read > 1 b",
"KB ex: read > 1 kb",
"MB ex: read > 1 mb",
"TB ex: read > 1 tb",
"KiB ex: read > 1 kib",
"MiB ex: read > 1 mib",
"GiB ex: read > 1 gib",
"4 - Process search widget\n",
"Tab Toggle between searching for PID and name\n",
"Esc Close the search widget (retains the filter)\n",
"Ctrl-a Skip to the start of the search query\n",
"Ctrl-e Skip to the end of the search query\n",
"Ctrl-u Clear the current search query\n",
"Backspace Delete the character behind the cursor\n",
"Delete Delete the character at the cursor\n",
"Alt-c/F1 Toggle matching case\n",
"Alt-w/F2 Toggle matching the entire word\n",
"Alt-r/F3 Toggle using regex\n",
"Left, Alt-h Move cursor left\n",
"Right, Alt-l Move cursor right\n",
"\n",
"Search keywords:\n",
"pid ex: pid 825\n",
"cpu ex: cpu > 4.2\n",
"mem ex: mem < 4.2\n",
"read ex: read >= 1 b\n",
"write ex: write <= 1 tb\n",
"tread ex: tread = 1\n",
"twrite ex: twrite = 1\n",
"\n",
"Comparison operators:\n",
"= ex: cpu = 1\n",
"> ex: cpu > 1\n",
"< ex: cpu < 1\n",
">= ex: cpu >= 1\n",
"<= ex: cpu <= 1\n",
"\n",
"Logical operators:\n",
"and/&&/<Space> ex: btm and cpu > 1 and mem > 1\n",
"or/|| ex: btm or firefox\n",
"\n",
"Supported units:\n",
"B ex: read > 1 b\n",
"KB ex: read > 1 kb\n",
"MB ex: read > 1 mb\n",
"TB ex: read > 1 tb\n",
"KiB ex: read > 1 kib\n",
"MiB ex: read > 1 mib\n",
"GiB ex: read > 1 gib\n",
"TiB ex: read > 1 tib",
];
pub const SORT_HELP_TEXT: [&str; 6] = [
"5 - Sort widget",
"Down, 'j' Scroll down in list",
"Up, 'k' Scroll up in list",
"Mouse scroll Scroll through sort widget",
"Esc Close the sort widget",
"5 - Sort widget\n",
"Down, 'j' Scroll down in list\n",
"Up, 'k' Scroll up in list\n",
"Mouse scroll Scroll through sort widget\n",
"Esc Close the sort widget\n",
"Enter Sort by current selected column",
];
pub const BATTERY_HELP_TEXT: [&str; 3] = [
"6 - Battery widget",
"Left Go to previous battery",
"6 - Battery widget\n",
"Left Go to previous battery\n",
"Right Go to next battery",
];