mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-02-27 12:22:43 -08:00
Merge branch 'master' of github.com:ksyasuda/dotfiles
This commit is contained in:
@@ -127,4 +127,5 @@ alias hypr='cd ~/.config/hypr && vim ~/.config/hypr/hyprland.conf && cd -'
|
||||
alias wlc='wl-copy'
|
||||
alias wlp='wl-paste'
|
||||
alias vn32='WINEPREFIX=/home/sudacode/S/lutris/wineprefix32 WINEARCH=win32'
|
||||
alias impv='mpv --profile=immersion'
|
||||
alias impv='mpv --profile=subminer'
|
||||
alias smpv='mpv --profile=subminer'
|
||||
|
||||
@@ -39,19 +39,23 @@
|
||||
"pyright-lsp@claude-plugins-official": true,
|
||||
"typescript-lsp@claude-plugins-official": true,
|
||||
"clangd-lsp@claude-plugins-official": true,
|
||||
"claude-mem@thedotmack": true,
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"code-review@claude-plugins-official": true,
|
||||
"code-simplifier@claude-plugins-official": true,
|
||||
"playwright@claude-plugins-official": true
|
||||
"playwright@claude-plugins-official": true,
|
||||
"superpowers@claude-plugins-official": true
|
||||
},
|
||||
"sandbox": {
|
||||
"enabled": false,
|
||||
"autoAllowBashIfSandboxed": true,
|
||||
"network": {
|
||||
"allowUnixSockets": ["/var/run/docker.sock"],
|
||||
"allowUnixSockets": [
|
||||
"/var/run/docker.sock"
|
||||
],
|
||||
"allowLocalBinding": true
|
||||
},
|
||||
"excludedCommands": ["docker"]
|
||||
"excludedCommands": [
|
||||
"docker"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
131
.config/SubMiner/config.jsonc##os.Darwin
Executable file
131
.config/SubMiner/config.jsonc##os.Darwin
Executable file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"keybindings": [],
|
||||
"shortcuts": {
|
||||
"copySubtitle": "CommandOrControl+C",
|
||||
"copySubtitleMultiple": "CommandOrControl+Shift+C",
|
||||
"updateLastCardFromClipboard": "CommandOrControl+V",
|
||||
"triggerFieldGrouping": "CommandOrControl+G",
|
||||
"triggerSubsync": "CommandOrControl+Alt+S",
|
||||
"mineSentence": "CommandOrControl+S",
|
||||
"mineSentenceMultiple": "CommandOrControl+Shift+S",
|
||||
"multiCopyTimeoutMs": 3000,
|
||||
"toggleSecondarySub": "CommandOrControl+Shift+V",
|
||||
"markAudioCard": "CommandOrControl+Shift+A",
|
||||
"openRuntimeOptions": "CommandOrControl+Shift+O",
|
||||
"toggleVisibleOverlayGlobal": "Alt+Shift+O",
|
||||
"toggleInvisibleOverlayGlobal": "Alt+Shift+I",
|
||||
},
|
||||
"auto_start_overlay": false,
|
||||
"bind_visible_overlay_to_mpv_sub_visibility": false,
|
||||
"texthooker": {
|
||||
"openBrowser": false,
|
||||
},
|
||||
"websocket": {
|
||||
"enabled": "auto",
|
||||
"port": 6677,
|
||||
},
|
||||
"ankiConnect": {
|
||||
"enabled": true,
|
||||
"url": "http://127.0.0.1:8765",
|
||||
"deck": "Minecraft",
|
||||
"pollingRate": 500,
|
||||
"fields": {
|
||||
"audio": "ExpressionAudio",
|
||||
"image": "Picture",
|
||||
"sentence": "Sentence",
|
||||
"miscInfo": "MiscInfo",
|
||||
"translation": "SelectionText",
|
||||
},
|
||||
"openRouter": {
|
||||
"enabled": true,
|
||||
"alwaysUseAiTranslation": true,
|
||||
"apiKey": "",
|
||||
"model": "openai/gpt-oss-120b:free",
|
||||
"baseUrl": "https://openrouter.ai/api/v1",
|
||||
"sourceLanguage": "Japanese",
|
||||
"systemPrompt": "You are a translation engine for translating Japanese into natural-sounding, context-aware English. Return only the translated text with no extra explanations or commentary. The translation must preserve the original tone and intent of the source. If the input is not in the target language, translate it to the target language. If the input is already in the target language, return it as is.",
|
||||
},
|
||||
"media": {
|
||||
"generateAudio": true,
|
||||
"generateImage": true,
|
||||
"imageType": "avif",
|
||||
"imageFormat": "webp",
|
||||
"animatedFps": 24,
|
||||
"animatedMaxWidth": 640,
|
||||
"animatedMaxHeight": null,
|
||||
"animatedCrf": 35,
|
||||
"audioPadding": 0.5,
|
||||
"fallbackDuration": 3,
|
||||
},
|
||||
"behavior": {
|
||||
"overwriteAudio": false,
|
||||
"overwriteImage": true,
|
||||
"mediaInsertMode": "append",
|
||||
"highlightWord": true,
|
||||
"notificationType": "system",
|
||||
"showNotificationOnUpdate": true,
|
||||
"autoUpdateNewCards": false,
|
||||
},
|
||||
"nPlusOne": {
|
||||
"decks": ["Minecraft", "Kaishi 1.5k"],
|
||||
"highlightEnabled": true,
|
||||
"refreshMinutes": 60,
|
||||
"matchMode": "headword",
|
||||
},
|
||||
"metadata": {
|
||||
"pattern": "[SubMiner] %f (%t)",
|
||||
},
|
||||
"isLapis": {
|
||||
"enabled": true,
|
||||
"sentenceCardModel": "Lapis Morph",
|
||||
"sentenceCardSentenceField": "Sentence",
|
||||
"sentenceCardAudioField": "SentenceAudio",
|
||||
},
|
||||
"isKiku": {
|
||||
"enabled": true,
|
||||
"fieldGrouping": "manual",
|
||||
"deleteDuplicateInAuto": true,
|
||||
},
|
||||
},
|
||||
"secondarySub": {
|
||||
"autoLoadSecondarySub": true,
|
||||
"secondarySubLanguages": ["en", "eng"],
|
||||
},
|
||||
"subsync": {
|
||||
"defaultMode": "manual",
|
||||
"alass_path": "~/.local/bin/alass-cli",
|
||||
"ffsubsync_path": "~/.local/bin/ffsubsync",
|
||||
"ffmpeg_path": "/opt/homebrew/ffmpeg/bin/ffmpeg",
|
||||
},
|
||||
"subtitleStyle": {
|
||||
"fontFamily": "Noto Sans CJK JP Regular, Noto Sans CJK JP, Arial Unicode MS, Arial, sans-serif",
|
||||
"fontSize": 35,
|
||||
"fontColor": "#cad3f5",
|
||||
"fontWeight": "normal",
|
||||
"fontStyle": "normal",
|
||||
"backgroundColor": "rgb(30, 32, 48, 0.88)",
|
||||
"secondary": {
|
||||
"fontSize": 24,
|
||||
"fontColor": "#cad3f5",
|
||||
"backgroundColor": "transparent",
|
||||
},
|
||||
},
|
||||
"jimaku": {
|
||||
// "apiKey": "YOUR_API_KEY",
|
||||
// or use a command that outputs the key:
|
||||
"apiKeyCommand": "cat ~/.jimaku-api-key",
|
||||
"apiBaseUrl": "https://jimaku.cc",
|
||||
"languagePreference": "ja",
|
||||
"maxEntryResults": 10,
|
||||
},
|
||||
"invisibleOverlay": {
|
||||
// "platform-default" => hidden on Wayland, visible elsewhere
|
||||
// other values: "visible", "hidden"
|
||||
"startupVisibility": "platform-default",
|
||||
},
|
||||
"youtubeSubgen": {
|
||||
"mode": "automatic", // automatic | preprocess | off
|
||||
"whisperBin": "/usr/bin/whisper-cli",
|
||||
"whisperModel": "~/models/whisper.cpp/ggml-small.bin",
|
||||
},
|
||||
}
|
||||
131
.config/SubMiner/config.jsonc##os.Linux
Normal file
131
.config/SubMiner/config.jsonc##os.Linux
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"keybindings": [],
|
||||
"shortcuts": {
|
||||
"copySubtitle": "CommandOrControl+C",
|
||||
"copySubtitleMultiple": "CommandOrControl+Shift+C",
|
||||
"updateLastCardFromClipboard": "CommandOrControl+V",
|
||||
"triggerFieldGrouping": "CommandOrControl+G",
|
||||
"triggerSubsync": "CommandOrControl+Alt+S",
|
||||
"mineSentence": "CommandOrControl+S",
|
||||
"mineSentenceMultiple": "CommandOrControl+Shift+S",
|
||||
"multiCopyTimeoutMs": 3000,
|
||||
"toggleSecondarySub": "CommandOrControl+Shift+V",
|
||||
"markAudioCard": "CommandOrControl+Shift+A",
|
||||
"openRuntimeOptions": "CommandOrControl+Shift+O",
|
||||
"toggleVisibleOverlayGlobal": "Alt+Shift+O",
|
||||
"toggleInvisibleOverlayGlobal": "Alt+Shift+I",
|
||||
},
|
||||
"auto_start_overlay": false,
|
||||
"bind_visible_overlay_to_mpv_sub_visibility": false,
|
||||
"texthooker": {
|
||||
"openBrowser": false,
|
||||
},
|
||||
"websocket": {
|
||||
"enabled": "auto",
|
||||
"port": 6677,
|
||||
},
|
||||
"ankiConnect": {
|
||||
"enabled": true,
|
||||
"url": "http://127.0.0.1:8765",
|
||||
"deck": "Minecraft",
|
||||
"pollingRate": 500,
|
||||
"fields": {
|
||||
"audio": "ExpressionAudio",
|
||||
"image": "Picture",
|
||||
"sentence": "Sentence",
|
||||
"miscInfo": "MiscInfo",
|
||||
"translation": "SelectionText",
|
||||
},
|
||||
"openRouter": {
|
||||
"enabled": true,
|
||||
"alwaysUseAiTranslation": true,
|
||||
"apiKey": "",
|
||||
"model": "openai/gpt-oss-120b:free",
|
||||
"baseUrl": "https://openrouter.ai/api/v1",
|
||||
"sourceLanguage": "Japanese",
|
||||
"systemPrompt": "You are a translation engine for translating Japanese into natural-sounding, context-aware English. Return only the translated text with no extra explanations or commentary. The translation must preserve the original tone and intent of the source. If the input is not in the target language, translate it to the target language. If the input is already in the target language, return it as is.",
|
||||
},
|
||||
"media": {
|
||||
"generateAudio": true,
|
||||
"generateImage": true,
|
||||
"imageType": "avif",
|
||||
"imageFormat": "webp",
|
||||
"animatedFps": 24,
|
||||
"animatedMaxWidth": 640,
|
||||
"animatedMaxHeight": null,
|
||||
"animatedCrf": 35,
|
||||
"audioPadding": 0.5,
|
||||
"fallbackDuration": 3,
|
||||
},
|
||||
"behavior": {
|
||||
"overwriteAudio": false,
|
||||
"overwriteImage": true,
|
||||
"mediaInsertMode": "append",
|
||||
"highlightWord": true,
|
||||
"notificationType": "system",
|
||||
"showNotificationOnUpdate": true,
|
||||
"autoUpdateNewCards": false,
|
||||
},
|
||||
"nPlusOne": {
|
||||
"decks": ["Minecraft", "Kaishi 1.5k"],
|
||||
"highlightEnabled": true,
|
||||
"refreshMinutes": 60,
|
||||
"matchMode": "headword",
|
||||
},
|
||||
"metadata": {
|
||||
"pattern": "[SubMiner] %f (%t)",
|
||||
},
|
||||
"isLapis": {
|
||||
"enabled": true,
|
||||
"sentenceCardModel": "Lapis Morph",
|
||||
"sentenceCardSentenceField": "Sentence",
|
||||
"sentenceCardAudioField": "SentenceAudio",
|
||||
},
|
||||
"isKiku": {
|
||||
"enabled": true,
|
||||
"fieldGrouping": "manual",
|
||||
"deleteDuplicateInAuto": true,
|
||||
},
|
||||
},
|
||||
"secondarySub": {
|
||||
"autoLoadSecondarySub": true,
|
||||
"secondarySubLanguages": ["en", "eng"],
|
||||
},
|
||||
"subsync": {
|
||||
"defaultMode": "manual",
|
||||
"alass_path": null,
|
||||
"ffsubsync_path": null,
|
||||
"ffmpeg_path": null,
|
||||
},
|
||||
"subtitleStyle": {
|
||||
"fontFamily": "Noto Sans CJK JP Regular, Noto Sans CJK JP, Arial Unicode MS, Arial, sans-serif",
|
||||
"fontSize": 35,
|
||||
"fontColor": "#cad3f5",
|
||||
"fontWeight": "normal",
|
||||
"fontStyle": "normal",
|
||||
"backgroundColor": "rgb(30, 32, 48, 0.88)",
|
||||
"secondary": {
|
||||
"fontSize": 24,
|
||||
"fontColor": "#cad3f5",
|
||||
"backgroundColor": "transparent",
|
||||
},
|
||||
},
|
||||
"jimaku": {
|
||||
// "apiKey": "YOUR_API_KEY",
|
||||
// or use a command that outputs the key:
|
||||
"apiKeyCommand": "cat ~/.jimaku-api-key",
|
||||
"apiBaseUrl": "https://jimaku.cc",
|
||||
"languagePreference": "ja",
|
||||
"maxEntryResults": 10,
|
||||
},
|
||||
"invisibleOverlay": {
|
||||
// "platform-default" => hidden on Wayland, visible elsewhere
|
||||
// other values: "visible", "hidden"
|
||||
"startupVisibility": "platform-default",
|
||||
},
|
||||
"youtubeSubgen": {
|
||||
"mode": "automatic", // automatic | preprocess | off
|
||||
"whisperBin": "/usr/bin/whisper-cli",
|
||||
"whisperModel": "~/models/whisper.cpp/ggml-small.bin",
|
||||
},
|
||||
}
|
||||
@@ -78,6 +78,7 @@ exec-once = uwsm app -sb -t service -- nm-applet
|
||||
exec-once = uwsm app -sb -t service -- waybar -c ~/.config/waybar/catppuccin-macchiato/config.jsonc -s ~/.config/waybar/catppuccin-macchiato/style.css
|
||||
exec-once = uwsm app -sb -t service -- hyprsunset
|
||||
exec-once = uwsm app -sb -t service -- /usr/lib/polkit-kde-authentication-agent-1
|
||||
exec-once = uwsm app -sb -t service -- gnome-keyring-daemon --start --components=secrets,ssh,pkcs11
|
||||
# exec-once = uwsm app -sb -t service -- variety
|
||||
exec-once = ~/.local/bin/aria
|
||||
# exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
|
||||
|
||||
@@ -95,7 +95,7 @@ bind = $mainMod SHIFT, v, exec, uwsm app -sb -- rofi-rbw
|
||||
# bind = $mainMod, w, exec, rofi -show window -theme $HOME/.config/rofi/launchers/type-2/style-2.rasi -dpi 96 -theme-str 'window {width: 35%;}'
|
||||
bind = $mainMod SHIFT, w, exec, "$HOME/.config/rofi/scripts/rofi-wallpaper.sh"
|
||||
bind = $mainMod SHIFT, d, exec, "$HOME/.config/rofi/scripts/rofi-docs.sh"
|
||||
bind = SUPER, j, exec, "$HOME/.config/rofi/scripts/rofi-jellyfin-dir.sh"
|
||||
bind = SUPER SHIFT, j, exec, "$HOME/.config/rofi/scripts/rofi-jellyfin-dir.sh"
|
||||
bind = SUPER, t, exec, "$HOME/.config/rofi/scripts/rofi-launch-texthooker-steam.sh"
|
||||
bind = $mainMod SHIFT, t, exec, "$HOME/projects/scripts/popup-ai-translator.py"
|
||||
bind = SUPER SHIFT, g, exec, "$HOME/.config/rofi/scripts/rofi-vn-helper.sh"
|
||||
@@ -133,7 +133,7 @@ bind = $mainMod, z, exec, uwsm app -sb -- zen-browser
|
||||
bind = $mainMod SHIFT, s, exec , rofi -show ssh -theme "$HOME/.config/rofi/launchers/type-2/style-2.rasi" -terminal -theme-str 'window{width: 25%;} listview {columns: 1; lines: 10;}' ghostty -ssh-command "ghostty --initial-command='TERM=kitty ssh {host}'"
|
||||
|
||||
# reload monitors
|
||||
bind = $mainMod SHIFT, R, exec, hyprctl dispatch dpms off && sleep 1 && hyprctl dispatch dpms on
|
||||
bind = CTRL $mainMod SHIFT, R, exec, hyprctl dispatch dpms off && sleep 1 && hyprctl dispatch dpms on
|
||||
|
||||
# Disable keybinds with one master keybind
|
||||
# https://wiki.hypr.land/0.49.0/Configuring/Uncommon-tips--tricks/#disabling-keybinds-with-one-master-keybind
|
||||
|
||||
1
.config/mpv-modules/ani-skip
Submodule
1
.config/mpv-modules/ani-skip
Submodule
Submodule .config/mpv-modules/ani-skip added at 12b4960ecd
@@ -85,6 +85,8 @@ bind j select-pane -D
|
||||
bind k select-pane -U
|
||||
bind l select-pane -R
|
||||
|
||||
bind r source-file ~/.tmux.conf \; display "Reloaded tmux config"
|
||||
|
||||
set-window-option -g mode-keys vi
|
||||
set -g mode-keys vi
|
||||
set -g status-keys vi
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -25,3 +25,6 @@
|
||||
[submodule ".config/mpv-modules/animecards"]
|
||||
path = .config/mpv-modules/animecards
|
||||
url = git@github.com:ksyasuda/Anacreon-Script
|
||||
[submodule ".config/mpv-modules/ani-skip"]
|
||||
path = .config/mpv-modules/ani-skip
|
||||
url = https://github.com/synacktraa/ani-skip.git
|
||||
|
||||
@@ -102,3 +102,11 @@ zle -N bracketed-paste bracketed-paste-magic
|
||||
alias claude-mem='bun "/home/sudacode/.claude/plugins/marketplaces/thedotmack/plugin/scripts/worker-service.cjs"'
|
||||
fpath=(/home/sudacode/.zsh/completions $fpath)
|
||||
autoload -Uz compinit && compinit
|
||||
|
||||
# pnpm
|
||||
export PNPM_HOME="/home/sudacode/.local/share/pnpm"
|
||||
case ":$PATH:" in
|
||||
*":$PNPM_HOME:"*) ;;
|
||||
*) export PATH="$PNPM_HOME:$PATH" ;;
|
||||
esac
|
||||
# pnpm end
|
||||
|
||||
@@ -2,28 +2,82 @@
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
URL="${1:-$(wl-paste -p)}"
|
||||
MPV_SOCKET=/tmp/mpvsocket
|
||||
URL="${1:-}"
|
||||
MPV_SOCKET="/tmp/mpvsocket"
|
||||
ICON_PATH="$HOME/.local/share/icons/Magna-Glassy-Dark-Icons/apps/48/mpv.svg"
|
||||
TITLE="mpv-add.sh"
|
||||
|
||||
notify() {
|
||||
local message="$1"
|
||||
notify-send -i "$ICON_PATH" "$TITLE" "$message"
|
||||
}
|
||||
|
||||
trim() {
|
||||
printf '%s' "$1" | sed 's/^[[:space:]]\+//;s/[[:space:]]\+$//'
|
||||
}
|
||||
|
||||
play_direct() {
|
||||
mpv -- "$URL" &> /dev/null &
|
||||
}
|
||||
|
||||
wait_for_socket() {
|
||||
local timeout_ms=2000
|
||||
local waited=0
|
||||
while ((waited < timeout_ms)); do
|
||||
if [[ -S "$MPV_SOCKET" ]]; then
|
||||
return 0
|
||||
fi
|
||||
sleep 0.05
|
||||
waited=$((waited + 50))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
is_valid_input() {
|
||||
local input="$1"
|
||||
|
||||
if [[ -f "$input" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! command -v yt-dlp > /dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if yt-dlp --simulate "$input" > /dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
if [[ -z "$URL" ]] && command -v wl-paste > /dev/null 2>&1; then
|
||||
URL="$(wl-paste -p || true)"
|
||||
fi
|
||||
|
||||
URL="$(trim "$URL")"
|
||||
|
||||
if [[ -z "$URL" ]]; then
|
||||
notify-send -i "$ICON_PATH" "$TITLE" "No URL provided"
|
||||
notify "No URL provided"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ -f "$URL" ]] && ! yt-dlp --simulate "$URL"; then
|
||||
notify-send -i "$ICON_PATH" "$TITLE" "Invalid URL"
|
||||
if ! is_valid_input "$URL"; then
|
||||
notify "Invalid input: provide a local file path or a yt-dlp supported URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! pgrep -x mpv &> /dev/null; then
|
||||
mpv "$URL" &> /dev/null &
|
||||
notify-send -i "$ICON_PATH" "$TITLE" "Playing $URL"
|
||||
rm -f "$MPV_SOCKET"
|
||||
mpv --input-ipc-server="$MPV_SOCKET" -- "$URL" &> /dev/null &
|
||||
notify "Playing $URL"
|
||||
else
|
||||
if echo "{ \"command\": [\"script-message\", \"add_to_queue\", \"$URL\" ] }" | socat - "$MPV_SOCKET" &> /dev/null; then
|
||||
notify-send -i "$ICON_PATH" "$TITLE" "Added $URL to queue"
|
||||
else
|
||||
notify-send -i "$ICON_PATH" "$TITLE" "Failed to add $URL to queue"
|
||||
if [[ -S "$MPV_SOCKET" ]] && wait_for_socket && echo "{ \"command\": [\"script-message\", \"add_to_queue\", \"$URL\" ] }" | socat - "$MPV_SOCKET" &> /dev/null; then
|
||||
notify "Added $URL to queue"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
notify "Queue unavailable, opening in new player"
|
||||
play_direct
|
||||
notify "Playing $URL"
|
||||
fi
|
||||
|
||||
@@ -4,6 +4,7 @@ THEME="${THEME:-$HOME/.local/share/SubMiner/themes/subminer.rasi}"
|
||||
FONTCONFIG_FILE=$HOME/.config/mpv/mpv-fonts.conf
|
||||
COMMAND=mpv
|
||||
VIDEO_EXTENSIONS="mkv|mp4|avi|webm|mov|flv|wmv|m4v|ts|m2ts"
|
||||
TARGET_DIRECTORY=""
|
||||
|
||||
# Parse command-line options first
|
||||
while getopts ":st:" opt; do
|
||||
@@ -26,6 +27,19 @@ while getopts ":st:" opt; do
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ $# -gt 1 ]]; then
|
||||
echo "Usage: $0 [-s] [-t theme] [directory]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -eq 1 ]]; then
|
||||
if [[ ! -d "$1" ]]; then
|
||||
echo "Invalid directory: $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
TARGET_DIRECTORY="$(realpath "$1")"
|
||||
fi
|
||||
|
||||
find_videos() {
|
||||
find "$PWD" -maxdepth 1 -type f -regextype posix-extended \
|
||||
-iregex ".*\.($VIDEO_EXTENSIONS)$" 2> /dev/null | sort -V
|
||||
@@ -40,6 +54,60 @@ build_rofi_menu() {
|
||||
done < <(find_videos)
|
||||
}
|
||||
|
||||
is_video_file() {
|
||||
local file="$1"
|
||||
local regex="\\.($VIDEO_EXTENSIONS)$"
|
||||
|
||||
if [[ ! "${file,,}" =~ $regex ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if command -v file > /dev/null 2>&1; then
|
||||
local mime
|
||||
mime=$(file -b --mime-type "$file" 2>/dev/null || true)
|
||||
[[ "$mime" == video/* ]] && return 0
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
select_video_via_rofi() {
|
||||
if [[ -n "$TARGET_DIRECTORY" ]]; then
|
||||
local selection=""
|
||||
local prompt="Choose Video "
|
||||
while true; do
|
||||
selection=$(rofi -show filebrowser -show-icons -theme "$THEME" \
|
||||
-theme-str 'configuration {font: "JetBrainsMono Nerd Font 10";} listview {columns: 1; lines: 15;} window {width: 88%;}' \
|
||||
-p "$prompt" \
|
||||
-filebrowser-directory "$TARGET_DIRECTORY" \
|
||||
-filebrowser-cancel-returns-1 true)
|
||||
|
||||
[[ -z "$selection" ]] && return 1
|
||||
|
||||
if [[ "$selection" != /* ]]; then
|
||||
selection="$TARGET_DIRECTORY/$selection"
|
||||
fi
|
||||
|
||||
if [[ -d "$selection" ]]; then
|
||||
prompt="Choose Video (folders are not selectable)"
|
||||
continue
|
||||
fi
|
||||
|
||||
if is_video_file "$selection"; then
|
||||
echo "$selection"
|
||||
return 0
|
||||
fi
|
||||
|
||||
prompt="Choose Video (select a video file)"
|
||||
done
|
||||
fi
|
||||
|
||||
build_rofi_menu | rofi -dmenu -i -show-icons -theme "$THEME" \
|
||||
-theme-str 'configuration {font: "JetBrainsMono Nerd Font 10";} listview {columns: 1; lines: 15;} window {width: 88%;}' -p "Choose Video "
|
||||
}
|
||||
|
||||
selection=$(select_video_via_rofi)
|
||||
|
||||
get_video_thumbnail() {
|
||||
local video="$1"
|
||||
local thumb_dir="$HOME/.cache/thumbnails/large"
|
||||
@@ -60,15 +128,24 @@ get_video_thumbnail() {
|
||||
fi
|
||||
}
|
||||
|
||||
selection=$(build_rofi_menu | rofi -dmenu -i -show-icons -theme "$THEME" \
|
||||
-theme-str 'configuration {font: "JetBrainsMono Nerd Font 10";} listview {columns: 1; lines: 15;} window {width: 88%;}' -p "Choose Video ")
|
||||
|
||||
if [[ -z "$selection" ]]; then
|
||||
echo "No video selected."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$TARGET_DIRECTORY" ]]; then
|
||||
choice="$selection"
|
||||
if [[ "$choice" != /* ]]; then
|
||||
choice="$TARGET_DIRECTORY/$choice"
|
||||
fi
|
||||
else
|
||||
choice="./$selection"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$choice" ]]; then
|
||||
echo "Selected item is not a valid file: $choice" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
THUMBNAIL_PATH=$(get_video_thumbnail "$choice")
|
||||
if [[ -n "$THUMBNAIL_PATH" && -f "$THUMBNAIL_PATH" ]]; then
|
||||
|
||||
@@ -444,6 +444,11 @@ def _type_with_tool(text: str) -> None:
|
||||
raise RuntimeError("No typing tool found. Install one of: wtype, ydotool, xdotool.")
|
||||
|
||||
|
||||
def _normalize_text_for_typing(text: str) -> str:
|
||||
# Prevent simulated Enter key presses from transcript line breaks.
|
||||
return " ".join(text.split())
|
||||
|
||||
|
||||
def _emit_text(text: str, args: argparse.Namespace, notifier: Notifier) -> int:
|
||||
if args.output == "print":
|
||||
print(text)
|
||||
@@ -451,7 +456,7 @@ def _emit_text(text: str, args: argparse.Namespace, notifier: Notifier) -> int:
|
||||
return 0
|
||||
|
||||
try:
|
||||
_type_with_tool(text)
|
||||
_type_with_tool(_normalize_text_for_typing(text))
|
||||
except Exception as exc:
|
||||
print(f"Failed to simulate typing: {exc}", file=sys.stderr)
|
||||
notifier.send("Typing error", str(exc), timeout_ms=2500)
|
||||
|
||||
Reference in New Issue
Block a user