mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
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.
155 lines
5.0 KiB
Bash
Executable File
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
|