aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/bin/ai48
-rwxr-xr-xscripts/bin/cbedit2
-rwxr-xr-xscripts/bin/file-manager2
-rwxr-xr-xscripts/bin/kman3
-rwxr-xr-xscripts/bin/open2
-rwxr-xr-xscripts/bin/tts23
-rwxr-xr-xscripts/orgagenda.sh98
7 files changed, 175 insertions, 3 deletions
diff --git a/scripts/bin/ai b/scripts/bin/ai
new file mode 100755
index 0000000..eb264ea
--- /dev/null
+++ b/scripts/bin/ai
@@ -0,0 +1,48 @@
+#!/usr/bin/env sh
+
+set -e -o pipefail
+
+AI_API_URL=${AI_API_URL:-"http://localhost:9081"}
+AI_API_KEY=${AI_API_KEY:-"no-key"}
+
+system_prompt="
+When responding with code, you are a senior software engineer, output only the raw code, without any enclosing markdown code blocks. Output only the final code. Do not include backticks, comments, or explanations.
+Do not include \`\`\` or any surrounding formatting. If you add anything other than code, you have failed.
+When responding with content, be concise.
+Do not hallucinate facts and respond with accurate information as much as possible.
+If you don't know, just say so. If you are not sure, ask for clarification.
+If the context appears unreadable or of poor quality, tell the user then answer as best as you can.
+"
+
+call_completion() {
+ local opts='"stream": true'
+ local payload="{\"messages\": $1, $opts }"
+ curl --silent --no-buffer \
+ -XPOST "$AI_API_URL/v1/chat/completions" \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer $AI_API_KEY" \
+ --data "$payload" \
+ | tee "$HOME/.local/state/local-ai-last-response" \
+ | stdbuf -oL sed -E 's/^data:\s*//; /^$/d' \
+ | while IFS= read -r line; do
+ printf "%s" "$line" | jq -rj '.choices[0].delta.content // ""' 2>/dev/null || true
+ done;
+}
+
+arg_prompt="$1"
+stdin=""
+if ! [ -t 0 ];
+ then stdin="$(cat)";
+fi
+
+# Start llama server if not started already
+# from: modules/ai/default.nix
+llama-start-server-background
+
+# Call completion api
+call_completion "$(jq -n \
+ --arg system "$system_prompt" \
+ --arg user "$arg_prompt" \
+ --arg user_supplement "$stdin" \
+ '[{ role: "system", content: $system }, { role: "user", content: $user }, { role: "user", content: $user_supplement }]')"
+
diff --git a/scripts/bin/cbedit b/scripts/bin/cbedit
index f4d88fd..b163ecb 100755
--- a/scripts/bin/cbedit
+++ b/scripts/bin/cbedit
@@ -4,7 +4,7 @@ set -e;
read_clipboard() { xclip -selection clipboard -o || echo -n ""; }
update_clipboard() { xclip -selection clipboard -i; }
-edit_file() { st -e nvim "$@"; }
+edit_file() { st -e sensible-editor "$@"; }
tmp_file=$(mktemp /tmp/cbedit-XXXXX);
read_clipboard > $tmp_file;
diff --git a/scripts/bin/file-manager b/scripts/bin/file-manager
index 467d346..016818e 100755
--- a/scripts/bin/file-manager
+++ b/scripts/bin/file-manager
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
-sensible-terminal -d "$1" -e lf
+sensible-terminal -d "$1" -e daffm
diff --git a/scripts/bin/kman b/scripts/bin/kman
new file mode 100755
index 0000000..052d410
--- /dev/null
+++ b/scripts/bin/kman
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+kak -e "man $@; map global normal q :quit<ret>;"
diff --git a/scripts/bin/open b/scripts/bin/open
index 9daa34a..001d784 100755
--- a/scripts/bin/open
+++ b/scripts/bin/open
@@ -13,7 +13,7 @@ open_by_mimetype() {
echo "Opening $file ($mime)...";
case "$mime" in
- inode/directory) lf "$file" ;;
+ inode/directory) daffm "$file" ;;
application/x-bittorrent) ~/scripts/torrent.sh torrent "$file" ;;
diff --git a/scripts/bin/tts b/scripts/bin/tts
new file mode 100755
index 0000000..ecb4ee2
--- /dev/null
+++ b/scripts/bin/tts
@@ -0,0 +1,23 @@
+#!/usr/bin/env sh
+
+set -e -o pipefail
+
+TTS_MODELS_PATH="$HOME/.config/piper-models"
+
+playaudio() {
+ ffplay -nodisp -autoexit -f s16le -ar 22050 -
+}
+
+text2speech() {
+ # https://huggingface.co/rhasspy/piper-voices/tree/main/en/en_US
+ local tts_model="en_US-lessac-medium.onnx";
+ # local tts_model="en_US-ryan-high.onnx";
+ # local tts_model="en_US-bryce-medium.onnx";
+ local tts_model_path="$TTS_MODELS_PATH/$tts_model";
+ [ -f "$tts_model_path" ] || (echo "Model not found" && exit 1);
+
+ piper --model "$tts_model_path" --sentence_silence 0.4 --output-raw | playaudio
+}
+
+text2speech;
+
diff --git a/scripts/orgagenda.sh b/scripts/orgagenda.sh
new file mode 100755
index 0000000..9f46778
--- /dev/null
+++ b/scripts/orgagenda.sh
@@ -0,0 +1,98 @@
+#!/usr/bin/env sh
+
+set -eu -o pipefail
+
+CONFIG_ORG_DIRECTORY=${CONFIG_ORG_DIRECTORY:-"$HOME/nixos/extras/notes"}
+
+datefmt='%Y-%m-%d'
+datetimefmt='%Y-%m-%d %H:%M:%S'
+
+weekdaynum() { echo "$(($(date -d "$1" +%u) % 7))"; }
+
+today=$(date "+$datefmt")
+weekincrement="${1:-0}"
+target=$(date -d "$weekincrement weeks" "+$datefmt")
+weekstart=$(date -d "$target -$(weekdaynum "$target") days" "+$datefmt")
+nextweekstart=$(date -d "$target -$(weekdaynum "$target") days +1 week" "+$datefmt")
+
+fetch_schedule() {
+ # TODO: Exclude DONE tasks
+ rg -i -g '**/*.org' --vimgrep --multiline \
+ '^\*+\s+(?<heading>.+)\n(^[^*]*\n)*^((?<type>SCHEDULED|DEADLINE)\s*:)?\s*<(?<date>[^>]*)>(--<(?<enddate>[^>]*)>)?' \
+ --replace '§$heading§$type§$date§$enddate' \
+ "$CONFIG_ORG_DIRECTORY" \
+ | sed -E 's/:[0-9]+:[0-9]+://'
+}
+
+# :: Date -> Date
+parse_start_date() {
+ echo "$1" | sed -E 's/^([0-9]+-[0-9]+-[0-9]+)\s*.*/\1/'
+}
+
+# :: ScheduleType -> Date -> End Date -> [Date]
+parse_date_range() {
+ [ -z "$2" ] && return 0
+ parsed_date=$(parse_start_date "$2")
+ if [ "$1" = "DEADLINE" ]; then
+ for i in $(seq 1 2); do
+ local d=$(date -d "$parsed_date -$i days" "+$datefmt" || true)
+ if [ "$d" \> "$today" ] || [ "$d" = "$today" ]; then echo "$d"; fi
+ done
+ date -d "$parsed_date" "+$datefmt" || true
+ else
+ # TODO: Parse end date
+ # TODO: Parse repeat syntax +x as well
+ date -d "$parsed_date" "+$datefmt" || true
+ fi
+}
+
+date_between() {
+ ([ "$1" \> "$2" ] || [ "$1" = "$2" ]) && [ "$1" \< "$3" ]
+}
+
+weeks_events() {
+ fetch_schedule | while IFS=§ read file heading scheduletype original_date end_date; do
+ parse_date_range "$scheduletype" "$original_date" "$end_date" | while IFS= read applied_date; do
+ day_of_week=$(date -d "$applied_date" +%A 2>/dev/null || true)
+ if ! [ -z "$applied_date" ] && (date_between "$applied_date" "$weekstart" "$nextweekstart"); then
+ parsed_date="$(parse_start_date "$original_date")"
+ echo -e "$day_of_week§$heading§$scheduletype§$original_date§$parsed_date§$applied_date"
+ fi
+ done
+ done
+}
+
+date_from_day() {
+ date -d "$weekstart +$(weekdaynum "$1") days" +"$datefmt";
+}
+
+relative_date_diff() {
+ start_sec=$(date -d "$1" +%s)
+ end_sec=$(date -d "$2" +%s)
+ diff=$((end_sec - start_sec))
+ days=$((diff / 86400))
+ if [ $diff = 0 ]; then echo "today"
+ elif [ $diff -gt 0 ]; then echo "in $days days"
+ else echo "$((days * -1)) days ago"
+ fi
+}
+
+events=$(weeks_events)
+cols=$(tput cols)
+
+days_of_week="Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
+
+for day_of_week in ${days_of_week}; do
+ echo -e "\033[38;5;73m${day_of_week} \033[1m($(date_from_day "$day_of_week"))\033[0m"
+ (echo "$events" | grep "^$day_of_week" || true) | \
+ while IFS=§ read _ heading scheduletype original_date real_date date; do
+ eventstyle=""
+ if [ "$scheduletype" = "DEADLINE" ]; then
+ eventstyle=$([ "$date" = "$real_date" ] \
+ && echo "\033[38;5;160m" \
+ || echo "\033[38;5;172m")
+ fi
+ printf "\033[38;5;243m%${cols}s\033[0m" "($original_date) "
+ echo -e "\r ${eventstyle}\033[1m${heading}\033[0m ($(relative_date_diff "$today" "$real_date"))"
+ done
+done