A wayland native krunner-like runner, made with customizability in mind.
Note
Anyrun is currently in maintenance mode due to the original maintainer taking an extended break. For the time being @notashelf will be reviewing and merging critical bug-fixes or must-have features in the form of pull requests. This is hopefully not a permanent status.
- Style customizability with GTK+ CSS
- More info in Styling
- Can do basically anything
- As long as it can work with input and selection
- Hence the name anyrun
- Easy to make plugins
- You only need 4 functions!
- See Rink for a simple example. More info in the documentation of the anyrun-plugin crate.
- Responsive
- Asynchronous running of plugin functions
- Wayland native
- GTK layer shell for overlaying the window
- data-control for managing the clipboard
Anyrun mainly depends various GTK libraries, and rust of course for building the project. Rust you can get with rustup. The rest are statically linked in the binary. Here are the libraries you need to have to build & run it:
gtk-layer-shell (libgtk-layer-shell)
gtk3 (libgtk-3 libgdk-3)
pango (libpango-1.0)
cairo (libcairo libcairo-gobject)
gdk-pixbuf2 (libgdk_pixbuf-2.0)
glib2 (libgobject-2.0 libgio-2.0 libglib-2.0)
You can use the provided flake:
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
anyrun = {
url = "github:anyrun-org/anyrun";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, anyrun }: {
nixosConfigurations."<your_hostname>" = nixpkgs.lib.nixosSystem {
# ...
modules = [
# Add Anyrun to environment.systemPackages to make it available to
# all system users. You may prefer `users.users.<your_username>.packages`
# to install it for a specified user only.
{environment.systemPackages = [ anyrun.packages.${system}.anyrun ];}
];
# ...
};
};
}
The flake provides multiple packages:
- anyrun (default) - the Anyrun binary, without plugins
- anyrun-with-all-plugins - Anyrun and all builtin plugins
- applications - the applications plugin
- dictionary - the dictionary plugin
- kidex - the kidex plugin
- randr - the randr plugin
- rink - the rink plugin
- shell - the shell plugin
- stdin - the stdin plugin
- symbols - the symbols plugin
- translate - the translate plugin
- websearch - the websearch plugin
The Anyrun flake exposes a Home-Manager module as homeManagerModules.default
which you can use to install and configure Anyrun in your system with ease.
You may use it in your system like this:
{
programs.anyrun = {
enable = true;
config = {
x = { fraction = 0.5; };
y = { fraction = 0.3; };
width = { fraction = 0.3; };
hideIcons = false;
ignoreExclusiveZones = false;
layer = "overlay";
hidePluginInfo = false;
closeOnClick = false;
showResultsImmediately = false;
maxEntries = null;
plugins = [
# An array of all the plugins you want, which either can be paths to the .so files, or their packages
inputs.anyrun.packages.${pkgs.system}.applications
./some_plugin.so
"${inputs.anyrun.packages.${pkgs.system}.anyrun-with-all-plugins}/lib/kidex"
];
};
# Inline comments are supported for language injection into
# multi-line strings with Treesitter! (Depends on your editor)
extraCss = /*css */ ''
.some_class {
background: red;
}
'';
extraConfigFiles."some-plugin.ron".text = ''
Config(
// for any other plugin
// this file will be put in ~/.config/anyrun/some-plugin.ron
// refer to docs of xdg.configFile for available options
)
'';
};
}
Anyrun packages are built and cached automatically. To avoid unnecessary recompilations, you may use the binary cache.
nix.settings = {
builders-use-substitutes = true;
extra-substituters = [
"https://anyrun.cachix.org"
];
extra-trusted-public-keys = [
"anyrun.cachix.org-1:pqBobmOjI7nKlsUMV25u9QHa9btJK65/C8vnO3p346s="
];
};
Warning
While using the Anyrun flake, overriding the nixpkgs
input for Anyrun will
cause cache hits, i.e., you will have to build from source every time. To use
the cache, do not override the Nixpkgs input.
Make sure all of the dependencies are installed, and then run the following commands in order:
# Clone the repository and move to the cloned location
git clone https://github.com/Kirottu/anyrun.git && cd anyrun
# Build all packages, and install the Anyrun binary
cargo build --release
cargo install --path anyrun/
# Create the config directory and the plugins subdirectory
mkdir -p ~/.config/anyrun/plugins
# Copy all of the built plugins to the correct directory
cp target/release/*.so ~/.config/anyrun/plugins
# Copy the default config file
cp examples/config.ron ~/.config/anyrun/config.ron
Anyrun requires plugins to function, as they provide the results for input. The list of plugins in this repository is as follows:
- Applications
- Search and run system & user specific desktop entries.
- Symbols
- Search unicode symbols.
- Rink
- Calculator & unit conversion.
- Shell
- Run shell commands.
- Translate
- Quickly translate text.
- Kidex
- File search provided by Kidex.
- Randr
- Rotate and resize; quickly change monitor configurations on the fly.
- TODO: Only supports Hyprland, needs support for other compositors.
- Stdin
- Turn Anyrun into a dmenu-like fuzzy selector.
- Should generally be used exclusively with the
--plugins
argument.
- Dictionary
- Look up definitions for words
- Websearch
- Search the web with configurable engines: Google, Ecosia, Bing, DuckDuckGo.
The default configuration directory is $HOME/.config/anyrun
the structure of
the config directory is as follows and should be respected by plugins:
- anyrun/
- plugins/
- <plugin dynamic libraries>
- config.ron
- style.css
- <any plugin specific config files>
The default config file contains the default values, and annotates all configuration options with comments on what they are and how to use them.
Anyrun supports GTK+ CSS styling. The names for the different widgets and widgets associated with them are as follows:
entry
: The entry boxGtkEntry
window
: The windowGtkWindow
main
: "Main" parts of the layoutGtkListBox
: The main list containing the pluginsGtkBox
: The box combining the main list and the entry box
plugin
: Anything for the entire pluginGtkLabel
: The name of the pluginGtkBox
: The different boxes in the plugin viewGtkImage
: The icon of the plugin
match
: Widgets of a specific matchGtkBox
: The main box of the match and the box containing the title and the description if presentGtkImage
: The icon of the match (if present)
match-title
: Specific for the title of the matchGtkLabel
match-desc
: Specific for the description of the matchGtkLabel
The custom arguments for anyrun are as follows:
--config-dir
,-c
: Override the configuration directory
The rest of the arguments are automatically generated based on the config, and
can be used to override configuration parameters. For example if you want to
temporarily only run the Applications and Symbols plugins on the top side of the
screen, you would run
anyrun --plugins libapplications.so --plugins libsymbols.so --position top
.
The plugin API is intentionally very simple to use. This is all you need for a plugin:
Cargo.toml
:
#[package] omitted
[lib]
crate-type = ["cdylib"] # Required to build a dynamic library that can be loaded by anyrun
[dependencies]
anyrun-plugin = { git = "https://github.com/Kirottu/anyrun" }
abi_stable = "0.11.1"
# Any other dependencies you may have
lib.rs
:
use abi_stable::std_types::{RString, RVec, ROption};
use anyrun_plugin::*;
#[init]
fn init(config_dir: RString) {
// Your initialization code. This is run in another thread.
// The return type is the data you want to share between functions
}
#[info]
fn info() -> PluginInfo {
PluginInfo {
name: "Demo".into(),
icon: "help-about".into(), // Icon from the icon theme
}
}
#[get_matches]
fn get_matches(input: RString) -> RVec<Match> {
// The logic to get matches from the input text in the `input` argument.
// The `data` is a mutable reference to the shared data type later specified.
vec![Match {
title: "Test match".into(),
icon: ROption::RSome("help-about".into()),
use_pango: false,
description: ROption::RSome("Test match for the plugin API demo".into()),
id: ROption::RNone, // The ID can be used for identifying the match later, is not required
}].into()
}
#[handler]
fn handler(selection: Match) -> HandleResult {
// Handle the selected match and return how anyrun should proceed
HandleResult::Close
}
And that's it! That's all of the API needed to make runners. Refer to the plugins in the plugins folder for more examples.