summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2020-05-02 23:54:10 -0400
committerGitHub <noreply@github.com>2020-05-02 23:54:10 -0400
commit39d7450aad1f9554a04d69ae655507eef0f3cac1 (patch)
tree224a86904999fad1600020fb8a66c3a523dc1fb4
parent2828449544b4ad5fbfdc6be21b85bd23b0a13e7c (diff)
parent5636f866567411e583118b63c29ec2659eae8da9 (diff)
Merge pull request #139 from ClementTsang/improve_searching
Improve searching
-rw-r--r--CHANGELOG.md12
-rw-r--r--CONTRIBUTING.md3
-rw-r--r--Cargo.lock20
-rw-r--r--Cargo.toml7
-rw-r--r--README.md106
-rw-r--r--assets/basic_mode.pngbin114620 -> 194990 bytes
-rw-r--r--assets/or_search.pngbin0 -> 62099 bytes
-rw-r--r--assets/search_cpu_filter.pngbin0 -> 34992 bytes
-rw-r--r--assets/search_empty.pngbin0 -> 172847 bytes
-rw-r--r--assets/simple_advanced_search.pngbin0 -> 51363 bytes
-rw-r--r--assets/simple_search.pngbin0 -> 51685 bytes
-rw-r--r--src/app.rs141
-rw-r--r--src/app/query.rs615
-rw-r--r--src/app/states.rs63
-rw-r--r--src/canvas.rs14
-rw-r--r--src/canvas/canvas_colours.rs2
-rw-r--r--src/canvas/dialogs/filter_dialog.rs1
-rw-r--r--src/canvas/widgets/basic_table_arrows.rs15
-rw-r--r--src/canvas/widgets/cpu_graph.rs3
-rw-r--r--src/canvas/widgets/process_table.rs158
-rw-r--r--src/constants.rs63
-rw-r--r--src/data_conversion.rs48
-rw-r--r--src/main.rs94
-rw-r--r--src/utils/error.rs11
-rw-r--r--src/utils/logging.rs1
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).
diff --git a/Cargo.lock b/Cargo.lock
index 2a03b367..ae20694c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index 58b5766a..ab5a1a70 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/README.md b/README.md
index f98a6648..83a757b7 100644
--- a/README.md
+++ b/README.md
@@ -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
index a11b1798..21a2fcd3 100644
--- a/assets/basic_mode.png
+++ b/assets/basic_mode.png
Binary files differ
diff --git a/assets/or_search.png b/assets/or_search.png
new file mode 100644
index 00000000..2ca4fa90
--- /dev/null
+++ b/assets/or_search.png
Binary files differ
diff --git a/assets/search_cpu_filter.png b/assets/search_cpu_filter.png
new file mode 100644
index 00000000..931fa92f
--- /dev/null
+++ b/assets/search_cpu_filter.png
Binary files differ
diff --git a/assets/search_empty.png b/assets/search_empty.png
new file mode 100644
index 00000000..38c63687
--- /dev/null
+++ b/assets/search_empty.png
Binary files differ
diff --git a/assets/simple_advanced_search.png b/assets/simple_advanced_search.png
new file mode 100644
index 00000000..94f94319
--- /dev/null
+++ b/assets/simple_advanced_search.png
Binary files differ
diff --git a/assets/simple_search.png b/assets/simple_search.png
new file mode 100644
index 00000000..b2c73888
--- /dev/null
+++ b/assets/simple_search.png
Binary files differ
diff --git a/src/app.rs b/src/app.rs
index 18581e43..ff39f06e 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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.