feat: Adds kanatactl to manage kanata installation, building, systemd service, etc.

This commit is contained in:
2025-10-12 20:43:11 -04:00
parent 5c6409c2e9
commit 0034ac6d87
5 changed files with 284 additions and 23 deletions

View File

@@ -59,7 +59,7 @@
mretu (tap-hold $tap-time $hold-time tab ret) mretu (tap-hold $tap-time $hold-time tab ret)
mlnums (tap-hold-press $tap-time $hold-time lctl (layer-while-held nums_and_symbols)) mlnums (tap-hold-press $tap-time $hold-time esc (layer-while-held nums_and_symbols))
mrnums (tap-hold-press $tap-time $hold-time ret (layer-while-held nums_and_symbols)) mrnums (tap-hold-press $tap-time $hold-time ret (layer-while-held nums_and_symbols))
;; Multi ;; Multi
@@ -80,21 +80,21 @@
) )
;; Blank layer ;; Blank layer
;;(deflayer {{NAME}} ;; (deflayer {{NAME}}
;; esc XX XX XX XX XX XX XX XX XX XX XX XX ;; function row ;; esc XX XX XX XX XX XX XX XX XX XX XX XX ;; function row
;; grv XX XX XX XX XX XX XX XX XX XX XX XX bspc ;; number row ;; grv XX XX XX XX XX XX XX XX XX XX XX XX bspc ;; number row
;; tab XX XX XX XX XX XX XX XX XX XX XX XX XX ;; top letter row ;; tab XX XX XX XX XX XX XX XX XX XX XX XX XX ;; top letter row
;; caps XX XX XX XX XX XX XX XX XX XX XX ret ;; home row ;; caps XX XX XX XX XX XX XX XX XX XX XX ret ;; home row
;; lsft XX XX XX XX XX XX XX XX XX XX XX rsft ;; bottom letter row ;; lsft XX XX XX XX XX XX XX XX XX XX XX rsft ;; bottom letter row
;; lctl lalt lmet spc rmet ralt ◀ ▼ ▶ ;; control row ;; lctl lalt lmet spc rmet ralt ◀ ▼ ▶ ;; control row
;;) ;; )
;; Main layer ;; Main layer
;; ;;
;; Disable most function keys, and add homerow mods. ;; Disable most function keys, and add homerow mods.
;; ;;
(deflayer main (deflayer main
esc brd bru XX XX XX XX XX XX XX mute vold volu esc brdn bru XX XX XX XX XX XX XX mute vold volu
grv 1 2 3 4 5 6 7 8 9 0 - = bspc grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ] \ tab q w e r t y u i o p [ ] \
@mlnums @mlctl @mlalt @mlmet @mlsft g h @mrsft @mrmet @mralt @mrctl ' @mrnums @mlnums @mlctl @mlalt @mlmet @mlsft g h @mrsft @mrmet @mralt @mrctl ' @mrnums
@@ -109,6 +109,5 @@
S-grv S-1 S-9 S-0 S-2 XX XX 1 2 3 \ XX XX XX S-grv S-1 S-9 S-0 S-2 XX XX 1 2 3 \ XX XX XX
XX [ ] S-[ S-] XX XX 4 5 6 . XX ret XX [ ] S-[ S-] XX XX 4 5 6 . XX ret
lsft S-7 S-8 S-4 S-3 XX XX 7 8 9 / XX rsft lsft S-7 S-8 S-4 S-3 XX XX 7 8 9 / XX rsft
lctl lalt lmet spc 0 ralt ◀ ▼ ▶ lctl lalt lmet 0 rmet ralt ◀ ▼ ▶
) )

View File

@@ -78,7 +78,7 @@ logging() {
args=() args=()
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
if [[ $1 == "-w" ]] || [[ $1 =~ ^--warn ]]; then if [[ $1 == "-w" ]] || [[ $1 == "--warn" ]] || [[ $1 == "--warning" ]]; then
log_flag="1" log_flag="1"
warn_flag="1" warn_flag="1"
elif [[ $1 == "-e" ]] || [[ $1 =~ ^--error ]]; then elif [[ $1 == "-e" ]] || [[ $1 =~ ^--error ]]; then
@@ -116,9 +116,10 @@ logging() {
local time=$(date '+%D %H:%M:%S') local time=$(date '+%D %H:%M:%S')
if [[ -z $file ]] || [[ -z $id ]] || [[ -z $label ]]; then if [[ -z $file ]] || [[ -z $id ]] || [[ -z $label ]]; then
echo "Loggging not properly setup." echo "Logging not properly setup."
exit 1 exit 1
fi fi
local prefix="[id: $id][time: $time][source: \e[32m$source_file\e[0m][\e[34m$label\e[0m] :" local prefix="[id: $id][time: $time][source: \e[32m$source_file\e[0m][\e[34m$label\e[0m] :"
local m="$prefix $msg" local m="$prefix $msg"
echo -e "$m" >>"$file" echo -e "$m" >>"$file"
@@ -127,6 +128,8 @@ logging() {
# Also log errors and warning messages to the console. # Also log errors and warning messages to the console.
if [[ $error_flag == "1" ]] || [[ $warn_flag == "1" ]]; then if [[ $error_flag == "1" ]] || [[ $warn_flag == "1" ]]; then
echo -e "[id: $id]$msg" echo -e "[id: $id]$msg"
elif [[ $warn_flag == "1" ]]; then
echo -e "[id: $id]$msg"
fi fi
else else
# Dry run mode, so just log to the console # Dry run mode, so just log to the console

255
env/.local/scripts/kanatactl vendored Executable file
View File

@@ -0,0 +1,255 @@
#!/usr/bin/env bash
set -e
set -o nounset
set -o pipefail
SCRIPTS=${SCRIPTS:-$HOME/.local/scripts}
THIS_FILE=${BASH_SOURCE[0]}
LOG_LABEL=$(basename "$THIS_FILE")
THIS=${THIS:-$LOG_LABEL}
LOG_FILE=${LOG_FILE:-"$LOG_LABEL.log"}
XDG_DATA_HOME=${XDG_DATA_HOME:-"$HOME/.local/share"}
XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-"$HOME/.config"}
DEV_ENV=${DEV_ENV:-""}
usage() {
cat <<EOF
Manages kanata qmk keyboard program, which needs to be built locally. Currently the linux builds
are only for x86. Also can manage as a systemd service.
USAGE:
$ $THIS <command> <flags>
FLAGS:
-h | --help: Show this help page.
COMMANDS:
bootstrap: Bootstrap a new machine, performs installation, enables, and starts kanata systemd service.
disable: Stop and disable the kanata systemd service.
install: Build and install kanata, prompts you to choose the version to install.
logs: View the log file.
restart: Restart the kanata systemd service.
start: Enable and start the kanata systemd service.
status: Get the status of the kanata systemd service.
update: Pull from git and check for updates.
EOF
}
kanata_dir="$XDG_DATA_HOME/kanata"
kanata_url="https://github.com/jtroo/kanata.git"
kanata_current_version=""
# Logging utility function, use in place of echo.
log() {
logging log --source "$THIS_FILE" "$@"
}
# Get the version of currently installed katana execuatable, if available.
get_current_version() {
if [[ $(command -v /usr/bin/kanata) ]]; then
kanata_current_version=$(/usr/bin/kanata --version)
# Remove 'kanata ' from output of the version command.
kanata_current_version="${version#kanata *}"
fi
}
# Get's kanat versions by git tag and filter's out versions that are less than our
# current version number.
get_versions() {
get_current_version
local rows=()
local tag=""
local has_seen_current="0"
for tag in $(git tag --list 'v*' | sort --version-sort); do
if [[ $has_seen_current == "1" ]] || [[ -z $kanata_current_version ]]; then
rows+=("$tag\n")
elif [[ $tag =~ $kanata_current_version ]]; then
has_seen_current="1"
fi
done
echo "$(echo -e "${rows[@]}" | sort --version-sort --reverse | tr -d ' ')"
}
# Present an fzf menu to choose a version to install / update to.
prompt_for_version_to_install() {
local rows=$(get_versions)
if [[ -z $rows ]]; then
log --error "No versions to select." && exit 1
else
echo $(printf '%s\n' "${rows[@]}" | fzf --header='Which version would you like to install?')
fi
}
# Compares the selected version to the installed version.
compare_versions() {
# An example selection at this point: 'v1.9.0'
local selection=""
read -r selection
if [[ $(command -v /usr/bin/kanata) ]] && [[ -n $selection ]]; then
[[ -z $kanata_current_version ]] && get_current_version
local selected_version=${selection#v*} # remove the 'v' from selected version.
log "Comparing selected: '$selected_version' to installed '$kanada_current_version'"
if [[ $selected_version == $kanada_current_version ]]; then
log --warn "Selected version matches the currently installed version." && exit 1
fi
fi
echo "$selection"
}
# Check's out the selected version tag and builds the kanata executable.
build_selection() {
# An example selection at this point: 'v1.9.0'
local selection=""
read -r selection
if [[ -z $selection ]]; then
log --error "Selection is empty." && exit 1
# Handle logged messages instead of an actual selection.
elif [[ $selection =~ "[WARN]" ]] || [[ $selection =~ "[ERROR]" ]]; then
echo $selection && exit 1
fi
if [[ $selection =~ ^v ]]; then
log "Building kanata..."
# checkout the selected version tag and build.
git checkout $selection
cargo build --release --features cmd
echo "done"
fi
}
# Copies the most recently built kanata executable to the '/usr/bin' directory.
#
copy_to_usr_bin() {
# This is the end of the install / update pipe, so it loops over output of
# the other commands in the pipe printing it to the console, while waiting on the
# build to be done.
while read line; do
if [[ $line == "done" ]]; then
log "Copying to '/usr/bin/kanata'" && echo "Copying to '/usr/bin/kanata'"
sudo cp target/release/kanata /usr/bin
echo "Done!"
else
echo "$line"
fi
done
}
# Installs the systemd service files and ensures that kanata configuration has been
# installed.
install_service() {
if [[ -z $DEV_ENV ]]; then
log --error "DEV_ENV is not set properly." && exit 1
fi
# Ensure the configuration is copied, this is generally handled by the 'dev-env' command in
# dotfiles, but just encase it hasn't been ran or removed we need to copy the configuration
# over, otherwise the keyboard may not work.
if [[ ! -d $XDG_CONFIG_HOME/kanata ]] || [[ ! -f $XDG_CONFIG_HOME/kanata/config.kbd ]]; then
log "Copying kanata configuration."
cp -R $DEV_ENV/env/.config/kanata $XDG_CONFIG_HOME/kanata
fi
log "Installing kanata service..."
[[ -f /etc/systemd/system/kanata.service ]] && sudo rm -rf /etc/systemd/system/kanata.service
sudo cp "$DEV_ENV/env/etc/systemd/system/kanata.service" /etc/systemd/system
sudo systemctl daemon-reload
}
# Enables and starts the kanata systemd service.
enable_and_start_service() {
log "Enabling kanata service..."
sudo systemctl enable kanata.service
sudo systemctl start kanata.service
}
# Get the status of the kanata systemd service.
get_status() {
log "Getting kanata service status..."
systemctl status kanata.service
}
# Disable the kanata systemd service.
disable_service() {
log "Disabling kanata service..."
sudo systemctl stop kanata.service
sudo systemctl disable kanata.service
}
# Restart the kanata systemd service.
restart_service() {
log "Restarting kanata service..."
sudo systemctl restart kanata.service
}
# Handles both install or update commands, as they do the same thing, just need to pass in the
# "Updating" argument when updating, so log messages are clear.
install_or_update() {
local mode=${1:-"Installing"}
log "$mode kanata..."
local should_pull="1"
if [[ ! -d $kanata_dir ]]; then
log "Cloning repo."
should_pull="0"
git clone $kanata_url $kanata_dir
fi
pushd $kanata_dir &>/dev/null
(
[[ $should_pull == "1" ]] && git pull origin main >/dev/null 2>&1
prompt_for_version_to_install | compare_versions | build_selection | copy_to_usr_bin
)
popd &>/dev/null
}
# Bootstrap a new machine, by building and installing the kanata executable,
# installing the systemd service files, and enable / start the service.
bootstrap() {
log "Bootstrapping new system..."
install_or_update
install_service
enable_and_start_service
}
################################################################################
# MAIN
################################################################################
# Setup logging file and label.
source "$SCRIPTS/hypr/logging"
setup-logging "$LOG_FILE" "$LOG_LABEL"
while [[ $# -gt 0 ]]; do
if [[ $1 == "-h" ]] || [[ $1 == "--help" ]]; then
usage && exit 0
elif [[ $1 == "bootstrap" ]]; then
bootstrap && exit 0
elif [[ $1 == "disable" ]]; then
disable_service && exit $?
elif [[ $1 == "start" ]]; then
enable_and_start_service && exit 1
elif [[ $1 == "install" ]]; then
install_or_update && exit $?
elif [[ $1 == "logs" ]]; then
bat ${LOG_DIR:-/tmp/logs}/$LOG_FILE && exit 0
elif [[ $1 == "status" ]]; then
get_status && exit $?
elif [[ $1 == "restart" ]]; then
restart_service && exit 0
elif [[ $1 == "update" ]]; then
install_or_update "Updating" && exit 0
fi
done
# If we've made it here, then we didn't handle the command.
usage && exit 1

12
env/etc/systemd/system/kanata.service vendored Normal file
View File

@@ -0,0 +1,12 @@
[Unit]
Description=Kanata Service
Requires=local-fs.target
After=local-fs.target
[Service]
ExecStartPre=/usr/bin/modprobe uinput
ExecStart=/usr/bin/kanata --cfg /home/michael/.config/kanata/config.kbd
Restart=no
[Install]
WantedBy=sysinit.target

View File

@@ -1,13 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
XDG_DATA_HOME=${XDG_DATA_HOME:-"$HOME/.local/share"}
kanata_dir="$XDG_DATA_HOME/kanata"
yay ${1:-"-S --noconfirm"} rustup yay ${1:-"-S --noconfirm"} rustup
git clone https://github.com/jtroo/kanata.git $kanata_dir $DEV_ENV/env/.local/scripts/kanatactl bootstrap
pushd $kanata_dir &>/dev/null
(
cargo install --features cmd --path .
)
popd &>/dev/null