diff --git a/README.md b/README.md index ad25e19..bf41b60 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Process Interactive Kill is a command line tool that helps to find and kill process. It works like pkill command but search is interactive. +![Example pik](docs/pik.png) This tool is still under development @@ -70,6 +71,7 @@ sudo zypper install pik On **Gentoo** It is available via `lamdness` overlay + ```sh sudo eselect repository enable lamdness sudo emaint -r lamdness sync @@ -99,9 +101,19 @@ cargo binstall pik ### Application configuration -You may set your preferences in `pik.toml` file located in `~/.config/pik` directory. +You may set your preferences in `config.toml` file located in `~/.config/pik` directory. All options are optional, if skipped default values will be used. -Example configuration with default settings can be found at [example config](example_config.toml) + +You can find default values below + +``` toml +# Size of the viewport +screen_size = { height = 20 } # run pik in 20 lines of the terminal +# screen_size = "fullscreen" # run pik in fullscreen + +# Icons require nerd fonts v3 +use_icons = false +``` ### Key maps diff --git a/docs/pik.png b/docs/pik.png new file mode 100644 index 0000000..df64b03 Binary files /dev/null and b/docs/pik.png differ diff --git a/example_config.toml b/example_config.toml deleted file mode 100644 index 8245cdb..0000000 --- a/example_config.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Size of the viewport -screen_size = { height = 20 } # run pik in 20 lines of the terminal -# screen_size = "fullscreen" # run pik in fullscreen diff --git a/src/config.rs b/src/config.rs index 15dfa56..b4fa59d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -24,6 +24,8 @@ use serde::Deserialize; pub struct AppConfig { #[serde(default)] pub screen_size: ScreenSize, + #[serde(default)] + pub use_icons: bool, } #[derive(Debug, Eq, PartialEq, Deserialize, Clone, Copy)] @@ -50,6 +52,14 @@ mod tests { fn should_deserialize_empty_configuration() { let default_settings = toml::from_str(""); assert_eq!(default_settings, Ok(AppConfig::default())); + // ensure what actual defaults are + assert_eq!( + default_settings, + Ok(AppConfig { + screen_size: ScreenSize::Height(DEFAULT_SCREEN_SIZE), + use_icons: false + }) + ); } #[test] @@ -57,13 +67,15 @@ mod tests { let default_settings: AppConfig = toml::from_str( r#" screen_size = "fullscreen" + use_icons = true "#, ) .unwrap(); assert_eq!( default_settings, AppConfig { - screen_size: ScreenSize::Fullscreen + screen_size: ScreenSize::Fullscreen, + use_icons: true } ); } diff --git a/src/settings.rs b/src/settings.rs index cc2fe09..39ba35e 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -10,6 +10,7 @@ use crate::{ pub struct AppSettings { pub viewport: Viewport, pub filter_opions: FilterOptions, + pub use_icons: bool, } impl AppSettings { @@ -20,6 +21,7 @@ impl AppSettings { ignore_threads: !cli_args.include_threads_processes, include_all_processes: cli_args.include_other_users_processes, }, + use_icons: config.use_icons, } } } @@ -96,6 +98,7 @@ mod tests { settings, AppSettings { viewport: Viewport::Inline(25), + use_icons: false, filter_opions: FilterOptions { ignore_threads: false, include_all_processes: true @@ -108,6 +111,7 @@ mod tests { fn should_prefer_cli_args_screen_size() { let config = AppConfig { screen_size: ScreenSize::Height(40), + ..Default::default() }; let cli_args = CliArgs { screen_size: Some(ScreenSizeOptions { diff --git a/src/tui.rs b/src/tui.rs index 30657d9..8470dd5 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -30,7 +30,7 @@ impl App { process_manager: ProcessManager::new()?, search_results: ProcessSearchResults::empty(), filter_options: app_settings.filter_opions, - tui: Tui::new(search_criteria), + tui: Tui::new(search_criteria, app_settings.use_icons), }; app.search_for_processess(); Ok(app) diff --git a/src/tui/rendering.rs b/src/tui/rendering.rs index 7bf1fa1..a89d1c2 100644 --- a/src/tui/rendering.rs +++ b/src/tui/rendering.rs @@ -17,7 +17,7 @@ use crate::processes::{MatchedBy, Process, ProcessSearchResults, ResultItem}; use super::highlight::highlight_text; -pub struct Theme { +struct Theme { row_fg: Color, selected_style_fg: Color, normal_row_color: Color, @@ -28,7 +28,7 @@ pub struct Theme { } impl Theme { - pub fn new() -> Self { + fn new() -> Self { Self { row_fg: tailwind::SLATE.c200, selected_style_fg: tailwind::BLUE.c400, @@ -43,6 +43,7 @@ impl Theme { pub struct Tui { theme: Theme, + use_icons: bool, process_table: TableState, process_table_scroll_state: ScrollbarState, process_table_number_of_items: usize, @@ -58,7 +59,18 @@ const MAX_PATH_LEN: usize = 38; const MAX_ARGS_LEN: usize = 35; const MAX_PORTS_LEN: usize = 20; -const TABLE_HEADERS: [&str; 8] = [ +const TABLE_HEADERS_ICONS: [&str; 8] = [ + "USER 󰋦", + "PID ", + "PARENT 󱖁", + "TIME ", + "CMD 󱃸", + "PATH ", + "ARGS 󱃼", + "PORTS ", +]; + +const TABLE_HEADERS_PLAIN: [&str; 8] = [ "USER", "PID", "PARENT", "RUN TIME", "CMD", "PATH", "ARGS", "PORTS", ]; @@ -74,13 +86,14 @@ const TABLE_WIDTHS: [Constraint; 8] = [ ]; impl Tui { - pub fn new(search_text: String) -> Self { + pub fn new(search_text: String, use_icons: bool) -> Self { let mut search_area = TextArea::from(search_text.lines()); search_area.move_cursor(tui_textarea::CursorMove::End); Self { process_table: TableState::default(), process_table_scroll_state: ScrollbarState::new(0), theme: Theme::new(), + use_icons, process_table_number_of_items: 0, process_details_scroll_offset: 0, process_details_number_of_lines: 0, @@ -247,8 +260,13 @@ impl Tui { ]) .style(Style::new().fg(self.theme.row_fg).bg(color)) }); + let headers = if self.use_icons { + TABLE_HEADERS_ICONS + } else { + TABLE_HEADERS_PLAIN + }; let table = Table::new(rows, TABLE_WIDTHS) - .header(Row::new(TABLE_HEADERS)) + .header(Row::new(headers)) .block( Block::default() .title_top(