Files
dikte/uninstall.sh
T
yusufipk 698eacf33a Take the install back, and pull the next one in
install.sh has been the only half of its job that was written down. Removing
Dikte meant remembering a symlink, three desktop files, an autostart entry and
a handful of kglobalshortcutsrc keys, and updating meant a pull followed by
guessing which of those the new version had moved. Both are now scripts,
because both are lists somebody would otherwise keep in their head.

uninstall.sh removes what install.sh put down and stops there. What you have
written is yours: the settings and the dictations, the meetings and the
recordings survive a plain run, and --purge is the word that deletes them. It
prints what that would cost first, how many dictations, how many meetings, how
much audio, since a count is the thing that makes the sentence real, and
without a terminal to ask it refuses rather than assuming --yes. Only our own
symlink goes; a file of that name somebody else put there is left alone. The
shortcuts are handed back to `dikte shortcut remove` rather than unpicked from
KDE's file here, because that is the half that knows whether they went into
kglobalshortcutsrc or into GNOME's gsettings.

update.sh asks whether anything is waiting before it complains about anything
else, because an unfinished afternoon in the working tree is nobody's problem
on a day when nothing has been published. If something is waiting and you do
have edits of your own, it stops and says so rather than choosing for you. The
merge is --ff-only: an update is somebody else's commits arriving, never a
merge a script decided to make on your behalf.

Then install.sh runs again, since an update can add a dependency or move a
file, and it is told which keys you chose so that it puts those back instead of
its own defaults. They are read from the settings rather than from the
desktop's file, that being the one place they mean the same thing on KDE and on
GNOME, and a key you had turned off is passed back as the empty string rather
than quietly becoming the default again. Finally the running instance is
restarted, because it is still holding the code from before the pull.
2026-08-01 18:57:50 +03:00

155 lines
5.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Dikte uninstaller: takes back what install.sh put down, and nothing else
# unless asked. Your settings and your dictations survive a plain run; --purge
# is the word that deletes them.
set -euo pipefail
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PY="$(command -v python3 || true)"
USER_NAME="$(id -un)"
BIN_DIR="$HOME/.local/bin"
APP_DIR="$HOME/.local/share/applications"
AUTOSTART_DIR="$HOME/.config/autostart"
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/dikte"
DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/dikte"
PURGE=0
ASSUME_YES=0
say() { printf ' %s\n' "$1"; }
ok() { printf ' \033[32m✓\033[0m %s\n' "$1"; }
warn() { printf ' \033[33m!\033[0m %s\n' "$1"; }
gone() { printf ' \033[90m·\033[0m %s\n' "$1"; }
# "1 dictation", "3 dictations": how many is the point of printing it at all.
count() {
if (( $1 == 1 )); then printf '%s %s' "$1" "$2"; else printf '%s %s' "$1" "$3"; fi
}
usage() {
cat <<EOF
Usage: ./uninstall.sh [--purge] [--yes]
--purge also delete the settings ($CONFIG_DIR)
and the dictations, meetings and recordings ($DATA_DIR)
--yes do not ask before deleting those
Without --purge nothing you have written is touched, and the source directory
is left alone either way.
EOF
}
for arg in "$@"; do
case "$arg" in
--purge) PURGE=1 ;;
--yes|-y) ASSUME_YES=1 ;;
-h|--help) usage; exit 0 ;;
*) printf 'uninstall.sh: unknown option: %s\n' "$arg" >&2; usage >&2; exit 2 ;;
esac
done
# A symlink whose target is gone is still a file to remove, hence -L.
remove() {
if [[ -e "$1" || -L "$1" ]]; then
rm -f "$1"
ok "Removed $1"
else
gone "Was not there: $1"
fi
}
echo
echo "Uninstalling Dikte"
echo "──────────────────"
# 1. Global shortcuts ------------------------------------------------------
# Handed to Dikte while it can still run, because it is the half that knows
# whether they went into KDE's kglobalshortcutsrc or GNOME's gsettings.
if [[ -n "$PY" ]] && python3 -c 'import PyQt6.QtWidgets' 2>/dev/null; then
for which in toggle cancel ask meeting; do
"$PY" "$DIR/dikte.py" shortcut remove "$which" >/dev/null 2>&1 || true
done
ok "Global shortcuts unregistered"
say "KWin reads that file at startup, so the keys are free after your next login."
else
warn "PyQt6 is missing, so the shortcuts were left registered."
say "Remove them in your desktop's shortcut settings."
fi
# 2. The running instance --------------------------------------------------
# It holds a tray icon and a socket; asking it to quit is tidier than pulling
# its launchers out from under it.
if pgrep -u "$USER_NAME" -f 'dikte\.py' >/dev/null 2>&1; then
[[ -n "$PY" ]] && "$PY" "$DIR/dikte.py" quit >/dev/null 2>&1 || true
sleep 0.5
if pgrep -u "$USER_NAME" -f 'dikte\.py' >/dev/null 2>&1; then
warn "Dikte is still running; close it from the tray icon"
else
ok "Stopped the running instance"
fi
fi
# 3. Launchers -------------------------------------------------------------
# Only our own symlink goes: a file of the same name that somebody else put
# there is not ours to delete.
if [[ -L "$BIN_DIR/dikte" ]]; then
remove "$BIN_DIR/dikte"
elif [[ -e "$BIN_DIR/dikte" ]]; then
warn "$BIN_DIR/dikte is not our symlink, leaving it alone"
else
gone "Was not there: $BIN_DIR/dikte"
fi
remove "$APP_DIR/dikte.desktop"
remove "$AUTOSTART_DIR/dikte.desktop"
# Removing the shortcut takes its desktop file with it, but an install from
# before this script existed may have left one behind on a desktop that never
# used them.
for id in dikte-toggle dikte-cancel dikte-ask dikte-meeting; do
if [[ -e "$APP_DIR/$id.desktop" ]]; then
remove "$APP_DIR/$id.desktop"
fi
done
# 4. Settings and dictations -----------------------------------------------
echo
if ((PURGE)); then
warn "--purge also deletes:"
if [[ -f "$CONFIG_DIR/config.json" ]]; then
say "$CONFIG_DIR/config.json (your API keys and every setting)"
fi
if [[ -f "$DATA_DIR/history.jsonl" ]]; then
# grep -c rather than wc -l: a last line with no newline is still a dictation.
say "$DATA_DIR/history.jsonl ($(count "$(grep -c '' "$DATA_DIR/history.jsonl" 2>/dev/null || echo 0)" dictation dictations))"
fi
if [[ -d "$DATA_DIR/meetings" ]]; then
say "$DATA_DIR/meetings ($(count "$(find "$DATA_DIR/meetings" -name '*.md' | wc -l)" meeting meetings))"
fi
if [[ -d "$DATA_DIR/recordings" ]]; then
say "$DATA_DIR/recordings ($(du -sh "$DATA_DIR/recordings" | cut -f1) of audio)"
fi
if ((!ASSUME_YES)); then
if [[ -t 0 ]]; then
printf ' Type yes to delete them: '
read -r reply
[[ "$reply" == "yes" ]] || { PURGE=0; say "Kept."; }
else
PURGE=0
warn "Not a terminal, so nothing was deleted. Pass --yes if you meant it."
fi
fi
fi
if ((PURGE)); then
rm -rf "$CONFIG_DIR" "$DATA_DIR"
ok "Settings and dictations deleted"
else
say "Settings kept: $CONFIG_DIR"
say "Dictations kept: $DATA_DIR"
say "Delete them too with: ./uninstall.sh --purge"
fi
echo
ok "Done."
say "The source directory is untouched: $DIR"
echo