Havel is a powerful utility for managing windows and hotkeys across multiple platforms, with a focus on Linux X11 environments. It allows for complex window management, hotkey configurations, and automated tasks via its own Havel scripting language.
- Features
- Installation
- Syntax Reference
- Keywords
- Conditional Hotkeys
- Examples
- Building
- Troubleshooting
- Global hotkey registration and management
- Dynamic conditional hotkeys with runtime evaluation
- Window tracking and manipulation
- Havel scripting language for complex automation (replacing Lua)
- Configurable via text files
- Cross-platform support
- C++17 compatible compiler (GCC 9+ or Clang 10+)
- CMake 3.10+
- X11 development libraries (on Linux)
- Qt6 development libraries
hotkey => action
data | transform1 | transform2
hotkey => {
// multiple statements
}
let variable_name = value
if condition { ... } else { ... }
| Keyword | Purpose | Example |
|---|---|---|
let |
Variable declaration | let x = 5 |
if/else |
Conditional execution | if x > 0 { ... } else { ... } |
when |
Conditional block | when condition { ... } |
fn |
Function definition | fn name(args) => ... |
return |
Function return | return value |
import |
Module import | import module from "path" |
config |
Configuration block | config { ... } |
devices |
Device configuration | devices { ... } |
modes |
Mode configuration | modes { ... } |
hotkey => action if condition
hotkey if condition => action
when condition {
hotkey1 => action1
hotkey2 => action2
}
when outer_condition {
hotkey if inner_condition => action
}
Example:
F1 when mode gaming => { print("Gaming mode active") }
!C if remapCapslock == false => map("capslock", "esc")
Group multiple hotkeys under a shared condition:
when mode gaming {
^!A => click()
^!B => click("right")
F1 if health < 50 => send("e")
}
All conditions are evaluated dynamically at runtime, allowing variables to change and trigger hotkeys accordingly.
F1 => send("Hello World!")
^V when title "Discord" => {
let clip = clipboard.get
if clip | matches("^\d+") || has("secret") {
let text = ""
let length = len(clip)
for i in 1..length {
text += "*"
}
send("$clip")
} else {
send(clip)
}
}
^!A if window.active.title.contains("Chrome") => send("^F5")
when mode coding {
^!S => send("^s")
^!F => send("^f")
^!G => send("^g")
}
The language includes a built-in help() function for interactive learning:
help()- Show main help pagehelp("syntax")- Show syntax referencehelp("keywords")- Show all keywordshelp("hotkeys")- Show hotkey featureshelp("modules")- Show available modules
# Build release
./build.sh 1 build
# Run havel script file
./build-release/havel script.hv
# Run REPL
./build-release/havwlAlternatively, you can use the Makefile:
makeIf you encounter build issues, please refer to the BUILD_ISSUES.md file for common problems and solutions.
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
/src- Source code/include- Header files/config- Configuration files/log- Log files/build- Build directory/scripts- Scripts examples