From 8e8f7260240beb10b95811f6d5d461c7e1c56e2c Mon Sep 17 00:00:00 2001 From: Carlos D Date: Wed, 3 Apr 2019 21:52:58 +1100 Subject: [PATCH 1/2] Add docs, manpage --- Cargo.lock | 2 +- Cargo.toml | 13 +-- build.rs | 24 +++++ doc/.gitignore | 1 + doc/mxhkd.1.md | 179 +++++++++++++++++++++++++++++++++++++ examples/mxhkd_config.toml | 8 +- shell.nix | 1 + src/config.rs | 2 +- 8 files changed, 218 insertions(+), 12 deletions(-) create mode 100644 build.rs create mode 100644 doc/.gitignore create mode 100644 doc/mxhkd.1.md diff --git a/Cargo.lock b/Cargo.lock index 5d5a50d..c3d3c79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,7 +83,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mxhkd" -version = "0.0.1" +version = "0.0.3" dependencies = [ "bimap 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index fbd8189..4d627be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,10 @@ [package] -name = "mxhkd" +name = "mxhkd" description = "Modal X Hotkey Daemon" -version = "0.0.2" -authors = ["Carlos D'Agostino ", "Robert McMichael "] -edition = "2018" +version = "0.0.3" +authors = ["Carlos D'Agostino ", "Robert McMichael "] +edition = "2018" +build = "build.rs" [dependencies] toml = "0.4" @@ -12,9 +13,9 @@ regex = "1.1" bimap = "0.3" [dependencies.xcb] -version = "0.8" +version = "0.8" features = ["xlib_xcb"] [dependencies.serde] -version = "1.0" +version = "1.0" features = ["derive"] diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..2661a81 --- /dev/null +++ b/build.rs @@ -0,0 +1,24 @@ +use std::process::Command; + +// Build the documentation first +fn main() { + let date = Command::new("date") + .arg("-I") + .arg("-r") + .arg("Cargo.toml") + .output() + .unwrap(); + + assert!(date.status.success()); + + let date = String::from_utf8(date.stdout).unwrap(); + + let ronn = Command::new("ronn") + .arg("--date") + .arg(date) + .arg("doc/mxhkd.1.md") + .status() + .unwrap(); + + assert!(ronn.success()); +} diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..d453d1d --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +mxhkd.1 diff --git a/doc/mxhkd.1.md b/doc/mxhkd.1.md new file mode 100644 index 0000000..4c114dc --- /dev/null +++ b/doc/mxhkd.1.md @@ -0,0 +1,179 @@ +# mxhkd -- Modal X Key Daemon + +## SYNOPSIS + +`mxhkd` --config + +`mxhkd` --version + +`mxhkd` --help + +## DESCRIPTION + +`mxhkd` is an X program that reacts to input events by executing commands. +It listens for a `mode_switch` specification, which can be either a single +key or a key plus a modifier. The configuration specifies bindings which +when detected will run commands specified by the user. + +There are two modes, and one pseudo-mode: + +- `Window`: In this mode, `mxhkd` only listens on the `mode_switch` + specification, and allows all other keypress events to pass through. + +- `Normal`: This mode is triggered by `mxhkd` when it detects that + `mode_switch` was pressed by the user. In this mode `mxhkd` listens to + all key presses waiting for a `binding` to be attempted. It exits back + into `Window` mode regardless of successfully running a binding or not. + +- `Normal + Sticky`: This is a pseudo mode which is optional. In the default + `Normal` mode, `mxhkd` will exit back into `Window` mode after a successful + or unsuccessful command. However in `Sticky` it will stay in `Normal` mode + waiting for bindings. This is a useful command e.g. if the user is + repeating the same command over and over, such as resizing windows or + the changing the volume. + +The intention of `mxhkd` is that it is `modal`, in order to discourage the +use of key chords. In some circumstances, simple key chords are acceptable. +For example, a `mode_switch` could be specified as + +``` +mode_switch = { key = "space", modifier = "Alt" } +``` + +This will only trigger `mxhkd` to go into `Normal` mode when `Alt+Space` +is presssed by the user. In general, the user should choose an unintrusive +key to switch modes. + +Another example can be for the bindings: + +``` +h = "i3 focus left" +j = "i3 focus down" +k = "i3 focus up" +l = "i3 focus right" +f = "i3 fullscreen toggle" + +H = "i3 resize grow width 5 px or 5 ppt" +J = "i3 resize shrink height 5 px or 5 ppt" +K = "i3 resize grow height 5 px or 5 ppt" +L = "i3 resize shrink width 5 px or 5 ppt" +F = "i3 floating toggle" +``` + +The top commands refer to the letters `h`, `j`, `k`, `l`, `f` pressed +normally (that is, without simultaneously pressing any other keys). +The uppercase notation refers to the same letters pressed while +pressing `Shift`. `mxhkd` can differenciate between these two in order +to overload the keystrokes while still focusing on comfort. + +## CONFIGURATION + +The configuration file for `mxhkd` is in `toml`. There are two top-level +keys to configure: + +* `settings`: Controls the overall behavior of `mxhkd`. + + * `shell` (**required**): The shell in which all `mxhkd` commands + are executed. `bash` and `fish` have been tested. In principle, any + shell that can accept a `-c` command will work. + + * `mode_switch` (**required**): The key specification used to switch + modes. This will work in both `Normal` and `Window` mode. Examples can be + + ``` + mode_switch = { key = "space", modifier = "Alt" } + ``` + + This will trigger `mode_switch` when `Alt+Space` is pressed by the user. + + Another example is + + ``` + mode_switch = { key = "Caps_Lock" } + ``` + + This will trigger `mode_switch` when `Caps_Lock` is pressed. This would + work nicely if for example the key has been reconfigured to disable + setting all caps. + + * `mode_change_cmd` (**optional**): Command that `mxhkd` will run every time + the `mode` changes. This setting will replace the string `%{mode}%` with + the corresponding mode. + + * `not_found_cmd` (**optional**): Command that `mxhkd` will run every time + a binding is attempted but not found in the configuration. Recommended. + `mxhkd` will replace the string `%{binding}%` with the failed binding + issued by the user. + + * `sticky_mode` (**optional**): Will enable the `Normal + Sticky` pseudo + mode. When pressed. This key will only be triggered once in `Normal` + mode. In `Window` mode it has no effect. + +* `bindings`: Defines the custom bindings attached to commands. For example: + + ``` + a = "rofi -show window -font 'Envy Code R 13'" + o = "rofi -show run -font 'Envy Code R 13'" + t = "termite" + + sx = "spotify-controls play-pause" + sn = "spotify-controls next" + sp = "spotify-controls prev" + + sl = "i3lock -i ~/Downloads/mountains_bg.png" + ``` + +For this sample configuration, a user who wants to lock the screen using +`i3lock` would first press `s` followed by `l`; `mxhkd` will trigger +the command immediately. + +**NOTE**: Overlapping bindings are not supported. No binding should be +the prefix of another binding. + +## OPTIONS + +`--config`: Specifies the location of the configuration file and starts +`mxhkd` with it. + + +`--help`: Shows the help menu. + + +`--version`: Outputs the program version. + +## SYNTAX + +`mxhkd` uses a configuration file in the `toml` format. Refer +to the example in the source code. + +## BUGS + +`mxhkd` has a runtime dependency in `xmodmap`. This will go away in +the future. It's used at startup to determine the key code to +character layout. + +Please file any bugs encountered using the following +[link](https://github.com/carlosdagos/mxhkd/issues) + +## HISTORY + +* March 2019: v0.0.1 +* April 2019: v0.0.3 + +## AUTHOR + +Carlos D'Agostino + +Robbie McMichael + +## COPYRIGHT + +See LICENSE file in the source code. + +## SEE ALSO + +[mxhkd](https://github.com/carlosdagos/mxhkd) + +[sxhkd](https://github.com/baskerville/sxhkd) + +[toml](https://github.com/toml-lang/toml) diff --git a/examples/mxhkd_config.toml b/examples/mxhkd_config.toml index 6c2e3b2..c24de9c 100644 --- a/examples/mxhkd_config.toml +++ b/examples/mxhkd_config.toml @@ -1,8 +1,8 @@ [settings] -# Mandatory +# Required shell = "bash" -# MANDATORY +# REQUIRED # # Choose an unobtrusive but easy to reach `key`. `Escape` might not # work for everyone because it's used by almost every program, so I @@ -42,7 +42,7 @@ not_found_cmd = ''' # attempt at running a binding. However in sticky mode # the mode will stay until `mode_switch` is triggered # again. -sticky_mode = "F1" +sticky_mode = "Escape" # TODO # @@ -50,7 +50,7 @@ sticky_mode = "F1" # in sticky mode. # sticky_repeat = "period" -# MANDATORY +# REQUIRED # # Define the bindings to run. DO NOT set up overlapping bindings as # one of them will never work. Will add an error for that later. diff --git a/shell.nix b/shell.nix index f07ce57..2cc85c6 100644 --- a/shell.nix +++ b/shell.nix @@ -20,6 +20,7 @@ stdenv.mkDerivation rec { RUST_BACKTRACE = 1; buildInputs = [ + ronn python3 xorg.libxcb xorg.libX11 diff --git a/src/config.rs b/src/config.rs index c49d405..7e615f2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,8 +42,8 @@ pub struct Config { #[cfg(test)] mod config_tests { - use toml; use crate::types::*; + use toml; #[test] fn test_config_parse_simple_mode_key() { From 1d76934e7d440ba6701a6e61b41033d10932f5d7 Mon Sep 17 00:00:00 2001 From: Carlos D Date: Wed, 3 Apr 2019 21:55:24 +1100 Subject: [PATCH 2/2] Update README --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8264af3..974e4e0 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,14 @@ manager you want. `bspwm` might be a natural fit to use with _mxhkd_, but also something like `herbstluftwm`. Up to you. Testing was mostly done with `i3` and that worked fine as well. +## Documentation + +Docs can be found [here](doc/mxhkd.1.md). + +### Sample configuration + +See the [`examples` folder](./examples). + ## Runnning If it's installed: @@ -58,10 +66,6 @@ nix-shell --command "cargo run -- --config examples/mxhkd_config.toml" Have a look at the `shell.nix` file to see which system dependencies are needed. -## Configuration - -See the [`examples` folder](./examples). - ## Compatibility _mxhkd_ takes over your main X window, so it might not be compatible with