mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-25 22:55:06 +02:00
Added vim + keyboard bindings.
This commit is contained in:
parent
0550402698
commit
1ebe04ecb2
57
README.md
57
README.md
@ -23,13 +23,29 @@ Currently, I'm unable to test on MacOS, so I'm not sure how well this will work,
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
### Command line options
|
||||||
|
|
||||||
|
* ``-h``, ``--help`` to show the help screen and exit (basically has all of the below CLI option info).
|
||||||
|
|
||||||
|
* ``-a``, ``--avgcpu`` enables showing the average CPU usage on rustop
|
||||||
|
|
||||||
|
* ``-c``, ``--celsius`` displays the temperature type in Celsius. This is the default.
|
||||||
|
|
||||||
|
* ``-f``, ``--fahrenheit`` displays the temperature type in Fahrenheit. This is the default.
|
||||||
|
|
||||||
|
* ``-k``, ``--kelvin`` displays the temperature type in Kelvin. This is the default.
|
||||||
|
|
||||||
|
* ``-v``, ``--version`` displays the version number and exits.
|
||||||
|
|
||||||
|
* ``-r <RATE>``, ``--rate <RATE>`` will set the refresh rate in *milliseconds*. Pick a range from 250ms to ``UINT_MAX``. Defaults to 1000ms, and higher values may take more resources due to more frequent polling of data, and may be less accurate in some circumstances.
|
||||||
|
|
||||||
### Keybinds (some may not be available on certain operating systems)
|
### Keybinds (some may not be available on certain operating systems)
|
||||||
|
|
||||||
#### General
|
#### General
|
||||||
|
|
||||||
* ``q``, ``Esc``, or ``Ctrl-C`` to quit
|
* ``q``, ``Esc``, or ``Ctrl-C`` to quit.
|
||||||
|
|
||||||
* ``Shift-Up/Shift-k``, ``Shift-Down/Shift-j``, ``Shift-Left/Shift-h``, ``Shift-Right/Shift-l`` to navigate between panels
|
* ``Up/k``, ``Down/j``, ``Left/h``, ``Right/l`` to navigate between panels. This currently doesn't have much functionality but will change in the future.
|
||||||
|
|
||||||
#### Processes Panel
|
#### Processes Panel
|
||||||
|
|
||||||
@ -45,16 +61,51 @@ Currently, I'm unable to test on MacOS, so I'm not sure how well this will work,
|
|||||||
|
|
||||||
### Mouse Actions
|
### Mouse Actions
|
||||||
|
|
||||||
* Scrolling either scrolls through the list if the panel is a table (Temperature, Disks, Processes), or zooms in and out if it is a chart
|
[* Scrolling either scrolls through the list if the panel is a table (Temperature, Disks, Processes), or zooms in and out if it is a chart.]: <>
|
||||||
|
|
||||||
|
* Scrolling currently only scrolls through the list if you are on the Processes panel. This will change in the future.
|
||||||
|
|
||||||
|
## Regarding Process Use Percentage (on Linux)
|
||||||
|
|
||||||
|
I cannot guarantee whether they are 100% accurate. I'm using a technique I found online which seems to be a better indicator of process use percentage at the current time, rather than pulling from, say, ``ps`` (which is average CPU usage over the *entire lifespan* of the process). I found the options from the library I used to get other data (heim) to be a bit too inaccurate in my testing.
|
||||||
|
|
||||||
|
For reference, the formula I am using to calculate CPU process usage is along the lines of:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let idle = idle + iowait;
|
||||||
|
let non_idle = user + nice + system + irq + softirq + steal + guest;
|
||||||
|
|
||||||
|
let total = idle + non_idle;
|
||||||
|
let prev_total = prev_idle + prev_non_idle; // Both of these values are calculated using the same formula from the previous polling
|
||||||
|
|
||||||
|
let total_delta : f64 = total - prev_total;
|
||||||
|
let idle_delta : f64 = idle - prev_idle;
|
||||||
|
|
||||||
|
let final_delta : f64 = total_delta - idle_delta;
|
||||||
|
|
||||||
|
//...
|
||||||
|
|
||||||
|
// Get utime and stime from reading /proc/<PID>/stat
|
||||||
|
let after_proc_val = utime + stime;
|
||||||
|
(after_proc_val - before_proc_val) / cpu_usage * 100_f64; //This gives your use percentage. before_proc_val comes from the previous polling
|
||||||
|
```
|
||||||
|
|
||||||
|
Any suggestions on more accurate data is welcome! Note all other fields should be accurate.
|
||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
|
|
||||||
* As mentioned, this project is very much inspired by both [gotop](https://github.com/cjbassi/gotop) and [gtop](https://github.com/aksakalli/gtop) .
|
* As mentioned, this project is very much inspired by both [gotop](https://github.com/cjbassi/gotop) and [gtop](https://github.com/aksakalli/gtop) .
|
||||||
|
|
||||||
* This application was written with the following libraries:
|
* This application was written with the following libraries:
|
||||||
|
* [chrono](https://github.com/chronotope/chrono)
|
||||||
* [clap](https://github.com/clap-rs/clap)
|
* [clap](https://github.com/clap-rs/clap)
|
||||||
* [crossterm](https://github.com/TimonPost/crossterm)
|
* [crossterm](https://github.com/TimonPost/crossterm)
|
||||||
|
* [failure](https://github.com/rust-lang-nursery/failure)
|
||||||
|
* [fern](https://github.com/daboross/fern)
|
||||||
|
* [futures-rs](https://github.com/rust-lang-nursery/futures-rs)
|
||||||
|
* [futures-timer](https://github.com/rustasync/futures-timer)
|
||||||
* [heim](https://github.com/heim-rs/heim)
|
* [heim](https://github.com/heim-rs/heim)
|
||||||
|
* [log](https://github.com/rust-lang-nursery/log)
|
||||||
* [sysinfo](https://github.com/GuillaumeGomez/sysinfo)
|
* [sysinfo](https://github.com/GuillaumeGomez/sysinfo)
|
||||||
* [tokio](https://github.com/tokio-rs/tokio)
|
* [tokio](https://github.com/tokio-rs/tokio)
|
||||||
* [tui-rs](https://github.com/fdehau/tui-rs) (note I used a fork due to some issues I faced, you can find that [here](https://github.com/ClementTsang/tui-rs))
|
* [tui-rs](https://github.com/fdehau/tui-rs) (note I used a fork due to some issues I faced, you can find that [here](https://github.com/ClementTsang/tui-rs))
|
||||||
|
16
TODO.md
16
TODO.md
@ -1,5 +1,7 @@
|
|||||||
# To-Do List
|
# To-Do List
|
||||||
|
|
||||||
|
Note this will probably migrate to GitHub's native Issues; this was mostly for personal use during early stages.
|
||||||
|
|
||||||
## Pre-release (bare minimum)
|
## Pre-release (bare minimum)
|
||||||
|
|
||||||
* ~~Get each function working as a POC~~
|
* ~~Get each function working as a POC~~
|
||||||
@ -14,21 +16,23 @@
|
|||||||
|
|
||||||
~~* Scrolling in at least processes~~
|
~~* Scrolling in at least processes~~
|
||||||
|
|
||||||
* Keybindings
|
* Keybindings - I want to do at least arrow keys and dd.
|
||||||
|
|
||||||
~~* Legend gets in the way at too small of a height... maybe modify tui a bit more to fix this.~~
|
~~* Legend gets in the way at too small of a height... maybe modify tui a bit more to fix this.~~
|
||||||
|
|
||||||
## After making public
|
## After making public
|
||||||
|
|
||||||
|
* Scaling in and out (zoom), may need to show zoom levels
|
||||||
|
|
||||||
|
* More keybinds
|
||||||
|
|
||||||
* Tests
|
* Tests
|
||||||
|
|
||||||
* Mouse + key events conflict? Make it so that some events don't clog up the loop if they are not valid keys!
|
* Mouse + key events conflict? Make it so that some events don't clog up the loop if they are not valid keys!
|
||||||
|
|
||||||
* Header should be clear on current sorting direction!
|
* Header should be clear on current sorting direction!
|
||||||
|
|
||||||
* Scaling in and out (zoom), may need to show zoom levels
|
* It would be maybe a good idea to see if we can run the process calculation across ALL cpus...? Might be more accurate.
|
||||||
|
|
||||||
* It would be maybe a good idea to see if we can run the process calculation across ALL cpus...?
|
|
||||||
|
|
||||||
* ~~Add custom error because it's really messy~~ Done, but need to implement across rest of app!
|
* ~~Add custom error because it's really messy~~ Done, but need to implement across rest of app!
|
||||||
|
|
||||||
@ -52,4 +56,6 @@
|
|||||||
|
|
||||||
* Modularity
|
* Modularity
|
||||||
|
|
||||||
*~~Potentially process managing? Depends on the libraries...~~ Done on Linux!
|
* ~~Potentially process managing? Depends on the libraries...~~ Done on Linux!
|
||||||
|
|
||||||
|
* Probably good to add a "are you sure" to dd-ing...
|
||||||
|
42
src/app.rs
42
src/app.rs
@ -3,8 +3,7 @@ use data_collection::{processes, temperature};
|
|||||||
|
|
||||||
mod process_killer;
|
mod process_killer;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[derive(Clone, Copy)]
|
||||||
// Probably only use the list elements...
|
|
||||||
pub enum ApplicationPosition {
|
pub enum ApplicationPosition {
|
||||||
CPU,
|
CPU,
|
||||||
MEM,
|
MEM,
|
||||||
@ -74,10 +73,6 @@ impl App {
|
|||||||
self.awaiting_d = true;
|
self.awaiting_d = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'h' => self.on_right(),
|
|
||||||
'j' => self.on_down(),
|
|
||||||
'k' => self.on_up(),
|
|
||||||
'l' => self.on_left(),
|
|
||||||
'c' => {
|
'c' => {
|
||||||
// TODO: This should depend on what tile you're on!
|
// TODO: This should depend on what tile you're on!
|
||||||
match self.process_sorting_type {
|
match self.process_sorting_type {
|
||||||
@ -137,16 +132,51 @@ impl App {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For now, these are hard coded --- in the future, they shouldn't be!
|
||||||
|
//
|
||||||
|
// General idea for now:
|
||||||
|
// CPU -(down)> MEM
|
||||||
|
// MEM -(down)> Network, -(right)> TEMP
|
||||||
|
// TEMP -(down)> Disk, -(left)> MEM, -(up)> CPU
|
||||||
|
// Disk -(down)> Processes, -(left)> MEM, -(up)> TEMP
|
||||||
|
// Network -(up)> MEM, -(right)> PROC
|
||||||
|
// PROC -(up)> Disk, -(left)> Network
|
||||||
pub fn on_left(&mut self) {
|
pub fn on_left(&mut self) {
|
||||||
|
self.current_application_position = match self.current_application_position {
|
||||||
|
ApplicationPosition::PROCESS => ApplicationPosition::NETWORK,
|
||||||
|
ApplicationPosition::DISK => ApplicationPosition::MEM,
|
||||||
|
ApplicationPosition::TEMP => ApplicationPosition::MEM,
|
||||||
|
_ => self.current_application_position,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_right(&mut self) {
|
pub fn on_right(&mut self) {
|
||||||
|
self.current_application_position = match self.current_application_position {
|
||||||
|
ApplicationPosition::MEM => ApplicationPosition::TEMP,
|
||||||
|
ApplicationPosition::NETWORK => ApplicationPosition::PROCESS,
|
||||||
|
_ => self.current_application_position,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_up(&mut self) {
|
pub fn on_up(&mut self) {
|
||||||
|
self.current_application_position = match self.current_application_position {
|
||||||
|
ApplicationPosition::MEM => ApplicationPosition::CPU,
|
||||||
|
ApplicationPosition::NETWORK => ApplicationPosition::MEM,
|
||||||
|
ApplicationPosition::PROCESS => ApplicationPosition::DISK,
|
||||||
|
ApplicationPosition::TEMP => ApplicationPosition::CPU,
|
||||||
|
ApplicationPosition::DISK => ApplicationPosition::TEMP,
|
||||||
|
_ => self.current_application_position,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_down(&mut self) {
|
pub fn on_down(&mut self) {
|
||||||
|
self.current_application_position = match self.current_application_position {
|
||||||
|
ApplicationPosition::CPU => ApplicationPosition::MEM,
|
||||||
|
ApplicationPosition::MEM => ApplicationPosition::NETWORK,
|
||||||
|
ApplicationPosition::TEMP => ApplicationPosition::DISK,
|
||||||
|
ApplicationPosition::DISK => ApplicationPosition::PROCESS,
|
||||||
|
_ => self.current_application_position,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrement_position_count(&mut self) {
|
pub fn decrement_position_count(&mut self) {
|
||||||
|
@ -11,6 +11,7 @@ const COLOUR_LIST : [Color; 6] = [Color::Red, Color::Green, Color::LightYellow,
|
|||||||
const TEXT_COLOUR : Color = Color::Gray;
|
const TEXT_COLOUR : Color = Color::Gray;
|
||||||
const GRAPH_COLOUR : Color = Color::Gray;
|
const GRAPH_COLOUR : Color = Color::Gray;
|
||||||
const BORDER_STYLE_COLOUR : Color = Color::Gray;
|
const BORDER_STYLE_COLOUR : Color = Color::Gray;
|
||||||
|
const HIGHLIGHTED_BORDER_STYLE_COLOUR : Color = Color::LightBlue;
|
||||||
const GRAPH_MARKER : Marker = Marker::Braille;
|
const GRAPH_MARKER : Marker = Marker::Braille;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -29,6 +30,7 @@ pub struct CanvasData {
|
|||||||
|
|
||||||
pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_state : &mut app::App, canvas_data : &CanvasData) -> error::Result<()> {
|
pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_state : &mut app::App, canvas_data : &CanvasData) -> error::Result<()> {
|
||||||
let border_style : Style = Style::default().fg(BORDER_STYLE_COLOUR);
|
let border_style : Style = Style::default().fg(BORDER_STYLE_COLOUR);
|
||||||
|
let highlighted_border_style : Style = Style::default().fg(HIGHLIGHTED_BORDER_STYLE_COLOUR);
|
||||||
|
|
||||||
let temperature_rows = canvas_data
|
let temperature_rows = canvas_data
|
||||||
.temp_sensor_data
|
.temp_sensor_data
|
||||||
@ -102,7 +104,15 @@ pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
Chart::default()
|
Chart::default()
|
||||||
.block(Block::default().title("CPU Usage").borders(Borders::ALL).border_style(border_style))
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title("CPU Usage")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(match app_state.current_application_position {
|
||||||
|
app::ApplicationPosition::CPU => highlighted_border_style,
|
||||||
|
_ => border_style,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.x_axis(x_axis)
|
.x_axis(x_axis)
|
||||||
.y_axis(y_axis)
|
.y_axis(y_axis)
|
||||||
.datasets(&dataset_vector)
|
.datasets(&dataset_vector)
|
||||||
@ -114,7 +124,15 @@ pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_sta
|
|||||||
let x_axis : Axis<String> = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([0.0, 600_000.0]);
|
let x_axis : Axis<String> = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([0.0, 600_000.0]);
|
||||||
let y_axis = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([-0.5, 100.5]).labels(&["0%", "100%"]); // Offset as the zero value isn't drawn otherwise...
|
let y_axis = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([-0.5, 100.5]).labels(&["0%", "100%"]); // Offset as the zero value isn't drawn otherwise...
|
||||||
Chart::default()
|
Chart::default()
|
||||||
.block(Block::default().title("Memory Usage").borders(Borders::ALL).border_style(border_style))
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title("Memory Usage")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(match app_state.current_application_position {
|
||||||
|
app::ApplicationPosition::MEM => highlighted_border_style,
|
||||||
|
_ => border_style,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.x_axis(x_axis)
|
.x_axis(x_axis)
|
||||||
.y_axis(y_axis)
|
.y_axis(y_axis)
|
||||||
.datasets(&[
|
.datasets(&[
|
||||||
@ -136,7 +154,15 @@ pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_sta
|
|||||||
{
|
{
|
||||||
let width = f64::from(middle_divided_chunk_2[0].width);
|
let width = f64::from(middle_divided_chunk_2[0].width);
|
||||||
Table::new(["Sensor", "Temp"].iter(), temperature_rows)
|
Table::new(["Sensor", "Temp"].iter(), temperature_rows)
|
||||||
.block(Block::default().title("Temperatures").borders(Borders::ALL).border_style(border_style))
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title("Temperatures")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(match app_state.current_application_position {
|
||||||
|
app::ApplicationPosition::TEMP => highlighted_border_style,
|
||||||
|
_ => border_style,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.header_style(Style::default().fg(Color::LightBlue))
|
.header_style(Style::default().fg(Color::LightBlue))
|
||||||
.widths(&[(width * 0.45) as u16, (width * 0.4) as u16])
|
.widths(&[(width * 0.45) as u16, (width * 0.4) as u16])
|
||||||
.render(&mut f, middle_divided_chunk_2[0]);
|
.render(&mut f, middle_divided_chunk_2[0]);
|
||||||
@ -144,10 +170,18 @@ pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_sta
|
|||||||
|
|
||||||
// Disk usage table
|
// Disk usage table
|
||||||
{
|
{
|
||||||
// TODO: We have to dynamically remove some of these table elements based on size...
|
// TODO: We may have to dynamically remove some of these table elements based on size...
|
||||||
let width = f64::from(middle_divided_chunk_2[1].width);
|
let width = f64::from(middle_divided_chunk_2[1].width);
|
||||||
Table::new(["Disk", "Mount", "Used", "Total", "Free", "R/s", "W/s"].iter(), disk_rows)
|
Table::new(["Disk", "Mount", "Used", "Total", "Free", "R/s", "W/s"].iter(), disk_rows)
|
||||||
.block(Block::default().title("Disk Usage").borders(Borders::ALL).border_style(border_style))
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title("Disk Usage")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(match app_state.current_application_position {
|
||||||
|
app::ApplicationPosition::DISK => highlighted_border_style,
|
||||||
|
_ => border_style,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.header_style(Style::default().fg(Color::LightBlue).modifier(Modifier::BOLD))
|
.header_style(Style::default().fg(Color::LightBlue).modifier(Modifier::BOLD))
|
||||||
.widths(&[
|
.widths(&[
|
||||||
(width * 0.18).floor() as u16,
|
(width * 0.18).floor() as u16,
|
||||||
@ -166,7 +200,15 @@ pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_sta
|
|||||||
let x_axis : Axis<String> = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([0.0, 600_000.0]);
|
let x_axis : Axis<String> = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([0.0, 600_000.0]);
|
||||||
let y_axis = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([-0.5, 1_000_000.5]).labels(&["0GB", "1GB"]);
|
let y_axis = Axis::default().style(Style::default().fg(GRAPH_COLOUR)).bounds([-0.5, 1_000_000.5]).labels(&["0GB", "1GB"]);
|
||||||
Chart::default()
|
Chart::default()
|
||||||
.block(Block::default().title("Network").borders(Borders::ALL).border_style(border_style))
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title("Network")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(match app_state.current_application_position {
|
||||||
|
app::ApplicationPosition::NETWORK => highlighted_border_style,
|
||||||
|
_ => border_style,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.x_axis(x_axis)
|
.x_axis(x_axis)
|
||||||
.y_axis(y_axis)
|
.y_axis(y_axis)
|
||||||
.datasets(&[
|
.datasets(&[
|
||||||
@ -196,7 +238,6 @@ pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_sta
|
|||||||
let num_rows = i64::from(bottom_chunks[1].height) - 3;
|
let num_rows = i64::from(bottom_chunks[1].height) - 3;
|
||||||
let mut process_counter = 0;
|
let mut process_counter = 0;
|
||||||
|
|
||||||
//TODO: Fix this!
|
|
||||||
let start_position = match app_state.scroll_direction {
|
let start_position = match app_state.scroll_direction {
|
||||||
app::ScrollDirection::DOWN => {
|
app::ScrollDirection::DOWN => {
|
||||||
if app_state.currently_selected_process_position < num_rows {
|
if app_state.currently_selected_process_position < num_rows {
|
||||||
@ -251,7 +292,15 @@ pub fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_sta
|
|||||||
});
|
});
|
||||||
|
|
||||||
Table::new(["PID", "Name", "CPU%", "Mem%"].iter(), process_rows)
|
Table::new(["PID", "Name", "CPU%", "Mem%"].iter(), process_rows)
|
||||||
.block(Block::default().title("Processes").borders(Borders::ALL).border_style(border_style))
|
.block(
|
||||||
|
Block::default()
|
||||||
|
.title("Processes")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(match app_state.current_application_position {
|
||||||
|
app::ApplicationPosition::PROCESS => highlighted_border_style,
|
||||||
|
_ => border_style,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.header_style(Style::default().fg(Color::LightBlue))
|
.header_style(Style::default().fg(Color::LightBlue))
|
||||||
.widths(&[(width * 0.2) as u16, (width * 0.35) as u16, (width * 0.2) as u16, (width * 0.2) as u16])
|
.widths(&[(width * 0.2) as u16, (width * 0.35) as u16, (width * 0.2) as u16, (width * 0.2) as u16])
|
||||||
.render(&mut f, bottom_chunks[1]);
|
.render(&mut f, bottom_chunks[1]);
|
||||||
|
16
src/main.rs
16
src/main.rs
@ -34,7 +34,7 @@ enum Event<I, J> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> error::Result<()> {
|
fn main() -> error::Result<()> {
|
||||||
let _log = utils::logging::init_logger(); // TODO: Error handling
|
let _log = utils::logging::init_logger(); // TODO: Note this could fail and we wouldn't know... consider whether it is worth dealing with
|
||||||
|
|
||||||
// Parse command line options
|
// Parse command line options
|
||||||
let matches = clap_app!(app =>
|
let matches = clap_app!(app =>
|
||||||
@ -42,9 +42,9 @@ fn main() -> error::Result<()> {
|
|||||||
(version: crate_version!())
|
(version: crate_version!())
|
||||||
(author: "Clement Tsang <clementjhtsang@gmail.com>")
|
(author: "Clement Tsang <clementjhtsang@gmail.com>")
|
||||||
(about: "A graphical top clone.")
|
(about: "A graphical top clone.")
|
||||||
(@arg THEME: -t --theme +takes_value "Sets a colour theme.")
|
//(@arg THEME: -t --theme +takes_value "Sets a colour theme.")
|
||||||
(@arg AVG_CPU: -a --avgcpu "Enables showing the average CPU usage.")
|
(@arg AVG_CPU: -a --avgcpu "Enables showing the average CPU usage.")
|
||||||
(@arg DEBUG: -d --debug "Enables debug mode.") // TODO: This isn't done yet!
|
//(@arg DEBUG: -d --debug "Enables debug mode.") // TODO: This isn't done yet!
|
||||||
(@group TEMPERATURE_TYPE =>
|
(@group TEMPERATURE_TYPE =>
|
||||||
(@arg CELSIUS : -c --celsius "Sets the temperature type to Celsius. This is the default option.")
|
(@arg CELSIUS : -c --celsius "Sets the temperature type to Celsius. This is the default option.")
|
||||||
(@arg FAHRENHEIT : -f --fahrenheit "Sets the temperature type to Fahrenheit.")
|
(@arg FAHRENHEIT : -f --fahrenheit "Sets the temperature type to Fahrenheit.")
|
||||||
@ -52,7 +52,7 @@ fn main() -> error::Result<()> {
|
|||||||
)
|
)
|
||||||
(@arg RATE: -r --rate +takes_value "Sets a refresh rate in milliseconds, min is 250ms, defaults to 1000ms. Higher values may take more resources.")
|
(@arg RATE: -r --rate +takes_value "Sets a refresh rate in milliseconds, min is 250ms, defaults to 1000ms. Higher values may take more resources.")
|
||||||
)
|
)
|
||||||
.after_help("Themes:")
|
//.after_help("Themes:") // TODO: This and others disabled for now
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let update_rate_in_milliseconds : u128 = matches.value_of("RATE").unwrap_or("1000").parse::<u128>()?;
|
let update_rate_in_milliseconds : u128 = matches.value_of("RATE").unwrap_or("1000").parse::<u128>()?;
|
||||||
@ -149,11 +149,11 @@ fn main() -> error::Result<()> {
|
|||||||
// debug!("Keyboard event fired!");
|
// debug!("Keyboard event fired!");
|
||||||
match event {
|
match event {
|
||||||
KeyEvent::Ctrl('c') | KeyEvent::Esc => break,
|
KeyEvent::Ctrl('c') | KeyEvent::Esc => break,
|
||||||
|
KeyEvent::Char('h') | KeyEvent::Left => app.on_left(),
|
||||||
|
KeyEvent::Char('l') | KeyEvent::Right => app.on_right(),
|
||||||
|
KeyEvent::Char('k') | KeyEvent::Up => app.on_up(),
|
||||||
|
KeyEvent::Char('j') | KeyEvent::Down => app.on_down(),
|
||||||
KeyEvent::Char(c) => app.on_key(c), // TODO: We can remove the 'q' event and just move it to the quit?
|
KeyEvent::Char(c) => app.on_key(c), // TODO: We can remove the 'q' event and just move it to the quit?
|
||||||
KeyEvent::Left => app.on_left(),
|
|
||||||
KeyEvent::Right => app.on_right(),
|
|
||||||
KeyEvent::Up => app.on_up(),
|
|
||||||
KeyEvent::Down => app.on_down(),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
use assert_cmd::prelude::*; // Add methods on commands
|
use assert_cmd::prelude::*;
|
||||||
use predicates::prelude::*;
|
use predicates::prelude::*;
|
||||||
use std::process::Command; // Run programs // Used for writing assertions
|
use std::process::Command;
|
||||||
|
|
||||||
//======================RATES======================//
|
//======================RATES======================//
|
||||||
#[test]
|
|
||||||
fn valid_rate_argument() {
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_small_rate() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_small_rate() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user