diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..98b5c3744 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,4 @@ +[target.x86_64-pc-windows-msvc] +rustflags = ["-Ctarget-feature=+crt-static"] +[target.i686-pc-windows-msvc] +rustflags = ["-Ctarget-feature=+crt-static"] diff --git a/.travis.yml b/.travis.yml index e3ab8a0bd..6d1953ad8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,8 @@ before_install: powershell Install-WindowsFeature Net-Framework-Core; choco install -y wixtoolset; export PATH=$PATH:"/c/Program Files (x86)/WiX Toolset v3.11/bin"; + choco install zip; + rustup target add i686-pc-windows-msvc; fi elif [[ $TRAVIS_OS_NAME == "osx" ]]; then export TARGET=x86_64-apple-darwin; @@ -45,49 +47,86 @@ notifications: on_success: never before_deploy: - - cargo install --path . --target $TARGET --locked --force; - | + echo "Test whether installing works. This is mostly just a sanity check."; + cargo install --path . --target $TARGET --locked --force; + - | + echo "Building release..." if [[ $TRAVIS_OS_NAME == "windows" ]]; then - choco install zip; - rustup target add x86_64-pc-windows-msvc; + + echo "Building Windows 64-bit..."; cargo build --release --target x86_64-pc-windows-msvc; + local target_dir=$(ls target/release/build/bottom-*/out/rg.bash | head -n1 | xargs dirname) + cp -r $target_dir completions mv "./target/x86_64-pc-windows-msvc/release/btm" "btm.exe"; strip "btm.exe" - zip bottom_x86_64-pc-windows-msvc.zip "btm.exe"; + zip -r bottom_x86_64-pc-windows-msvc.zip "btm.exe" "completions"; rm "btm.exe" - rustup target add i686-pc-windows-msvc; + rm -r "completions" + + echo "Building Windows 32-bit..."; + cargo clean; cargo build --release --target i686-pc-windows-msvc; + local target_dir=$(ls target/release/build/bottom-*/out/rg.bash | head -n1 | xargs dirname) + cp -r $target_dir completions mv "./target/i686-pc-windows-msvc/release/btm" "btm.exe"; strip "btm.exe" - zip bottom_i686-pc-windows-msvc.zip "btm.exe"; + zip -r bottom_i686-pc-windows-msvc.zip "btm.exe" "completions"; rm "btm.exe" + rm -r "completions" + + echo "Building choco template..."; python "./deployment/windows/choco/choco_packager.py" "bottom_i686-pc-windows-msvc.zip" "bottom_x86_64-pc-windows-msvc.zip" $TRAVIS_TAG "./deployment/windows/choco/bottom.nuspec.template" "./deployment/windows/choco/chocolateyinstall.ps1.template" "./deployment/windows/choco/bottom.nuspec" "./deployment/windows/choco/tools/chocolateyinstall.ps1" "./deployment/windows/choco/tools/"; cd "./deployment/windows/choco/" zip -r choco.zip "bottom.nuspec" "tools/"; cd "../../../"; mv "./deployment/windows/choco/choco.zip" "./choco.zip" + + echo "Building msi file..."; cargo install cargo-wix; cargo wix init; cargo wix; - python "./deployment/packager.py" $TRAVIS_TAG "./deployment/windows/winget/winget.yaml.template" "$TRAVIS_TAG.yaml" "SHA256" "./bottom_x86_64_installer.msi" ; + + echo "Building winget template..."; + python "./deployment/packager.py" $TRAVIS_TAG "./deployment/windows/winget/winget.yaml.template" "$TRAVIS_TAG.yaml" "SHA256" "./bottom_x86_64_installer.msi"; + + echo "Done Windows pre-deploy!"; else + echo "Building release for macOS/Linux..."; cargo build --release; cp ./target/release/btm btm; strip btm; + local target_dir=$(ls target/release/build/bottom-*/out/rg.bash | head -n1 | xargs dirname) + cp -r $target_dir completions + if [[ $TRAVIS_OS_NAME == "linux" ]]; then - tar -czvf bottom_x86_64-unknown-linux-gnu.tar.gz btm; + echo "Tar-ing Linux binary and completions..." + tar -czvf bottom_x86_64-unknown-linux-gnu.tar.gz btm completions; + + echo "Generating AUR template..."; python "./deployment/packager.py" $TRAVIS_TAG "./deployment/linux/arch/PKGBUILD_BIN.template" "./PKGBUILD_BIN" "SHA512" "./bottom_x86_64-unknown-linux-gnu.tar.gz"; curl -LO "https://github.com/ClementTsang/bottom/archive/$TRAVIS_TAG.tar.gz"; + + echo "Generating AUR binary template..."; python "./deployment/packager.py" $TRAVIS_TAG "./deployment/linux/arch/PKGBUILD.template" "./PKGBUILD" "SHA512" "./$TRAVIS_TAG.tar.gz"; rm "$TRAVIS_TAG.tar.gz"; + + echo "Tar-ing AUR PKGBUILDs..."; tar -czvf arch.tar.gz PKGBUILD_BIN PKGBUILD; + + # Note this requires the completions directory in the current directory. + echo "Generating Debian install file..."; cargo install cargo-deb; cargo deb; cp ./target/debian/bottom_*.deb .; elif [[ $TRAVIS_OS_NAME == "osx" ]]; then - tar -czvf bottom_x86_64-apple-darwin.tar.gz btm; + + echo "Tar-ing macOS binary and completions..." + tar -czvf bottom_x86_64-apple-darwin.tar.gz btm completions; # The bottom.rb file must be generated AFTER, since it relies on the Linux binary file. fi + + echo "Done macOS/Linux pre-deploy!"; fi deploy: diff --git a/.vscode/settings.json b/.vscode/settings.json index 554f59940..3c0c2b46a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -46,6 +46,7 @@ "markdownlint", "memb", "minwindef", + "n'th", "noheader", "ntdef", "nuget", diff --git a/Cargo.toml b/Cargo.toml index 5fa791b37..ce60333a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ categories = ["command-line-utilities", "visualization"] description = "A cross-platform graphical process/system monitor with a customizable interface and a multitude of features. Supports Linux, macOS, and Windows." readme = "README.md" default-run = "btm" +build = "build.rs" [[bin]] name = "btm" @@ -55,14 +56,22 @@ winapi = "0.3.9" assert_cmd = "1.0" predicates = "1" +[build-dependencies] +clap = "2.33" + [package.metadata.deb] section = "utility" assets = [ ["target/release/btm", "usr/bin/", "755"], ["LICENSE", "usr/share/doc/btm/", "644"], - ["README.md", "usr/share/doc/btm/README", "644"], + ["completions/btm.bash", "usr/share/bash-completion/completions/btm", "644"], + ["completions/btm.fish", "usr/share/fish/vendor_completions.d/btm.fish", "644"], + ["completions/_btm", "usr/share/zsh/vendor-completions/", "644"], ] extended-description = """\ +A cross-platform graphical process/system monitor with a customizable interface and a multitude of +features. Supports Linux, macOS, and Windows. + By default, bottom will look for a config file in ~/.config/bottom/bottom.toml. If one is not specified it will fall back to defaults. If a config file does not exist at the specified or default location, a blank one will be created for the user. diff --git a/README.md b/README.md index 82a355a8d..16f395763 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ A cross-platform graphical process/system monitor with a customizable interface - [Homebrew](#homebrew) - [Scoop](#scoop) - [Chocolatey](#chocolatey) + - [Auto-completion](#auto-completion) - [Usage](#usage) - [Flags](#flags) - [Options](#options) @@ -86,6 +87,9 @@ tar -xzvf 0.4.7.tar.gz cargo install --path . ``` +Or, you can just download the binary from the [latest release](https://github.com/ClementTsang/bottom/releases/latest) and install/use it +in whatever way you want. + ### Cargo ```bash @@ -152,6 +156,19 @@ choco install bottom choco install bottom --version=0.4.7 ``` +### Auto-completion + +Shell completions are included in binary releases, and are generated in the same directory as the +binary if bottom is manually built. + +- For bash, move `btm.bash` to `$XDG_CONFIG_HOME/bash_completion or /etc/bash_completion.d/`. +- For fish, move `btm.fish` to `$HOME/.config/fish/completions/`. +- For zsh, move `_btm` to one of your `$fpath` directories. +- For PowerShell, add `. _btm.ps1` to your PowerShell + [profile](). + +Some install scripts (i.e. AUR) will automatically do this for you. + ## Usage Run using `btm`. diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..472a0a6cf --- /dev/null +++ b/build.rs @@ -0,0 +1,31 @@ +use clap::Shell; +use std::{env, fs, process}; +include!("src/clap.rs"); + +fn main() { + // OUT_DIR is where extra build files are written to for Cargo. + let out_dir = match env::var_os("OUT_DIR") { + Some(out_dir) => out_dir, + None => { + eprintln!("The OUT_DIR environment variable was not set! Aborting..."); + process::exit(1) + } + }; + match fs::create_dir_all(&out_dir) { + Ok(()) => {} + Err(err) => { + eprintln!( + "Failed to create a directory at OUT_DIR location {:?}, encountered error {:?}. Aborting...", + out_dir, err + ); + process::exit(1) + } + } + + // Generate completions + let mut app = build_app(); + app.gen_completions("btm", Shell::Bash, &out_dir); + app.gen_completions("btm", Shell::Zsh, &out_dir); + app.gen_completions("btm", Shell::Fish, &out_dir); + app.gen_completions("btm", Shell::PowerShell, &out_dir); +} diff --git a/deployment/linux/arch/PKGBUILD.template b/deployment/linux/arch/PKGBUILD.template index 583209ae6..e9311b433 100644 --- a/deployment/linux/arch/PKGBUILD.template +++ b/deployment/linux/arch/PKGBUILD.template @@ -26,4 +26,9 @@ package() { cd $pkgname-$pkgver install -Dm755 target/release/btm "$pkgdir/usr/bin/btm" install -Dm644 "LICENSE" "$pkgdir/usr/share/licenses/${pkgname}/LICENSE" + + local target_dir=$(ls target/release/build/bottom-*/out/rg.bash | head -n1 | xargs dirname) + install -Dm644 "$target_dir"/_btm "$pkgdir/usr/share/zsh/site-functions/_btm" + install -Dm644 "$target_dir"/btm.bash "$pkgdir/usr/share/bash-completion/completions/btm" + install -Dm644 "$target_dir"/btm.fish "$pkgdir/usr/share/fish/vendor_completions.d/btm.fish" } \ No newline at end of file diff --git a/deployment/linux/arch/PKGBUILD_BIN.template b/deployment/linux/arch/PKGBUILD_BIN.template index e2003c95d..9111363cf 100644 --- a/deployment/linux/arch/PKGBUILD_BIN.template +++ b/deployment/linux/arch/PKGBUILD_BIN.template @@ -10,15 +10,19 @@ arch=('x86_64') url="https://github.com/ClementTsang/bottom" license=(MIT) source=( - archive-${pkgver}.tar.gz::${url}/releases/download/${pkgver}/bottom_x86_64-unknown-linux-gnu.tar.gz - LICENSE::${url}/raw/${pkgver}/LICENSE + archive-${pkgver}.tar.gz::${url}/releases/download/${pkgver}/bottom_x86_64-unknown-linux-gnu.tar.gz + LICENSE::${url}/raw/${pkgver}/LICENSE ) sha512sums=( - '$hash1' - SKIP + '$hash1' + SKIP ) package() { - install -Dm755 btm "$pkgdir"/usr/bin/btm - install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE + install -Dm755 btm "$pkgdir"/usr/bin/btm + install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE + + install -Dm644 completion/_btm "$pkgdir/usr/share/zsh/site-functions/_btm" + install -Dm644 completion/btm.bash "$pkgdir/usr/share/bash-completion/completions/btm" + install -Dm644 completion/btm.fish "$pkgdir/usr/share/fish/vendor_completions.d/btm.fish" } diff --git a/deployment/macos/homebrew/bottom.rb.template b/deployment/macos/homebrew/bottom.rb.template index 451905cf9..1e9fce5bf 100644 --- a/deployment/macos/homebrew/bottom.rb.template +++ b/deployment/macos/homebrew/bottom.rb.template @@ -11,6 +11,8 @@ class Bottom < Formula end def install + bash_completion.install "completion/rg.bash" + zsh_completion.install "completion/_rg" bin.install "btm" ohai "You're done! Run with \"btm\"" ohai "For runtime flags, see \"btm --help\"" diff --git a/src/bin/main.rs b/src/bin/main.rs index 34c8c2b7c..954444910 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -29,7 +29,7 @@ fn main() -> error::Result<()> { { utils::logging::init_logger()?; } - let matches = get_matches(); + let matches = clap::get_matches(); let config: Config = create_config(matches.value_of("CONFIG_LOCATION"))?; diff --git a/src/clap.rs b/src/clap.rs new file mode 100644 index 000000000..eb376d8ba --- /dev/null +++ b/src/clap.rs @@ -0,0 +1,273 @@ +use clap::*; + +const TEMPLATE: &str = "\ +{bin} {version} +{author} + +{about} + +USAGE: +{usage} + +FLAGS: +{flags} + +OPTIONS: +{options} +"; + +pub fn get_matches() -> clap::ArgMatches<'static> { + build_app().get_matches() +} + +pub fn build_app() -> App<'static, 'static> { + // Temps + let kelvin = Arg::with_name("KELVIN") + .short("k") + .long("kelvin") + .help("Sets the temperature type to Kelvin.") + .long_help( + "\ +Sets the temperature type to Kelvin.\n\n", + ); + let fahrenheit = Arg::with_name("FAHRENHEIT") + .short("f") + .long("fahrenheit") + .help("Sets the temperature type to Fahrenheit.") + .long_help( + "\ +Sets the temperature type to Fahrenheit.\n\n", + ); + let celsius = Arg::with_name("CELSIUS") + .short("c") + .long("celsius") + .help("Sets the temperature type to Celsius.") + .long_help( + "\ +Sets the temperature type to Celsius. This is the default +option.\n\n", + ); + + // All flags. These are in alphabetical order + let autohide_time = Arg::with_name("AUTOHIDE_TIME") + .long("autohide_time") + .help("Temporarily shows the time scale in graphs.") + .long_help( + "\ +Automatically hides the time scaling in graphs after being +shown for a brief moment when zoomed in/out. If time is +disabled via --hide_time then this will have no effect.\n\n\n", + ); + let basic = Arg::with_name("BASIC_MODE") + .short("b") + .long("basic") + .help("Hides graphs and uses a more basic look.") + .long_help( + "\ +Hides graphs and uses a more basic look. Design is largely +inspired by htop's.\n\n", + ); + let battery = Arg::with_name("BATTERY") + .long("battery") + .help("Shows the battery widget.") + .long_help( + "\ +Shows the battery widget in default or basic mode. No effect on +custom layouts.\n\n", + ); + let case_sensitive = Arg::with_name("CASE_SENSITIVE") + .short("S") + .long("case_sensitive") + .help("Enables case sensitivity by default.") + .long_help( + "\ +When searching for a process, enables case sensitivity by default.\n\n", + ); + let disable_click = Arg::with_name("DISABLE_CLICK") + .long("disable_click") + .help("Disables mouse clicks.") + .long_help( + "\ +Disables mouse clicks from interacting with the program.\n\n", + ); + let dot_marker = Arg::with_name("DOT_MARKER") + .short("m") + .long("dot_marker") + .help("Uses a dot marker for graphs.") + .long_help( + "\ +Uses a dot marker for graphs as opposed to the default braille +marker.\n\n", + ); + let group = Arg::with_name("GROUP_PROCESSES") + .short("g") + .long("group") + .help("Groups processes with the same name by default.") + .long_help( + "\ +Groups processes with the same name by default.\n\n", + ); + let hide_avg_cpu = Arg::with_name("HIDE_AVG_CPU") + .short("a") + .long("hide_avg_cpu") + .help("Hides the average CPU usage.") + .long_help( + "\ +Hides the average CPU usage from being shown.\n\n", + ); + let hide_table_gap = Arg::with_name("HIDE_TABLE_GAP") + .long("hide_table_gap") + .help("Hides the spacing between table headers and entries.") + .long_help( + "\ +Hides the spacing between table headers and entries.\n\n", + ); + let hide_time = Arg::with_name("HIDE_TIME") + .long("hide_time") + .help("Completely hides the time scaling.") + .long_help( + "\ +Completely hides the time scaling from being shown.\n\n", + ); + let left_legend = Arg::with_name("LEFT_LEGEND") + .short("l") + .long("left_legend") + .help("Puts the CPU chart legend to the left side.") + .long_help( + "\ +Puts the CPU chart legend to the left side rather than the right side.\n\n", + ); + let regex = Arg::with_name("REGEX_DEFAULT") + .short("R") + .long("regex") + .help("Enables regex by default.") + .long_help( + "\ +When searching for a process, enables regex by default.\n\n", + ); + let current_usage = Arg::with_name("USE_CURR_USAGE") + .short("u") + .long("current_usage") + .help("Sets process CPU% to be based on current CPU%.") + .long_help( + "\ +Sets process CPU% usage to be based on the current system CPU% usage +rather than total CPU usage.\n\n", + ); + let use_old_network_legend = Arg::with_name("USE_OLD_NETWORK_LEGEND") + .long("use_old_network_legend") + .help("DEPRECATED - uses the older network legend.") + .long_help( + "\ +DEPRECATED - uses the older (pre-0.4) network widget legend. +This display is not tested anymore and could be broken.\n\n\n", + ); + let whole_word = Arg::with_name("WHOLE_WORD") + .short("W") + .long("whole_word") + .help("Enables whole-word matching by default.") + .long_help( + "\ +When searching for a process, return results that match the +entire query by default.\n\n", + ); + + // All options. Again, alphabetical order. + let config = Arg::with_name("CONFIG_LOCATION") + .short("C") + .long("config") + .takes_value(true) + .value_name("CONFIG PATH") + .help("Sets the location of the config file.") + .long_help( + "\ +Sets the location of the config file. Expects a config +file in the TOML format. If it doesn't exist, one is created.\n\n\n", + ); + let default_time_value = Arg::with_name("DEFAULT_TIME_VALUE") + .short("t") + .long("default_time_value") + .takes_value(true) + .value_name("MS") + .help("Default time value for graphs in ms.") + .long_help( + "\ +Default time value for graphs in milliseconds. The minimum +time is 30s (30000), and the default is 60s (60000).\n\n\n", + ); + let default_widget_count = Arg::with_name("DEFAULT_WIDGET_COUNT") + .long("default_widget_count") + .takes_value(true) + .value_name("INT") + .help("Sets the n'th selected widget type as the default.") + .long_help( + "\ +Sets the n'th selected widget type to use as the default widget. +Goes from left to right, top to bottom.\n\n", + ); //FIXME: Explain this + let default_widget_type = Arg::with_name("DEFAULT_WIDGET_TYPE") + .long("default_widget_type") + .takes_value(true) + .value_name("WIDGET TYPE") + .help("Sets which widget type to use as the default widget.") + .long_help( + "\ +Sets which widget type to use as the default widget. +Acceptable widget types are...\n\n", + ); //FIXME: Expand + let rate = Arg::with_name("RATE_MILLIS") + .short("r") + .long("rate") + .takes_value(true) + .value_name("MS") + .help("Sets a refresh rate in ms.") + .long_help( + "\ +Sets a refresh rate in milliseconds. The minimum is 250ms, +and defaults to 1000ms. Smaller values may take more resources.\n\n\n", + ); + let time_delta = Arg::with_name("TIME_DELTA") + .short("d") + .long("time_delta") + .takes_value(true) + .value_name("MS") + .help("The amount in ms changed upon zooming.") + .long_help( + "\ +The amount of time in milliseconds changed when zooming in/out. +The minimum is 1s (1000), and defaults to 15s (15000).\n\n\n", + ); + + App::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!()) + .about(crate_description!()) + .template(TEMPLATE) + .help_message("Prints help information. Use --help for more info.") + .version_message("Prints version information.") + .arg(kelvin) + .arg(fahrenheit) + .arg(celsius) + .group(ArgGroup::with_name("TEMPERATURE_TYPE").args(&["KELVIN", "FAHRENHEIT", "CELSIUS"])) + .arg(autohide_time) + .arg(basic) + .arg(battery) + .arg(case_sensitive) + .arg(disable_click) + .arg(dot_marker) + .arg(group) + .arg(hide_avg_cpu) + .arg(hide_table_gap) + .arg(hide_time) + .arg(left_legend) + .arg(regex) + .arg(current_usage) + .arg(use_old_network_legend) + .arg(whole_word) + .arg(config) + .arg(default_time_value) + .arg(default_widget_count) + .arg(default_widget_type) + .arg(rate) + .arg(time_delta) +} diff --git a/src/lib.rs b/src/lib.rs index 2022e1b53..4850d48ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,6 @@ use std::{ time::{Duration, Instant}, }; -use clap::*; - use crossterm::{ event::{poll, read, DisableMouseCapture, Event, KeyCode, KeyEvent, KeyModifiers, MouseEvent}, execute, @@ -43,6 +41,8 @@ pub mod constants; pub mod data_conversion; pub mod options; +pub mod clap; + pub enum BottomEvent { KeyInput(I), MouseInput(J), @@ -54,42 +54,6 @@ pub enum ResetEvent { Reset, } -pub fn get_matches() -> clap::ArgMatches<'static> { - clap_app!(app => - (name: crate_name!()) - (version: crate_version!()) - (author: crate_authors!()) - (about: crate_description!()) - (@arg HIDE_AVG_CPU: -a --hide_avg_cpu "Hides the average CPU usage.") - (@arg DOT_MARKER: -m --dot_marker "Use a dot marker instead of the default braille marker.") - (@group TEMPERATURE_TYPE => - (@arg KELVIN : -k --kelvin "Sets the temperature type to Kelvin.") - (@arg FAHRENHEIT : -f --fahrenheit "Sets the temperature type to Fahrenheit.") - (@arg CELSIUS : -c --celsius "Sets the temperature type to Celsius. This is the default option.") - ) - (@arg RATE_MILLIS: -r --rate +takes_value "Sets a refresh rate in milliseconds; the minimum is 250ms, defaults to 1000ms. Smaller values may take more resources.") - (@arg LEFT_LEGEND: -l --left_legend "Puts external chart legends on the left side rather than the default right side.") - (@arg USE_CURR_USAGE: -u --current_usage "Within Linux, sets a process' CPU usage to be based on the total current CPU usage, rather than assuming 100% usage.") - (@arg CONFIG_LOCATION: -C --config +takes_value "Sets the location of the config file. Expects a config file in the TOML format. If it doesn't exist, one is created.") - (@arg BASIC_MODE: -b --basic "Hides graphs and uses a more basic look") - (@arg GROUP_PROCESSES: -g --group "Groups processes with the same name together on launch.") - (@arg CASE_SENSITIVE: -S --case_sensitive "Match case when searching by default.") - (@arg WHOLE_WORD: -W --whole_word "Match whole word when searching by default.") - (@arg REGEX_DEFAULT: -R --regex "Use regex in searching by default.") - (@arg DEFAULT_TIME_VALUE: -t --default_time_value +takes_value "Default time value for graphs in milliseconds; minimum is 30s, defaults to 60s.") - (@arg TIME_DELTA: -d --time_delta +takes_value "The amount changed upon zooming in/out in milliseconds; minimum is 1s, defaults to 15s.") - (@arg HIDE_TIME: --hide_time "Completely hide the time scaling") - (@arg AUTOHIDE_TIME: --autohide_time "Automatically hide the time scaling in graphs after being shown for a brief moment when zoomed in/out. If time is disabled via --hide_time then this will have no effect.") - (@arg DEFAULT_WIDGET_TYPE: --default_widget_type +takes_value "The default widget type to select by default.") - (@arg DEFAULT_WIDGET_COUNT: --default_widget_count +takes_value "Which number of the selected widget type to select, from left to right, top to bottom. Defaults to 1.") - (@arg USE_OLD_NETWORK_LEGEND: --use_old_network_legend "Use the older (pre-0.4) network widget legend.") - (@arg HIDE_TABLE_GAP: --hide_table_gap "Hides the spacing between the table headers and entries.") - (@arg BATTERY: --battery "Shows the battery widget in default or basic mode. No effect on custom layouts.") - (@arg DISABLE_CLICK: --disable_click "Disables mouse clicks from interacting with the program.") - ) - .get_matches() -} - pub fn handle_mouse_event(event: MouseEvent, app: &mut App) { match event { MouseEvent::ScrollUp(_x, _y, _modifiers) => app.handle_scroll_up(),