diff options
author | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2020-05-02 23:54:10 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-02 23:54:10 -0400 |
commit | 39d7450aad1f9554a04d69ae655507eef0f3cac1 (patch) | |
tree | 224a86904999fad1600020fb8a66c3a523dc1fb4 | |
parent | 2828449544b4ad5fbfdc6be21b85bd23b0a13e7c (diff) | |
parent | 5636f866567411e583118b63c29ec2659eae8da9 (diff) |
Merge pull request #139 from ClementTsang/improve_searching
Improve searching
-rw-r--r-- | CHANGELOG.md | 12 | ||||
-rw-r--r-- | CONTRIBUTING.md | 3 | ||||
-rw-r--r-- | Cargo.lock | 20 | ||||
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | README.md | 106 | ||||
-rw-r--r-- | assets/basic_mode.png | bin | 114620 -> 194990 bytes | |||
-rw-r--r-- | assets/or_search.png | bin | 0 -> 62099 bytes | |||
-rw-r--r-- | assets/search_cpu_filter.png | bin | 0 -> 34992 bytes | |||
-rw-r--r-- | assets/search_empty.png | bin | 0 -> 172847 bytes | |||
-rw-r--r-- | assets/simple_advanced_search.png | bin | 0 -> 51363 bytes | |||
-rw-r--r-- | assets/simple_search.png | bin | 0 -> 51685 bytes | |||
-rw-r--r-- | src/app.rs | 141 | ||||
-rw-r--r-- | src/app/query.rs | 615 | ||||
-rw-r--r-- | src/app/states.rs | 63 | ||||
-rw-r--r-- | src/canvas.rs | 14 | ||||
-rw-r--r-- | src/canvas/canvas_colours.rs | 2 | ||||
-rw-r--r-- | src/canvas/dialogs/filter_dialog.rs | 1 | ||||
-rw-r--r-- | src/canvas/widgets/basic_table_arrows.rs | 15 | ||||
-rw-r--r-- | src/canvas/widgets/cpu_graph.rs | 3 | ||||
-rw-r--r-- | src/canvas/widgets/process_table.rs | 158 | ||||
-rw-r--r-- | src/constants.rs | 63 | ||||
-rw-r--r-- | src/data_conversion.rs | 48 | ||||
-rw-r--r-- | src/main.rs | 94 | ||||
-rw-r--r-- | src/utils/error.rs | 11 | ||||
-rw-r--r-- | src/utils/logging.rs | 1 |
25 files changed, 1003 insertions, 374 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index fe400143..563b0efb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.5.0] - Unreleased + +### Features + +- [#114](https://github.com/ClementTsang/bottom/pull/114): Process state per process (originally in 0.4.0, moved to later). + ## [0.4.0] - Unreleased ### Features @@ -13,7 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#55](https://github.com/ClementTsang/bottom/issues/55): Battery monitoring widget. -- [#114](https://github.com/ClementTsang/bottom/pull/114): Process state per process. +- [#134](https://github.com/ClementTsang/bottom/pull/134): `hjkl` movement to delete dialog (credit to [andys8](https://github.com/andys8)). + +- [#59](https://github.com/ClementTsang/bottom/issues/59): `Alt-h` and `Alt-l` to move left/right in query (and rest of the app actually). ### Changes @@ -42,7 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#70](https://github.com/ClementTsang/bottom/issues/70): Redesigned help menu to allow for scrolling. -- [#134](https://github.com/ClementTsang/bottom/pull/134): Added `hjkl` movement to delete dialog. +- [#59](https://github.com/ClementTsang/bottom/issues/59): Moved maximization key to `e`, renamed feature to _expanding_ the widget. Done to allow for the `<Enter>` key to be used later for a more intuitive usage. - [#59](https://github.com/ClementTsang/bottom/issues/59): Redesigned search menu and query. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5ab00396..96250ae6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,6 +42,9 @@ If you want to help contribute by submitting a PR, by all means, I'm open! In re - You can check clippy using `cargo +nightly clippy`. +- You may notice that I have fern and log as dependencies; this is mostly for easy debugging via the `debug!()` macro. It writes to the + `debug.log` file that will automatically be created if you run in debug mode (so `cargo run`). + And in regards to the pull request process: - Create a personal fork of the process and PR that, as per the [fork and pull method](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-collaborative-development-models). @@ -63,7 +63,7 @@ name = "backtrace" version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -71,7 +71,7 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)", @@ -116,7 +116,7 @@ dependencies = [ [[package]] name = "bottom" -version = "0.3.0" +version = "0.4.0" dependencies = [ "assert_cmd 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)", @@ -422,7 +422,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1063,7 +1063,7 @@ version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1107,7 +1107,7 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1191,7 +1191,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1310,7 +1310,7 @@ dependencies = [ "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum backtrace 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" -"checksum backtrace-sys 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "78848718ee1255a2485d1309ad9cdecfc2e7d0362dd11c6829364c6b35ae1bc7" +"checksum backtrace-sys 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "18fbebbe1c9d1f383a9cc7e8ccdb471b91c8d024ee9c2ca5b5346121fe8b4399" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum battery 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "36a698e449024a5d18994a815998bf5e2e4bc1883e35a7d7ba95b6b69ee45907" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" @@ -1403,7 +1403,7 @@ dependencies = [ "checksum proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" "checksum proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" "checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" -"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +"checksum quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" "checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" "checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" "checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" @@ -27,11 +27,9 @@ crossterm = "0.17" chrono = "0.4.11" clap = "2.33.0" dirs = "2.0.2" -fern = "0.6.0" futures = "0.3.4" heim = "0.0.10" itertools = "0.9.0" -log = "0.4.8" regex = "1.3" sysinfo = "0.14" toml = "0.5.6" @@ -42,9 +40,14 @@ serde = {version = "1.0", features = ["derive"] } unicode-segmentation = "1.6.0" unicode-width = "0.1.7" +# For debugging only... +fern = "0.6.0" +log = "0.4.8" + tui = {version = "0.9", features = ["crossterm"], default-features = false } # tui = {git = "https://github.com/ClementTsang/tui-rs", features = ["crossterm"], default-features = false } + [target.'cfg(windows)'.dependencies] winapi = "0.3.8" @@ -3,13 +3,13 @@ [![Build Status](https://travis-ci.com/ClementTsang/bottom.svg?token=1wvzVgp94E1TZyPNs8JF&branch=master)](https://travis-ci.com/ClementTsang/bottom) [![crates.io link](https://img.shields.io/crates/v/bottom.svg)](https://crates.io/crates/bottom) [![tokei](https://tokei.rs/b1/github/ClementTsang/bottom?category=code)](https://github.com/ClementTsang/bottom) -[![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-) A cross-platform graphical process/system monitor with a customizable interface and a multitude of features. Supports Linux, macOS, and Windows. Inspired by both [gtop](https://github.com/aksakalli/gtop) and [gotop](https://github.com/cjbassi/gotop). <!--TODO: Update recording for 0.4--> -![Quick demo recording showing off searching, maximizing, and process killing.](assets/summary_and_search.gif) _Theme based on [gruvbox](https://github.com/morhetz/gruvbox) (see [sample config](./sample_configs/demo_config.toml))._ Recorded on version 0.2.0. +![Quick demo recording showing off searching, expanding, and process killing.](assets/summary_and_search.gif) _Theme based on [gruvbox](https://github.com/morhetz/gruvbox) (see [sample config](./sample_configs/demo_config.toml))._ Recorded on version 0.2.0. **Note**: This documentation is relevant to version 0.4.0 and may refer to in-development or unreleased features, especially if you are reading this on the master branch. Please refer to [release branch](https://github.com/ClementTsang/bottom/tree/release/README.md) or [crates.io](https://crates.io/crates/bottom) for the most up-to-date _release_ documentation. @@ -32,10 +32,15 @@ A cross-platform graphical process/system monitor with a customizable interface - [Process bindings](#process-bindings) - [Process search bindings](#process-search-bindings) - [Battery bindings](#battery-bindings) + - [Process searching keywords](#process-searching-keywords) + - [Supported keywords](#supported-keywords) + - [Supported comparison operators](#supported-comparison-operators) + - [Supported logical operators](#supported-logical-operators) + - [Supported units](#supported-units) - [Features](#features) - - [Process filtering](#process-filtering) + - [Process searching](#process-searching) - [Zoom](#zoom) - - [Maximizing](#maximizing) + - [Expanding](#expanding) - [Basic mode](#basic-mode) - [Config files](#config-files) - [Config flags](#config-flags) @@ -44,6 +49,7 @@ A cross-platform graphical process/system monitor with a customizable interface - [Battery](#battery) - [Compatibility](#compatibility) - [Contribution](#contribution) + - [Contributors](#contributors) - [Thanks](#thanks) ## Installation @@ -169,7 +175,7 @@ Run using `btm`. | | | | -------------------------------------------------- | ---------------------------------------------------------------------------- | | `q`, `Ctrl-c` | Quit | -| `Esc` | Close dialog windows, search, widgets, or exit maximized mode | +| `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`-arrow key<br>`Shift`-arrow key<br>`H/J/K/L` | Move to a different widget (on macOS some keybindings may conflict) | @@ -180,7 +186,7 @@ Run using `btm`. | `?` | Open help menu | | `gg`, `Home` | Jump to the first entry | | `Shift-g`, `End` | Jump to the last entry | -| `Enter` | Maximize the currently selected widget | +| `e` | Expand the currently selected widget | | `+` | Zoom in on chart (decrease time range) | | `-` | Zoom out on chart (increase time range) | | `=` | Reset zoom | @@ -225,10 +231,57 @@ Run using `btm`. #### Battery bindings -| | | -| ------- | -------------------------- | -| `Left` | Go to the next battery | -| `Right` | Go to the previous battery | +| | | +| -------------- | -------------------------- | +| `Left, Alt-h` | Go to the next battery | +| `Right, Alt-l` | Go to the previous battery | + +### Process searching keywords + +Note none of the keywords are case sensitive. Furthermore, if you want to search a reserved keyword, surround the text in quotes - for example, `"And" or "Or"` would be a valid search. + +#### Supported keywords + +| | | | +| -------- | --------------- | ------------------------------------------------------------------------------- | +| `pid` | `pid: 1044` | Matches by PID; supports regex and requiring matching the entire PID | +| `cpu` | `cpu > 0.5` | Matches the condition for the CPU column; supports comparison operators | +| `mem` | `mem < 0.5` | Matches the condition for the memory column; supports comparison operators | +| `read` | `read = 1` | Matches the condition for the read/s column; supports comparison operators | +| `write` | `write >= 1` | Matches the condition for the write/s column; supports comparison operators | +| `tread` | `tread <= 1024` | Matches the condition for the total read column; supports comparison operators | +| `twrite` | `twrite > 1024` | Matches the condition for the total write column; supports comparison operators | + +#### Supported comparison operators + +| | | +| ---- | -------------------------------------------------------------- | +| `=` | Checks if the values are equal | +| `>` | Checks if the left value is strictly greater than the right | +| `<` | Checks if the left value is strictly less than the right | +| `>=` | Checks if the left value is greater than or equal to the right | +| `<=` | Checks if the left value is less than or equal to the right | + +#### Supported logical operators + +| | | | +| ------------------ | -------------------------------------------- | ----------------------------------------------------| +| `and, &&, <Space>` | `<CONDITION 1> and/&&/<Space> <CONDITION 2>` | Requires both conditions to be true to match | +| `or, \|\|` | `<CONDITION 1> or/\|\| <CONDITION 2>` | Requires at least one condition to be true to match | + +#### Supported units + +| | | +| ----- | --------- | +| `B` | Bytes | +| `KB` | Kilobytes | +| `MB` | Megabytes | +| `GB` | Gigabytes | +| `TB` | Terabytes | +| `KiB` | Kibibytes | +| `MiB` | Mebibytes | +| `GiB` | Gibibytes | +| `TiB` | Tebibytes | ## Features @@ -252,12 +305,29 @@ It also aims to be: In addition, bottom also currently has the following features: -### Process filtering +### Process searching -On any process widget, hit `/` to bring up a search bar. If the layout has -multiple process widgets, note this search is independent of other widgets. Searching -supports regex, matching case, and matching entire words. Use `Tab` to toggle between -searching by PID and by process name. +On any process widget, hit `/` to bring up a search bar. If the layout has multiple process widgets, note this search is independent of other widgets. + +![search bar image](assets/search_empty.png) + +By default, just typing in something will search by process name: + +![a simple search](assets/simple_search.png) + +This simple search can be refined by matching by case, matching the entire word, or by using regex: + +![a slightly better search](assets/simple_advanced_search.png) + +Now let's say you want to search for two things: luckily, we have the `AND` and `OR` logical operators: + +![logical operator demo](assets/or_search.png) + +Furthermore, one is able to refine their searches by CPU usage, memory usage, PID, and more. For example: + +![using cpu filter](assets/search_cpu_filter.png) + +One can see all available keywords and query options [here](#process-searching-keywords). ### Zoom @@ -265,9 +335,9 @@ Using the `+`/`-` keys or the scroll wheel will move the current time intervals Widgets can hold different time intervals independently. These time intervals can be adjusted using the `-t`/`--default_time_value` and `-d`/`--time_delta` options, or their corresponding config options. -### Maximizing +### Expand -Only care about one specific widget? You can go to that widget and hit `Enter` to make that widget take +Only care about one specific widget? You can go to that widget and hit `e` to make that widget expand and take up the entire drawing area. ### Basic mode @@ -464,6 +534,8 @@ The current compatibility of widgets with operating systems from personal testin Contribution is always welcome - please take a look at [CONTRIBUTING.md](./CONTRIBUTING.md) for details on how to help. +### Contributors + Thanks to all contributors ([emoji key](https://allcontributors.org/docs/en/emoji-key)): <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> diff --git a/assets/basic_mode.png b/assets/basic_mode.png Binary files differindex a11b1798..21a2fcd3 100644 --- a/assets/basic_mode.png +++ b/assets/basic_mode.png diff --git a/assets/or_search.png b/assets/or_search.png Binary files differnew file mode 100644 index 00000000..2ca4fa90 --- /dev/null +++ b/assets/or_search.png diff --git a/assets/search_cpu_filter.png b/assets/search_cpu_filter.png Binary files differnew file mode 100644 index 00000000..931fa92f --- /dev/null +++ b/assets/search_cpu_filter.png diff --git a/assets/search_empty.png b/assets/search_empty.png Binary files differnew file mode 100644 index 00000000..38c63687 --- /dev/null +++ b/assets/search_empty.png diff --git a/assets/simple_advanced_search.png b/assets/simple_advanced_search.png Binary files differnew file mode 100644 index 00000000..94f94319 --- /dev/null +++ b/assets/simple_advanced_search.png diff --git a/assets/simple_search.png b/assets/simple_search.png Binary files differnew file mode 100644 index 00000000..b2c73888 --- /dev/null +++ b/assets/simple_search.png @@ -19,6 +19,7 @@ pub mod data_farmer; pub mod data_harvester; pub mod layout_manager; mod process_killer; +pub mod query; pub mod states; const MAX_SEARCH_LENGTH: usize = 200; @@ -307,19 +308,6 @@ impl App { let is_in_search_widget = self.is_in_search_widget(); if !self.is_in_dialog() { if is_in_search_widget { - if let Some(proc_widget_state) = self - .proc_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) - { - if !proc_widget_state.is_grouped { - if proc_widget_state.process_search_state.is_searching_with_pid { - self.search_with_name(); - } else { - self.search_with_pid(); - } - } - } } else if let Some(proc_widget_state) = self .proc_state .widget_states @@ -327,11 +315,7 @@ impl App { { // Toggles process widget grouping state proc_widget_state.is_grouped = !(proc_widget_state.is_grouped); - if proc_widget_state.is_grouped { - self.search_with_name(); - } else { - self.proc_state.force_update = Some(self.current_widget.widget_id); - } + self.proc_state.force_update = Some(self.current_widget.widget_id); } } } @@ -387,9 +371,6 @@ impl App { .process_search_state .search_state .is_enabled = true; - if proc_widget_state.is_grouped { - self.search_with_name(); - } self.move_widget_selection_down(); } } @@ -426,44 +407,6 @@ impl App { } } - pub fn search_with_pid(&mut self) { - if !self.is_in_dialog() { - if let Some(proc_widget_state) = self - .proc_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) - { - if proc_widget_state - .process_search_state - .search_state - .is_enabled - { - proc_widget_state.process_search_state.is_searching_with_pid = true; - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); - } - } - } - } - - pub fn search_with_name(&mut self) { - if !self.is_in_dialog() { - if let Some(proc_widget_state) = self - .proc_state - .widget_states - .get_mut(&(self.current_widget.widget_id - 1)) - { - if proc_widget_state - .process_search_state - .search_state - .is_enabled - { - proc_widget_state.process_search_state.is_searching_with_pid = false; - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); - } - } - } - } - pub fn toggle_ignore_case(&mut self) { let is_in_search_widget = self.is_in_search_widget(); if let Some(proc_widget_state) = self @@ -475,7 +418,7 @@ impl App { proc_widget_state .process_search_state .search_toggle_ignore_case(); - proc_widget_state.update_regex(); + proc_widget_state.update_query(); self.proc_state.force_update = Some(self.current_widget.widget_id - 1); } } @@ -492,7 +435,7 @@ impl App { proc_widget_state .process_search_state .search_toggle_whole_word(); - proc_widget_state.update_regex(); + proc_widget_state.update_query(); self.proc_state.force_update = Some(self.current_widget.widget_id - 1); } } @@ -507,7 +450,7 @@ impl App { { if is_in_search_widget && proc_widget_state.is_search_enabled() { proc_widget_state.process_search_state.search_toggle_regex(); - proc_widget_state.update_regex(); + proc_widget_state.update_query(); self.proc_state.force_update = Some(self.current_widget.widget_id - 1); } } @@ -533,16 +476,6 @@ impl App { } else { self.delete_dialog_state.is_showing_dd = false; } - } else if !self.is_in_dialog() && !self.app_config_fields.use_basic_mode { - // Pop-out mode. We ignore if in process search. - - match self.current_widget.widget_type { - BottomWidgetType::ProcSearch => {} - _ => { - self.is_expanded = true; - self.is_force_redraw = true; - } - } } } @@ -585,7 +518,7 @@ impl App { true, ); - proc_widget_state.update_regex(); + proc_widget_state.update_query(); self.proc_state.force_update = Some(self.current_widget.widget_id - 1); } } else { @@ -640,24 +573,18 @@ impl App { .search_state .cursor_direction = CursorDirection::LEFT; - proc_widget_state.update_regex(); + proc_widget_state.update_query(); self.proc_state.force_update = Some(self.current_widget.widget_id - 1); } } } } - pub fn get_current_regex_matcher( - &self, widget_id: u64, - ) -> &Option<std::result::Result<regex::Regex, regex::Error>> { - match self.proc_state.widget_states.get(&widget_id) { - Some(proc_widget_state) => { - &proc_widget_state - .process_search_state - .search_state - .current_regex - } - None => &None, + pub fn get_process_filter(&self, widget_id: u64) -> &Option<query::Query> { + if let Some(process_widget_state) = self.proc_state.widget_states.get(&widget_id) { + &process_widget_state.process_search_state.search_state.query + } else { + &None } } @@ -882,6 +809,8 @@ impl App { } pub fn start_dd(&mut self) { + self.reset_multi_tap_keys(); + if let Some(proc_widget_state) = self .proc_state .widget_states @@ -895,32 +824,25 @@ impl App { if proc_widget_state.scroll_state.current_scroll_position < corresponding_filtered_process_list.len() as u64 { - let current_process = if self.is_grouped(self.current_widget.widget_id) { - let group_pids = &corresponding_filtered_process_list - [proc_widget_state.scroll_state.current_scroll_position as usize] - .group_pids; - - let mut ret = ("".to_string(), group_pids.clone()); - - for pid in group_pids { - if let Some(process) = self.canvas_data.process_data.get(&pid) { - ret.0 = process.name.clone(); - break; - } + let current_process: (String, Vec<u32>); + if self.is_grouped(self.current_widget.widget_id) { + if let Some(process) = &corresponding_filtered_process_list + .get(proc_widget_state.scroll_state.current_scroll_position as usize) + { + current_process = (process.name.to_string(), process.group_pids.clone()) + } else { + return; } - ret } else { let process = corresponding_filtered_process_list [proc_widget_state.scroll_state.current_scroll_position as usize] .clone(); - (process.name.clone(), vec![process.pid]) + current_process = (process.name.clone(), vec![process.pid]) }; self.to_delete_process_list = Some(current_process); self.delete_dialog_state.is_showing_dd = true; } - - self.reset_multi_tap_keys(); } } } @@ -987,7 +909,7 @@ impl App { .char_cursor_position += UnicodeWidthChar::width(caught_char).unwrap_or(0); - proc_widget_state.update_regex(); + proc_widget_state.update_query(); self.proc_state.force_update = Some(self.current_widget.widget_id - 1); proc_widget_state .process_search_state @@ -1178,6 +1100,7 @@ impl App { '+' => self.zoom_in(), '-' => self.zoom_out(), '=' => self.reset_zoom(), + 'e' => self.expand_widget(), _ => {} } @@ -1209,6 +1132,20 @@ impl App { self.to_delete_process_list.clone() } + fn expand_widget(&mut self) { + if !self.is_in_dialog() && !self.app_config_fields.use_basic_mode { + // Pop-out mode. We ignore if in process search. + + match self.current_widget.widget_type { + BottomWidgetType::ProcSearch => {} + _ => { + self.is_expanded = true; + self.is_force_redraw = true; + } + } + } + } + pub fn move_widget_selection_left(&mut self) { if !self.is_in_dialog() && !self.is_expanded { if let Some(current_widget) = self.widget_map.get(&self.current_widget.widget_id) { diff --git a/src/app/query.rs b/src/app/query.rs new file mode 100644 index 00000000..73bea66b --- /dev/null +++ b/src/app/query.rs @@ -0,0 +1,615 @@ +use super::ProcWidgetState; +use crate::{ + data_conversion::ConvertedProcessData, + utils::error::{ + BottomError::{self, QueryError}, + Result, + }, +}; +use std::collections::VecDeque; + +const DELIMITER_LIST: [char; 5] = ['=', '>', '<', '(', ')']; +const AND_LIST: [&str; 2] = ["and", "&&"]; +const OR_LIST: [&str; 2] = ["or", "||"]; + +/// I only separated this as otherwise, the states.rs file gets huge... and this should +/// belong in another file anyways, IMO. +pub trait ProcessQuery { + /// In charge of parsing the given query. + /// We are defining the following language for a query (case-insensitive prefixes): + /// + /// - Process names: No prefix required, can use regex, match word, or case. + /// Enclosing anything, including prefixes, in quotes, means we treat it as an entire process + /// rather than a prefix. + /// - PIDs: Use prefix `pid`, can use regex or match word (case is irrelevant). + /// - CPU: Use prefix `cpu`, cannot use r/m/c (regex, match word, case). Can compare. |