initial commit

This commit is contained in:
Daniel Fichtinger 2025-07-17 22:42:32 -04:00
commit 3d676babd5
3 changed files with 168 additions and 0 deletions

24
LICENSE Normal file
View file

@ -0,0 +1,24 @@
Copyright (c) 2025 Daniel Fichtinger <daniel@ficd.sh>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the author nor the names of its contributors may
be used to endorse or promote products derived from this software
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

37
README.md Normal file
View file

@ -0,0 +1,37 @@
# foot scripts
[foot]: https://codeberg.org/dnkl/foot
[`wtype`]: https://github.com/atx/wtype
This repository contains scripts for [foot].
## `foot-command`
This script implements a command palette for Foot. It allows you to
interactively pick a command defined in your `foot.ini` keybindings, and
simulate its corresponding keypress with [`wtype`]. Here's how it works:
1. Parses keybindings from the `[key-bindings]` section of `foot.ini`.
2. Pipes the list of commands to a picker and waits for a selection.
3. Sends the mapped keypress to to the focused window using `wtype`.
### Dependencies
- [`wtype`].
- A dmenu-compatible picker (e.g. `fuzzel`).
### Usage
```sh
foot-command.py [-c PATH_TO_CONFIG] [-p PICKER_COMMAND]
```
I recommend binding this to a key in your window manager. You need to invoke the
command when Foot is the focused window.
### Options
- `-c`, `--config`: Path to your `foot.ini` file. Defaults to
`$HOME/.config/foot/foot.ini`.
- `-p`, `--picker`: Picker to use (must support `dmenu` style input). Defaults
to `fuzzel --dmenu --placeholder=Select a command:`.

107
foot-command.py Executable file
View file

@ -0,0 +1,107 @@
#!/bin/env python3
# Depends: wtype
import os
import subprocess
from argparse import ArgumentParser
from configparser import ConfigParser
ENV_CONFIG = "FOOT_CONFIG"
ENV_PICKER = "FOOT_PICKER"
DEFAULT_CONFIG = "$HOME/.config/foot.ini"
def parse_config(path: str):
config = ConfigParser(allow_unnamed_section=True)
config.read(path)
section = "key-bindings"
pairs: list[tuple[str, str]] = config.items(section, raw=True)
out: dict[str, str] = {}
for pair in pairs:
command = pair[0]
bindings = pair[1].split(" ")
if bindings[0] == "none":
continue
elif bindings[0][0] == "[":
out[command] = bindings[1]
else:
out[command] = bindings[0]
return out
def get_query_string(mapping: dict[str, str]) -> str:
return "\n".join(mapping.keys())
def spawn_picker(cmd, query_string):
process = subprocess.Popen(
cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
selection = process.communicate(input=query_string.encode("UTF-8"))
if process.returncode != 2:
return selection[0].decode("UTF-8").strip("\n")
else:
return None
MOD_MAP = {
"Control": "ctrl",
"Shift": "shift",
"Mod1": "alt",
}
def get_wtype_args(selection: str, mapping: dict[str, str]):
binding = mapping[selection]
args: list[str] = ["wtype"]
for k in binding.split("+"):
if k in MOD_MAP:
args += ["-M", MOD_MAP[k]]
else:
args += ["-k", k]
return args
def send_keys(args):
process = subprocess.run(args)
process.check_returncode()
def validate_path(path: str) -> str:
if path == DEFAULT_CONFIG:
return str(os.environ["HOME"]) + "/.config/foot/foot.ini"
else:
return path
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument(
"-c",
"--config",
required=False,
help="Absolute path to foot.ini file. (default: %(default)s)",
default=DEFAULT_CONFIG,
type=str,
metavar=ENV_CONFIG,
)
parser.add_argument(
"-p",
"--picker",
required=False,
help="Picker command to be used. (default: %(default)s)",
type=str,
default="fuzzel --dmenu --placeholder=Select a command:",
metavar=ENV_PICKER,
)
args = parser.parse_args()
picker = args.picker
foot_path = validate_path(args.config)
mapping = parse_config(foot_path)
query = get_query_string(mapping)
selection = spawn_picker(picker, query)
if selection is not None:
wtype_args = get_wtype_args(selection, mapping)
print(wtype_args)
send_keys(wtype_args)