From b8e909d68bcb035648dda93f15de7863f444a3c4 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sat, 22 Nov 2025 00:43:12 +0530 Subject: Switch to kakoune + daffm --- scripts/bin/ai | 48 ++++++++++++++++++++++++ scripts/bin/cbedit | 2 +- scripts/bin/file-manager | 2 +- scripts/bin/kman | 3 ++ scripts/bin/open | 2 +- scripts/bin/tts | 23 ++++++++++++ scripts/orgagenda.sh | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 3 deletions(-) create mode 100755 scripts/bin/ai create mode 100755 scripts/bin/kman create mode 100755 scripts/bin/tts create mode 100755 scripts/orgagenda.sh (limited to 'scripts') 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;" 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+(?.+)\n(^[^*]*\n)*^((?SCHEDULED|DEADLINE)\s*:)?\s*<(?[^>]*)>(--<(?[^>]*)>)?' \ + --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 -- cgit v1.3.1