LeftHK - A hotkey daemon written in Rust

Related tags

System tools lefthk


LeftHK - A hotkey daemon written in Rust


The configuration file should be created in ~/.config/lefthk/ and called config.kdl. If the configuration file is not created the program will exit. Example config:

Execute "st" {
    modifier "Mod4"
    key "x"

Kill {
    modifier "Mod4" "Shift"
    key "q"

Reload {
    modifier "Mod4"
    key "r"

ExitChord {
    modifier "Mod4"
    key "q"

Chord {
    modifier "Mod4"
    key "c"
    Execute "st -e htop" {
        modifier "Mod4"
        key "x"

    Kill {
        modifier "Mod4"
        key "c"

Reload, Kill, Chord, and ExitChord are the only internal commands. To run a normal command you need to call Execute, with the added value of the command. A chord can accept any amount and type of extra keybind nodes, which when started blocks previous keybinds and will exit once a sub-keybind is executed. A Chord will take the ExitChord set within it first, then if not set it will take the ExitChord from its parent (e.g. a Chord within a Chord will take the ExitChord from the previous Chord). There is a pipe which receives commands through $XDG_RUNTIME_DIR/lefthk/commands.pipe, currently only accepts Reload and Kill.

If the config file changes it will live update.

  • refactoring


    Mainly some refactoring with the command-handling in lefthk-core.


    Whenever you want to create a new command, this just needs to be done: config/command/<new command>.rs

    // register the new command
    pub struct MyNewCommand {
        // the arguments of the command
    impl Command for MyNewCommand {
        // ...


    opened by TornaxO7 10
  • [Discussion] Restructure `Command`

    [Discussion] Restructure `Command`


    I propose to write every command as a struct instead of putting all commands into an enum. What do you think about @AethanFoot


    A command has a lot of properties in my opinion. This includes: - matching a string to themself - converting themself to a string - do that what their name says (like reload the daemon if the Reload Command was called) - having different arguments

    those are all I could find yet and in my opinion this is why we should split the commands up from an enum into a struct for each command.

    How should it look like

    Example: config/command/mod.rs

    mod chord;
    mod execute;
    mod exit_chord;
    mod kill;
    mod reload;
    use std::convert::TryFrom;
    use crate::errors::LeftError;
    pub use self::{chord::Chord, execute::Execute, exit_chord::ExitChord, reload::Reload};
    pub trait Command<'a>: ToString + Default + TryFrom<&'a str> {}


    use crate::config::Keybind;
    use super::Command;
    #[derive(Debug, PartialEq)]
    pub struct Chord(Vec<Keybind>);
    impl Chord {
        pub fn new(keybinds: Vec<Keybind>) -> Self {
    impl<'a> Command<'a> for Chord {
        // bla bla
    // other functions which are *only* relevant to `Chord`

    Pros and Cons


    • logic of each command is only isolated in a file, while an enum gets bigger and bigger and the the enum includes the whole logic of all enum-entries

    yeah, that's basically it. All functions which affect to all commands (like searching through them) can be put to config/command/mod.rs, the "main" command file.


    • the syntax might be a little bit strange for the beginning like here. This should be, in my opinion:
    fn main() {
        // ...
        // ...
    fn send_command(command: Box<dyn Command>) {
        let path = errors::exit_on_error!(BaseDirectories::with_prefix(lefthk_core::LEFTHK_DIR_NAME));
        let pipe_name = Pipe::pipe_name();
        let pipe_file = errors::exit_on_error!(path.place_runtime_file(pipe_name));
        let mut pipe = fs::OpenOptions::new().write(true).open(&pipe_file).unwrap();
        // difference is here with `command.to_string()`
        writeln!(pipe, "{}", command.to_string()).unwrap();

    which would be more typesafety and also makes it easier to change the code since you don't have to replace the string "Kill" everywhere if you want to rename this command.

    opened by TornaxO7 6
  • Add command ExitChord

    Add command ExitChord

    Add a keybind for exiting out of current chord. If a "global" one is set, it will be used for all child chords unless one is set for it specifically. This will occur recursively as chords can technically be nested infinitely :fearful:. Thanks.

    opened by AethanFoot 0
  • Key pressed event missed due to multiple keycodes for one keysym

    Key pressed event missed due to multiple keycodes for one keysym

    I had trouble making the deamon react to a key press from XF86AudioPlay coming from a bluetooth headset, due to this keysym have multiple codes associated (had 172 by default and the headset sent a 208).

    It seems the reason is the same as described here : https://github.com/electron/electron/issues/2210 , in short XKeyGrab is only used with code 172 thus code 208 aren't registered.

    I manually added a XKeyGrab for the code 208 and it worked, but I haven't found a more elegant solution (not really familiar with Xlib). I have seen people use xbindkeys to detect key pressed event with this code and map it to send a XF86AudioPlay key pressed event with xdotool, maybe lefthk could also have some way to configure keys by code?

    opened by Lieunoir 0
  • Default Modifier

    Default Modifier

    Create a new default modifier param and make keybind modifier optional, based on #9 Create test for the new parser of config

    • [x] feature
    • [x] tests

    Note: after talking about this feature, I think this feature is necessary for future features.

    opened by SergioRibera 1
  • [bug] daemon works 2 times of 5

    [bug] daemon works 2 times of 5


    Thank you so much for you work! I just wanted to test out new eco-system tool cause I really like "modes" of keybindings. But when I start daemon by some reason it works approx. 2 times of 5. I made a small look into code and realized that most probably it happens somewhere here when it is trying to get mutable reference of listener(???).

    Could you please help with this issue?

    opened by denvaki 2
  • [Feature] Sub command similar to `leftwm state`

    [Feature] Sub command similar to `leftwm state`

    This could be used to implement some keybind infos in bars or widgets. Especially when entering a chord it might be useful to have visual feedback and info about the available key commands.

    opened by VuiMuich 0
  • [feature] interactive mode

    [feature] interactive mode

    Eventually it would be nice to have a interactive mode (maybe with a little tui?) to create new keybinds. This should be especially be helpful for binding obscure keys, or with use of odd keyboad layouts.

    opened by VuiMuich 0
Process killer daemon for out-of-memory scenarios

bustd: Available memory or bust! bustd is a lightweight process killer daemon for out-of-memory scenarios for Linux! Features Small memory usage! bust

Vinícius Miguel 188 Dec 14, 2022
`haproxy_autconfd` is a daemon that automatically assembles a HAProxy config and restarts HAProxy if the config changes

haproxy_autconfd Welcome to haproxy_autconfd ?? haproxy_autconfd is a daemon that automatically assembles a HAProxy config and restarts HAProxy if the

null 0 Nov 9, 2021
A modern replacement for ps written in Rust

procs procs is a replacement for ps written in Rust. Documentation quick links Features Platform Installation Usage Configuration Features Output by t

null 3.6k Jan 5, 2023
Blazing 💥 fast terminal-ui for git written in rust 🦀

Blazing fast terminal client for git written in Rust Features Fast and intuitive keyboard only control Context based help (no need to memorize tons of

Stephan Dilly 11.8k Jan 5, 2023
A simple and fast download accelerator, written in Rust

zou A simple and fast download accelerator, written in Rust Zou is a Snatch fork by @k0pernicus. Snatch is a fast and interruptable download accelerat

Antonin Carette 173 Dec 4, 2022
A bash-like Unix shell written in Rust

Cicada Unix Shell Cicada is a simple Unix shell written in Rust. Documents Install cicada Environment Variables Cicada Builtins Completion RC File His

Hugo Wang 921 Dec 28, 2022
Performs distributed command execution, written in Rust w/ Tokio

Concurr: Distributed and Concurrent Command Execution, in Rust This project is dual licensed under MIT and Apache 2.0. Originally inspired by the GNU

Michael Murphy 93 Dec 18, 2022
A TUI system monitor written in Rust

NO LONGER MAINTAINED. For a similar program, check out https://github.com/ClementTsang/bottom. ytop Another TUI based system monitor, this time in Rus

Caleb Bassi 2.1k Jan 3, 2023
A non-root version of traceroute written in Rust

tracepath-rs A non-root version of traceroute written in Rust for Linux.

Peter Malmgren 9 Dec 30, 2022
Dancing Links (“dlx”) solver for the exact cover problem, written in Rust. Can be used to create a sudoku solver.

Dancing Links “dlx” Dancing Links solver for “algorithm X” by Knuth This solver solves the exact cover problem using “algorithm X”, implemented using

bluss 4 Nov 19, 2022
A system handler to get information and interact with processes written in Rust

A system handler to get information and interact with processes written in Rust

Guillaume Gomez 1.1k Jan 3, 2023
minimalistic command launcher in rust

rrun Note: Apart from the occasional fix, this project is not actively developed anymore. rrun works fine and should run/compile for the time being on

null 105 Nov 18, 2022
Yet another fancy watcher. (Rust)

funzzy Yet another fancy watcher. (Inspired by antr / entr) Configure execution of different commands using semantic yaml. # .watch.yaml # list here a

Cristian Oliveira 188 Dec 12, 2022
A more intuitive version of du in rust

Dust du + rust = dust. Like du but more intuitive. Why Because I want an easy way to see where my disk is being used. Demo Install Cargo cargo install

andy.boot 5.5k Jan 8, 2023
Fuzzy Finder in rust!

Life is short, skim! Half of our life is spent on navigation: files, lines, commands… You need skim! It is a general fuzzy finder that saves you time.

Jinzhou Zhang 3.7k Jan 4, 2023
A library to listen to global hotkeys in Rust

Rust Hotkey A library to listen to global hotkeys in Rust How to use See the examples folder for how to use this library. OS Support This lib aims to

James Birtles 44 Dec 12, 2022
🔮 Futuristic take on hexdump, made in Rust.

hex (hx) Futuristic take on hexdump. hx accepts a file path as input and outputs a hexadecimal colorized view to stdout. $ hx tests/files/alphanumeric

Julian Sitkevich 387 Dec 27, 2022
Cross-platform Rust rewrite of the GNU coreutils

uutils coreutils uutils is an attempt at writing universal (as in cross-platform) CLI utilities in Rust. This repository is intended to aggregate GNU

null 13k Dec 30, 2022
A rust layered configuration loader with zero-boilerplate configuration management.

salak A layered configuration loader with zero-boilerplate configuration management. About Features Placeholder Key Convension Cargo Features Default

Daniel YU 28 Sep 20, 2022