Repository: Speyll/dotfiles Branch: main Commit: 45a4914cf020 Files: 160 Total size: 252.3 KB Directory structure: gitextract_qfp0rn95/ ├── .bashrc ├── .config/ │ ├── DankMaterialShell/ │ │ └── settings.json │ ├── MangoHud/ │ │ └── MangoHud.conf │ ├── alacritty/ │ │ ├── alacritty.toml │ │ └── colors.toml │ ├── aliasrc │ ├── autostart/ │ │ ├── autostart │ │ └── openrgb.desktop │ ├── flavours/ │ │ ├── config.toml │ │ ├── schemes/ │ │ │ ├── catppuccin/ │ │ │ │ ├── catppuccin-dark.yaml │ │ │ │ └── catppuccin-light.yaml │ │ │ ├── gruvbox/ │ │ │ │ ├── gruvbox-dark-medium.yaml │ │ │ │ └── gruvbox-light-medium.yaml │ │ │ └── solarized/ │ │ │ ├── solarized-dark.yaml │ │ │ └── solarized-light.yaml │ │ └── templates/ │ │ ├── ags/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── alacritty/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ ├── default-256.mustache │ │ │ └── default.mustache │ │ ├── fnott/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── foot/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── fuzzel/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── gtk-flatcolor/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ ├── gtk-2.mustache │ │ │ └── gtk-3.mustache │ │ ├── hyprland/ │ │ │ └── templates/ │ │ │ ├── colors.mustache │ │ │ └── config.yaml │ │ ├── imv/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── labwc/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── nvim/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── nvim-hardline/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── river/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── sway/ │ │ │ └── templates/ │ │ │ ├── colors.mustache │ │ │ └── config.yaml │ │ ├── swayimg/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── tmux/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ ├── waybar/ │ │ │ └── templates/ │ │ │ ├── config.yaml │ │ │ └── default.mustache │ │ └── wayfire/ │ │ └── templates/ │ │ ├── config.yaml │ │ └── default.mustache │ ├── fontconfig/ │ │ └── fonts.conf │ ├── gtk-2.0/ │ │ ├── gtkfilechooser.ini │ │ └── gtkrc-2.0 │ ├── gtk-3.0/ │ │ └── settings.ini │ ├── gtk-4.0/ │ │ └── settings.ini │ ├── htop/ │ │ └── htoprc │ ├── mimeapps.list │ ├── mpv/ │ │ ├── input.conf │ │ ├── mpv.conf │ │ ├── script-modules/ │ │ │ └── user-input-module.lua │ │ └── scripts/ │ │ ├── delete-current-video.lua │ │ ├── keep-session.lua │ │ ├── mpv-scut.lua │ │ ├── mpv-splice.lua │ │ ├── playlist-shuffle.lua │ │ ├── save-playlist.lua │ │ └── user-input.lua │ ├── nano/ │ │ └── nanorc │ ├── niri/ │ │ ├── config.kdl │ │ ├── dms.kdl │ │ ├── keybinds.kdl │ │ ├── layout.kdl │ │ ├── outputs.kdl │ │ ├── rules.kdl │ │ └── scripts/ │ │ ├── obs-replay │ │ └── waybar │ ├── nvim/ │ │ ├── init.lua │ │ └── lua/ │ │ └── speyll/ │ │ ├── commands.lua │ │ ├── lazy.lua │ │ ├── plugins/ │ │ │ ├── autopairs.lua │ │ │ ├── cmp.lua │ │ │ ├── colorscheme.lua │ │ │ ├── nvim-hardline.lua │ │ │ ├── nvim-highlight-colors.lua │ │ │ ├── telescope.lua │ │ │ ├── treesitter.lua │ │ │ └── undotree.lua │ │ ├── remap.lua │ │ └── settings.lua │ ├── pcmanfm-qt/ │ │ └── default/ │ │ ├── recent-files.conf │ │ └── settings.conf │ ├── pipewire/ │ │ ├── pipewire-pulse.conf.d/ │ │ │ └── switch-on-connect.conf │ │ └── pipewire.conf │ ├── qt5ct/ │ │ └── qt5ct.conf │ ├── qt6ct/ │ │ ├── qt6ct.conf │ │ └── style-colors.conf │ ├── swayimg/ │ │ ├── config │ │ └── set-wall │ ├── tmux/ │ │ └── tmux.conf │ ├── user-dirs.dirs │ ├── user-dirs.locale │ ├── wireplumber/ │ │ └── wireplumber.conf.d/ │ │ └── 51-disable-suspension.conf │ ├── xdg-desktop-portal/ │ │ ├── kde-portals.conf │ │ ├── niri-portals.conf │ │ └── portals.conf │ └── xsettingsd/ │ └── xsettingsd.conf ├── .inputrc ├── .local/ │ ├── bin/ │ │ ├── archive │ │ ├── aria2-grabber │ │ ├── aria2-lynx-downloader │ │ ├── bemoji │ │ ├── clip-manager │ │ ├── dircomp │ │ ├── exefind │ │ ├── ff-concat │ │ ├── ff-crop │ │ ├── ff-diff │ │ ├── ff-enc │ │ ├── font-char-list │ │ ├── font-unicode │ │ ├── fuzz-launcher │ │ ├── get-steamid │ │ ├── git-ops │ │ ├── grim-print │ │ ├── img-dupes │ │ ├── img-duprestore │ │ ├── img-enc │ │ ├── imv-mass │ │ ├── mass-mpv │ │ ├── mem │ │ ├── mvToParent │ │ ├── net-menu │ │ ├── reload-wall │ │ ├── spefetch │ │ ├── start-comp │ │ ├── updtscan │ │ ├── usb-mnt │ │ ├── vertsearch-lf │ │ └── yt-search │ └── share/ │ ├── applications/ │ │ ├── browser.desktop │ │ ├── file.desktop │ │ ├── img.desktop │ │ ├── text.desktop │ │ └── video.desktop │ ├── fonts/ │ │ └── git-fonts.sh │ ├── icons/ │ │ └── git-cursors.sh │ └── themes/ │ └── Base16/ │ └── openbox-3/ │ ├── bullet.xbm │ ├── close.xbm │ ├── desk.xbm │ ├── desk_toggled.xbm │ ├── iconify.xbm │ ├── max.xbm │ ├── max_disabled.xbm │ ├── max_toggled.xbm │ ├── menu.xbm │ ├── shade.xbm │ └── themerc ├── .profile └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .bashrc ================================================ # ~/.bashrc: executed by bash(1) for non-login shells. # If not running interactively, don't do anything case $- in *i*) ;; *) return;; esac # History settings export HISTCONTROL=ignoreboth:erasedups export HISTIGNORE="ls:cd:exit:history*" export HISTSIZE=1000 export HISTFILESIZE=2000 shopt -s histappend # Check window size after each command shopt -s checkwinsize # Git branch function git_branch() { local branch branch=$(git branch --show-current 2>/dev/null) if [[ -n "$branch" ]]; then # Purple color for git branch echo -e "\[\e[35m\]$branch\[\e[0m\] " fi } # Color prompt setup if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then set_prompt() { local branch=$(git_branch) local title="\[\e]0;\u@\h: \w\a\]" PS1="${title}[\[\e[32m\]\A\[\e[0m\]][\[\e[34m\]\h\[\e[0m\]][${branch}\[\e[33m\]\w\[\e[0m\]]\$ " } prompt_command() { history -a # Append current session history to file history -n # Read new history entries from file cleanup-history # Clean up the history file set_prompt # Set the prompt dynamically } PROMPT_COMMAND=prompt_command else PS1='[\A][\h][\w]\$ ' fi # Enable programmable completion if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fi fi # Load aliases [[ -f ~/.config/aliasrc ]] && . ~/.config/aliasrc # Proper FZF integration if [[ -f /usr/share/doc/fzf/examples/key-bindings.bash ]]; then source /usr/share/doc/fzf/examples/key-bindings.bash elif [[ -f ~/.fzf.bash ]]; then source ~/.fzf.bash elif [[ -f /usr/share/fzf/key-bindings.bash ]]; then source /usr/share/fzf/key-bindings.bash fi # Keep bash history clean cleanup-history() { local histfile="$HOME/.bash_history" [[ -r "$histfile" ]] || return awk ' { cleaned = $0 gsub(/[[:space:]]*$/, "", cleaned) if (cleaned != "") { last[cleaned] = NR line[NR] = cleaned } } END { for (i = 1; i <= NR; i++) { if (i in line && last[line[i]] == i) { print line[i] } } } ' "$histfile" > "${histfile}.tmp" if [[ -s "${histfile}.tmp" ]]; then command mv -f "${histfile}.tmp" "$histfile" >/dev/null 2>&1 else rm -f "${histfile}.tmp" >/dev/null 2>&1 fi history -c history -r } # Enhanced history search (CTRL-R) __fzf_history__() { history -a history -c history -r local line line=$(history | fzf --height 100% --tac --tiebreak=index --no-sort --exact \ --bind 'ctrl-d:page-down,ctrl-u:page-up' | sed 's/^ *[0-9]* *//') if [[ -n "$line" ]]; then READLINE_LINE=$line READLINE_POINT=${#line} fi } # Bind CTRL-R to the history search function in interactive shells if [[ $- == *i* ]]; then bind -x '"\C-r": __fzf_history__' fi # FZF preview with bat if available, otherwise cat if command -v bat >/dev/null 2>&1; then export FZF_CTRL_T_OPTS="--preview 'bat --color=always --line-range :500 {}'" else export FZF_CTRL_T_OPTS="--preview 'cat {}'" fi ================================================ FILE: .config/DankMaterialShell/settings.json ================================================ { "currentThemeName": "blue", "customThemeFile": "", "matugenScheme": "scheme-tonal-spot", "runUserMatugenTemplates": true, "matugenTargetMonitor": "", "popupTransparency": 1, "dockTransparency": 0.5, "widgetBackgroundColor": "sch", "widgetColorMode": "default", "cornerRadius": 5, "use24HourClock": true, "showSeconds": false, "useFahrenheit": false, "nightModeEnabled": false, "animationSpeed": 1, "customAnimationDuration": 500, "wallpaperFillMode": "Fill", "blurredWallpaperLayer": false, "blurWallpaperOnOverview": false, "showLauncherButton": true, "showWorkspaceSwitcher": true, "showFocusedWindow": true, "showWeather": true, "showMusic": true, "showClipboard": true, "showCpuUsage": true, "showMemUsage": true, "showCpuTemp": true, "showGpuTemp": true, "selectedGpuIndex": 0, "enabledGpuPciIds": [], "showSystemTray": true, "showClock": true, "showNotificationButton": true, "showBattery": true, "showControlCenterButton": true, "showCapsLockIndicator": true, "controlCenterShowNetworkIcon": true, "controlCenterShowBluetoothIcon": true, "controlCenterShowAudioIcon": true, "controlCenterShowVpnIcon": true, "controlCenterShowBrightnessIcon": false, "controlCenterShowMicIcon": false, "controlCenterShowBatteryIcon": false, "controlCenterShowPrinterIcon": false, "showPrivacyButton": true, "privacyShowMicIcon": false, "privacyShowCameraIcon": false, "privacyShowScreenShareIcon": false, "controlCenterWidgets": [ { "id": "volumeSlider", "enabled": true, "width": 50 }, { "id": "brightnessSlider", "enabled": true, "width": 50 }, { "id": "wifi", "enabled": true, "width": 50 }, { "id": "bluetooth", "enabled": true, "width": 50 }, { "id": "audioOutput", "enabled": true, "width": 50 }, { "id": "audioInput", "enabled": true, "width": 50 }, { "id": "builtin_vpn", "enabled": true, "width": 50 }, { "id": "doNotDisturb", "enabled": true, "width": 50 }, { "id": "nightMode", "enabled": true, "width": 50 }, { "id": "darkMode", "enabled": true, "width": 50 } ], "showWorkspaceIndex": false, "showWorkspacePadding": false, "workspaceScrolling": false, "showWorkspaceApps": false, "maxWorkspaceIcons": 3, "workspacesPerMonitor": true, "showOccupiedWorkspacesOnly": false, "dwlShowAllTags": false, "workspaceNameIcons": {}, "waveProgressEnabled": true, "scrollTitleEnabled": true, "clockCompactMode": true, "focusedWindowCompactMode": true, "runningAppsCompactMode": true, "keyboardLayoutNameCompactMode": true, "runningAppsCurrentWorkspace": false, "runningAppsGroupByApp": false, "centeringMode": "index", "clockDateFormat": "", "lockDateFormat": "", "mediaSize": 0, "appLauncherViewMode": "list", "spotlightModalViewMode": "list", "sortAppsAlphabetically": false, "appLauncherGridColumns": 4, "spotlightCloseNiriOverview": true, "niriOverviewOverlayEnabled": true, "weatherLocation": "New York, NY", "weatherCoordinates": "40.7128,-74.0060", "useAutoLocation": true, "weatherEnabled": true, "networkPreference": "wifi", "vpnLastConnected": "400fa537-b18c-4a96-b670-3f3713232299", "iconTheme": "breeze", "launcherLogoMode": "apps", "launcherLogoCustomPath": "", "launcherLogoColorOverride": "surface", "launcherLogoColorInvertOnMode": false, "launcherLogoBrightness": 0.5, "launcherLogoContrast": 1, "launcherLogoSizeOffset": 0, "fontFamily": "Inter Variable", "monoFontFamily": "Monospace", "fontWeight": 400, "fontScale": 1, "notepadUseMonospace": true, "notepadFontFamily": "", "notepadFontSize": 14, "notepadShowLineNumbers": false, "notepadTransparencyOverride": -1, "notepadLastCustomTransparency": 0.7, "soundsEnabled": true, "useSystemSoundTheme": false, "soundNewNotification": true, "soundVolumeChanged": true, "soundPluggedIn": true, "acMonitorTimeout": 0, "acLockTimeout": 0, "acSuspendTimeout": 0, "acSuspendBehavior": 0, "acProfileName": "", "batteryMonitorTimeout": 0, "batteryLockTimeout": 0, "batterySuspendTimeout": 0, "batterySuspendBehavior": 0, "batteryProfileName": "", "lockBeforeSuspend": false, "loginctlLockIntegration": true, "fadeToLockEnabled": false, "fadeToLockGracePeriod": 5, "launchPrefix": "", "brightnessDevicePins": {}, "wifiNetworkPins": { "preferredWifi": "Void" }, "bluetoothDevicePins": {}, "audioInputDevicePins": {}, "audioOutputDevicePins": {}, "gtkThemingEnabled": false, "qtThemingEnabled": false, "syncModeWithPortal": true, "terminalsAlwaysDark": false, "showDock": false, "dockAutoHide": false, "dockGroupByApp": true, "dockOpenOnOverview": false, "dockPosition": 1, "dockSpacing": 4, "dockBottomGap": -13, "dockMargin": 0, "dockIconSize": 34, "dockIndicatorStyle": "circle", "dockBorderEnabled": false, "dockBorderColor": "surfaceText", "dockBorderOpacity": 1, "dockBorderThickness": 1, "notificationOverlayEnabled": false, "modalDarkenBackground": true, "lockScreenShowPowerActions": true, "enableFprint": false, "maxFprintTries": 3, "lockScreenActiveMonitor": "all", "lockScreenInactiveColor": "#000000", "hideBrightnessSlider": false, "notificationTimeoutLow": 5000, "notificationTimeoutNormal": 5000, "notificationTimeoutCritical": 0, "notificationPopupPosition": 0, "osdAlwaysShowValue": false, "osdPosition": 5, "osdVolumeEnabled": true, "osdMediaVolumeEnabled": true, "osdBrightnessEnabled": true, "osdIdleInhibitorEnabled": true, "osdMicMuteEnabled": true, "osdCapsLockEnabled": true, "osdPowerProfileEnabled": true, "osdAudioOutputEnabled": true, "powerActionConfirm": true, "powerActionHoldDuration": 0.5, "powerMenuActions": [ "reboot", "logout", "poweroff", "lock", "suspend", "restart" ], "powerMenuDefaultAction": "logout", "powerMenuGridLayout": false, "customPowerActionLock": "", "customPowerActionLogout": "", "customPowerActionSuspend": "", "customPowerActionHibernate": "", "customPowerActionReboot": "", "customPowerActionPowerOff": "", "updaterUseCustomCommand": false, "updaterCustomCommand": "", "updaterTerminalAdditionalParams": "", "displayNameMode": "model", "screenPreferences": { "dock": [] }, "showOnLastDisplay": { "dock": false }, "barConfigs": [ { "id": "default", "name": "Main Bar", "enabled": true, "position": 2, "screenPreferences": [ { "name": "DP-2", "model": "24G4" } ], "showOnLastDisplay": true, "leftWidgets": [ "launcherButton", "workspaceSwitcher", { "id": "runningApps", "enabled": true } ], "centerWidgets": [], "rightWidgets": [ { "id": "systemTray", "enabled": true }, { "id": "clipboard", "enabled": true }, { "id": "notificationButton", "enabled": true }, { "id": "weather", "enabled": true }, { "id": "controlCenterButton", "enabled": true }, { "id": "clock", "enabled": true }, { "id": "spacer", "enabled": true, "size": 5 } ], "spacing": 5, "innerPadding": 0, "bottomGap": 0, "transparency": 1, "widgetTransparency": 1, "squareCorners": false, "noBackground": false, "gothCornersEnabled": false, "gothCornerRadiusOverride": false, "gothCornerRadiusValue": 12, "borderEnabled": false, "borderColor": "surfaceText", "borderOpacity": 1, "borderThickness": 1, "fontScale": 1, "autoHide": false, "autoHideDelay": 250, "openOnOverview": false, "visible": true, "popupGapsAuto": true, "popupGapsManual": 4, "maximizeDetection": false, "widgetOutlineEnabled": false, "widgetOutlineColor": "primary" }, { "id": "bar1765687519252", "name": "Bar 2", "enabled": true, "position": 0, "screenPreferences": [ { "name": "HDMI-A-1", "model": "LG FULL HD" } ], "showOnLastDisplay": false, "leftWidgets": [ "launcherButton", "workspaceSwitcher", { "id": "runningApps", "enabled": true } ], "centerWidgets": [], "rightWidgets": [ { "id": "systemTray", "enabled": true }, { "id": "clipboard", "enabled": true }, { "id": "notificationButton", "enabled": true }, { "id": "weather", "enabled": true }, { "id": "controlCenterButton", "enabled": true }, { "id": "clock", "enabled": true }, { "id": "spacer", "enabled": true, "size": 5 } ], "spacing": 5, "innerPadding": 0, "bottomGap": 0, "transparency": 1, "widgetTransparency": 1, "squareCorners": false, "noBackground": false, "gothCornersEnabled": false, "gothCornerRadiusOverride": false, "gothCornerRadiusValue": 12, "borderEnabled": false, "borderColor": "surfaceText", "borderOpacity": 1, "borderThickness": 1, "widgetOutlineEnabled": false, "widgetOutlineColor": "primary", "widgetOutlineOpacity": 1, "widgetOutlineThickness": 1, "fontScale": 1, "autoHide": false, "autoHideDelay": 250, "openOnOverview": false, "visible": true, "popupGapsAuto": true, "popupGapsManual": 4, "maximizeDetection": false } ], "configVersion": 2 } ================================================ FILE: .config/MangoHud/MangoHud.conf ================================================ ################### File Generated by Goverlay ################### legacy_layout=false horizontal horizontal_stretch=0 background_alpha=0.3 round_corners=10 background_alpha=0.3 background_color=000000 font_size=24 font_size_text=24 text_color=FFFFFF position=top-left hud_compact hud_no_margin pci_dev=0:2d:00.0 table_columns=2 gpu_text=GPU gpu_stats gpu_load_change gpu_load_value=50,90 gpu_load_color=FFFFFF,FFAA7F,CC0000 gpu_temp gpu_mem_temp gpu_color=2E9762 cpu_text=CPU cpu_stats cpu_load_change cpu_load_value=50,90 cpu_load_color=FFFFFF,FFAA7F,CC0000 cpu_temp cpu_color=2E97CB vram vram_color=AD64C1 vram_color=AD64C1 ram ram_color=C26693 fps frame_timing frametime_color=00FF00 fps_limit_method=early show_fps_limit fps_limit=119,59,48,30 fsr fps_color_change fps_color=B22222,FDFD09,39F900 fps_value=60,120 #offset=-1 vsync=0 gl_vsync=-1 time# output_folder=$HOME/.cache log_duration=30 autostart_log=0 log_interval=100 blacklist=protonplus,lsfg-vk-ui,bazzar,gnome-calculator,pamac-manager,lact,ghb,bitwig-studio,ptyxis,yumex toggle_logging=Shift_L+F2 ================================================ FILE: .config/alacritty/alacritty.toml ================================================ [general] import = [ "~/.config/alacritty/colors.toml" ] [window] opacity = 0.96 padding.x = 24 padding.y = 24 [font] normal = { family = "monospace", style = "Regular" } size = 12.0 [cursor] style = { shape = "Block", blinking = "On" } ================================================ FILE: .config/alacritty/colors.toml ================================================ # Base16 Gruvbox dark, medium - alacritty color config # Dawid Kurek (dawikur@gmail.com), morhetz (https://github.com/morhetz/gruvbox) [colors] draw_bold_text_with_bright_colors = false # Default colors [colors.primary] background = '0x282828' foreground = '0xd5c4a1' # Colors the cursor will use if `custom_cursor_colors` is true [colors.cursor] text = '0x282828' cursor = '0xd5c4a1' # Normal colors [colors.normal] black = '0x282828' red = '0xfb4934' green = '0xb8bb26' yellow = '0xfabd2f' blue = '0x83a598' magenta = '0xd3869b' cyan = '0x8ec07c' white = '0xd5c4a1' # Bright colors [colors.bright] black = '0x665c54' red = '0xfe8019' green = '0x3c3836' yellow = '0x504945' blue = '0xbdae93' magenta = '0xebdbb2' cyan = '0xd65d0e' white = '0xfbf1c7' ================================================ FILE: .config/aliasrc ================================================ #!/bin/sh # Colorized commands alias \ ls="ls -shA --color=auto" \ dir="dir --color=auto" \ vdir="vdir --color=auto" \ grep="grep --color=auto" \ fgrep="fgrep --color=auto" \ egrep="egrep --color=auto" \ diff="diff --color=auto" \ ccat="highlight --out-format=ansi" \ dfg="df -BG" \ dfm="df -BM" \ ip="ip --color=auto" # LS aliases with preserved color flags alias \ ll="ls -l --color=auto" \ la="ls -A --color=auto" \ llt="ls -latrG --color=auto" # Package management alias \ xbs="sudo xbps-install" \ xbr="sudo xbps-remove -Rv" \ xbq="xbps-query -Rs" \ pac="sudo pacman" \ prm="sudo pacman -Rns" \ pror="sudo pacman -Rns $(pacman -Qtdq)" \ apti="sudo apt-get install --no-install-recommends" \ aptr="sudo apt-get --purge autoremove" \ zyi="sudo zypper install --no-recommends" \ zyr="sudo zypper remove --clean-deps --no-confirm" \ flinst="flatpak install" \ flrem="flatpak uninstall --delete-data" \ flclean="flatpak uninstall --unused --delete-data -y && flatpak repair" # Network aliases alias \ rsync="rsync -avh --progress" \ rsync-ssh="rsync -avzh --progress -e ssh" \ rsync-net="rsync -avzh --progress" \ nfs-mount="sudo mount -t nfs -o hard,tcp,rsize=32768,wsize=32768,actimeo=30" \ ssh-mount="sshfs -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,sshfs_sync" # Safe file operations alias \ cp="cp -iv" \ mv="mv -iv" \ rm="rm -vI" \ mkd="mkdir -pv" \ clear="tput clear" \ reset="tput reset" # System utilities alias \ pyserv="python3 -m http.server" \ pyenv="python -m venv" \ cleanup-gamescope='pkill -9 -f "wine|wineserver|winedevice.exe|explorer.exe|gamescope-wl"' \ reset="tput reset" # Version control alias gcl='git clone --depth 1' # Use neovim if available command -v nvim >/dev/null && alias vim="nvim" vimdiff="nvim -d" # XDG-compliant tmux configuration alias tmux="tmux -f ${XDG_CONFIG_HOME:-$HOME/.config}/tmux/tmux.conf" ================================================ FILE: .config/autostart/autostart ================================================ #!/bin/sh LOG="/tmp/autostart.log" # Config AUDIO=false MODE="swaybg-random-online" # swaybg, swaybg-random, mpvpaper-local, mpvpaper-online, swaybg-random-online, wallhaven, none THEME_MODE="none" # auto, fixed, none THEME_NAME="gruvbox-dark-medium" CURSOR="Kaela-Kovalskia-v2" WAYBAR_STYLE="none" # stacking, tiling, none UPDATE_SCAN=true # Defaults local DWALL="$HOME/pictures/walls/wall.jpg" DVWALL="$HOME/pictures/walls/vert-wall.jpg" # Pastebin URLs P_WALL="https://pastebin.com/raw/7YwMgZXg" P_VWALL="https://pastebin.com/raw/Q8GUUAse" P_VID="https://pastebin.com/raw/yHFpxMDB" P_VVID="https://pastebin.com/raw/NTVA8RMd" # Wait for Wayland compositor to be ready (max 10s) timeout=20 while { [ -z "$WAYLAND_DISPLAY" ] || [ ! -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; } && [ "$timeout" -gt 0 ]; do sleep 0.5 timeout=$((timeout - 1)) done # --- Env setup --- dbus-update-activation-environment --all >>"$LOG" 2>&1 & #/usr/libexec/polkit-gnome-authentication-agent-1 >>"$LOG" 2>&1 & /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 >>"$LOG" 2>&1 & # --- Monitor layout --- #wlr-randr --output DP-2 --on --mode 1920x1080@120 --pos 0,0 --transform normal --scale 1 --adaptive-sync enabled >>"$LOG" 2>&1 #wlr-randr --output HDMI-A-1 --on --mode 1920x1080@60 --pos -1080,-840 --transform 270 --scale 1 --adaptive-sync enabled >>"$LOG" 2>&1 & # --- Process Management --- for p in flavours mpvpaper swaybg fnott wlsunset cliphist; do pkill -x "$p" >>"$LOG" 2>&1 || : done # --- Audio --- if [ "$AUDIO" = true ]; then for p in pipewire wireplumber pipewire-pulse; do pkill -x "$p" >>"$LOG" 2>&1 || :; done pipewire >>"$LOG" 2>&1 & sleep 1 wireplumber >>"$LOG" 2>&1 & pipewire-pulse >>"$LOG" 2>&1 & fi # --- OpenRGB --- if command -v openrgb >/dev/null 2>&1; then openrgb --server -p pureWhite >>"$LOG" 2>&1 & else echo "OpenRGB not found" >>"$LOG" fi # --- Helpers --- get_orient() { wlr-randr | awk ' /^[A-Za-z0-9-]+/ { o = $1 } /Transform:/ { t = $2 if (t ~ /90|270/) print o ":portrait" else print o ":landscape" } ' } fetch_url() { curl -fsSL "$1" | shuf -n1 | tr -d '\r\n' | xargs } download_wallhaven() { r=$1 out=$2 fb=$3 res=$4 pg=$(shuf -i1-5 -n1) json=$(curl -sf "https://wallhaven.cc/api/v1/search?categories=110&purity=100&sorting=toplist&topRange=1y&ratios=$r&atleast=$res&page=$pg&per_page=24") || { echo "Wallhaven fail $r" >>"$LOG" cp "$fb" "$out" return } cnt=$(echo "$json" | jq '.data|length') if [ "$cnt" -eq 0 ]; then cp "$fb" "$out" return fi idx=$(shuf -i0-$((cnt - 1)) -n1) url=$(echo "$json" | jq -r ".data[$idx].path") curl -sfL "$url" -o "$out" || cp "$fb" "$out" } apply_swaybg() { w=$1 vw=$2 while IFS=: read -r o or; do if [ "$or" = "portrait" ]; then swaybg -o "$o" -i "$vw" -m fill >>"$LOG" 2>&1 & else swaybg -o "$o" -i "$w" -m fill >>"$LOG" 2>&1 & fi done <>"$LOG" continue fi mpvpaper -vsp -o "no-audio pause=no --loop --ytdl-format='bestvideo[height<=1080]+bestaudio/best'" "$o" "$v" >>"$LOG" 2>&1 & else if [ "$or" = "portrait" ]; then u=$(fetch_url "$P_VVID") else u=$(fetch_url "$P_VID") fi mpvpaper -vsp -o "no-audio pause=no --loop --ytdl-format='bestvideo[height<=1080]+bestaudio/best'" "$o" "$u" >>"$LOG" 2>&1 & fi done } configure_theme() { case "$THEME_MODE" in auto) if [ -f /tmp/wall.jpg ]; then flavours generate dark /tmp/wall.jpg >>"$LOG" 2>&1 flavours apply generated >>"$LOG" 2>&1 & fi ;; fixed) flavours apply "$THEME_NAME" >>"$LOG" 2>&1 & ;; none) ;; esac } configure_waybar() { case "$WAYBAR_STYLE" in stacking) pkill -x waybar >>"$LOG" 2>&1 || : waybar -c "$HOME/.config/waybar/stacking-config" -s "$HOME/.config/waybar/style.css" >>"$LOG" 2>&1 & ;; tiling) pkill -x waybar >>"$LOG" 2>&1 || : waybar -c "$HOME/.config/waybar/tiling-config" -s "$HOME/.config/waybar/style.css" >>"$LOG" 2>&1 & ;; none) ;; esac } # --- Main --- case "$MODE" in swaybg-random-online) w=$(fetch_url "$P_WALL") curl -fsSL "$w" -o /tmp/wall.jpg || cp "$DWALL" /tmp/wall.jpg vw=$(fetch_url "$P_VWALL") curl -fsSL "$vw" -o /tmp/vert_wall.jpg || cp "$DVWALL" /tmp/vert_wall.jpg apply_swaybg /tmp/wall.jpg /tmp/vert_wall.jpg ;; swaybg-random) w=$(find "$HOME/pictures/walls/"*.jpg -type f | shuf -n1) [ -z "$w" ] && w="$DWALL" vw=$(find "$HOME/pictures/walls/"vert-*.jpg -type f | shuf -n1) [ -z "$vw" ] && vw="$DVWALL" apply_swaybg "$w" "$vw" ;; swaybg) apply_swaybg "$DWALL" "$DVWALL" ;; mpvpaper-local|mpvpaper-online) apply_mpvpaper ;; wallhaven) download_wallhaven "16x9" /tmp/wall.jpg "$DWALL" "1920x1080" download_wallhaven "9x16" /tmp/vert_wall.jpg "$DVWALL" "1080x1920" apply_swaybg /tmp/wall.jpg /tmp/vert_wall.jpg ;; none) ;; *) echo "Unknown MODE: $MODE" >>"$LOG" ;; esac configure_theme configure_waybar # --- Cursor --- gsettings set org.gnome.desktop.interface cursor-theme "$CURSOR" >>"$LOG" 2>&1 & seat seat0 xcursor_theme "$CURSOR" >>"$LOG" 2>&1 & # --- Extras --- #fnott >>"$LOG" 2>&1 & wlsunset -l 36.7 -L 3.08 >>"$LOG" 2>&1 & wl-paste --watch cliphist store -max-items 100 >>"$LOG" 2>&1 & gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' & # --- Updates --- if [ "$UPDATE_SCAN" = true ]; then sleep 2 "$HOME/.local/bin/updtscan" >>"$LOG" 2>&1 & fi ================================================ FILE: .config/autostart/openrgb.desktop ================================================ [Desktop Entry] Type=Application Exec=bash -c 'if command -v openrgb >/dev/null 2>&1; then openrgb --server -p pureWhite >>"$HOME/openrgb.log" 2>&1 & else echo "OpenRGB is not installed, skipping RGB startup." >>"$HOME/openrgb.log"; fi' Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true Name=OpenRGB Autostart Comment=Start OpenRGB server with pureWhite profile at login ================================================ FILE: .config/flavours/config.toml ================================================ shell = "bash -c '{}'" [[item]] file = "~/.config/waybar/colors.css" template = "waybar" hook = "pkill -SIGRTMIN+7 waybar" rewrite = true [[item]] file = "~/.config/foot/colors.ini" template = "foot" hook = "footclient -e 'source ~/.config/foot/colors.ini'" rewrite = true [[item]] file = "~/.config/alacritty/colors.toml" template = "alacritty" rewrite = true [[items]] file = "~/.config/fuzzel/colors.ini" template = "fuzzel" rewrite = true [[items]] file = "/home/lyes/.local/share/themes/Base16/openbox-3/themerc" template = "labwc" hook = "labwc -r" start= "!! Start flavours" end = "!! End flavours" [[items]] file = "/home/lyes/.config/nvim/lua/speyll/plugins/colorscheme.lua" template = "nvim" hook = "nvim --server /tmp/nvim-server --remote-send ':source ~/.config/nvim/lua/speyll/plugins/colorscheme.lua:lua require(\"base16-colorscheme\").setup()'" start= "-- Start flavours" end = "-- End flavours" [[items]] file = "/home/lyes/.config/nvim/lua/speyll/plugins/nvim-hardline.lua" template = "nvim-hardline" start= "-- Start flavours" end = "-- End flavours" [[items]] file = "~/.config/imv/config" template = "imv" [[items]] file = "~/.config/fnott/fnott.ini" template = "fnott" [[item]] file = "~/.config/swayimg/config" template = "swayimg" [[item]] file = "~/.config/sway/config.d/colors" template = "sway" subtemplate = "colors" rewrite = true light = false hook = "swaymsg reload" [[items]] file = "~/.config/hypr/colors.conf" template = "hyprland" subtemplate = "colors" rewrite = true hook = "hyprctl reload" [[item]] file = "~/.config/river/init" template = "river" [[item]] file = "~/.config/wayfire.ini" template = "wayfire" ================================================ FILE: .config/flavours/schemes/catppuccin/catppuccin-dark.yaml ================================================ scheme: "Catppuccin Mocha" author: "https://github.com/catppuccin/catppuccin" base00: "1e1e2e" # base base01: "181825" # mantle base02: "313244" # surface0 base03: "45475a" # surface1 base04: "585b70" # surface2 base05: "cdd6f4" # text base06: "f5e0dc" # rosewater base07: "b4befe" # lavender base08: "f38ba8" # red base09: "fab387" # peach base0A: "f9e2af" # yellow base0B: "a6e3a1" # green base0C: "94e2d5" # teal base0D: "89b4fa" # blue base0E: "cba6f7" # mauve base0F: "f2cdcd" # flamingo ================================================ FILE: .config/flavours/schemes/catppuccin/catppuccin-light.yaml ================================================ scheme: "Catppuccin Latte" author: "https://github.com/catppuccin/catppuccin" base00: "eff1f5" # base base01: "e6e9ef" # mantle base02: "ccd0da" # surface0 base03: "bcc0cc" # surface1 base04: "acb0be" # surface2 base05: "4c4f69" # text base06: "dc8a78" # rosewater base07: "7287fd" # lavender base08: "d20f39" # red base09: "fe640b" # peach base0A: "df8e1d" # yellow base0B: "40a02b" # green base0C: "179299" # teal base0D: "1e66f5" # blue base0E: "8839ef" # mauve base0F: "dd7878" # flamingo ================================================ FILE: .config/flavours/schemes/gruvbox/gruvbox-dark-medium.yaml ================================================ scheme: "Gruvbox dark, medium" author: "Dawid Kurek (dawikur@gmail.com), morhetz (https://github.com/morhetz/gruvbox)" base00: "282828" # ---- base01: "3c3836" # --- base02: "504945" # -- base03: "665c54" # - base04: "bdae93" # + base05: "d5c4a1" # ++ base06: "ebdbb2" # +++ base07: "fbf1c7" # ++++ base08: "fb4934" # red base09: "fe8019" # orange base0A: "fabd2f" # yellow base0B: "b8bb26" # green base0C: "8ec07c" # aqua/cyan base0D: "83a598" # blue base0E: "d3869b" # purple base0F: "d65d0e" # brown ================================================ FILE: .config/flavours/schemes/gruvbox/gruvbox-light-medium.yaml ================================================ scheme: "Gruvbox light, medium" author: "Dawid Kurek (dawikur@gmail.com), morhetz (https://github.com/morhetz/gruvbox)" base00: "fbf1c7" # ---- base01: "ebdbb2" # --- base02: "d5c4a1" # -- base03: "bdae93" # - base04: "665c54" # + base05: "504945" # ++ base06: "3c3836" # +++ base07: "282828" # ++++ base08: "9d0006" # red base09: "af3a03" # orange base0A: "b57614" # yellow base0B: "79740e" # green base0C: "427b58" # aqua/cyan base0D: "076678" # blue base0E: "8f3f71" # purple base0F: "d65d0e" # brown ================================================ FILE: .config/flavours/schemes/solarized/solarized-dark.yaml ================================================ scheme: "Solarized Dark" author: "Ethan Schoonover (modified by aramisgithub)" base00: "002b36" base01: "073642" base02: "586e75" base03: "657b83" base04: "839496" base05: "93a1a1" base06: "eee8d5" base07: "fdf6e3" base08: "dc322f" base09: "cb4b16" base0A: "b58900" base0B: "859900" base0C: "2aa198" base0D: "268bd2" base0E: "6c71c4" base0F: "d33682" ================================================ FILE: .config/flavours/schemes/solarized/solarized-light.yaml ================================================ scheme: "Solarized Light" author: "Ethan Schoonover (modified by aramisgithub)" base00: "fdf6e3" base01: "eee8d5" base02: "93a1a1" base03: "839496" base04: "657b83" base05: "586e75" base06: "073642" base07: "002b36" base08: "dc322f" base09: "cb4b16" base0A: "b58900" base0B: "859900" base0C: "2aa198" base0D: "268bd2" base0E: "6c71c4" base0F: "d33682" ================================================ FILE: .config/flavours/templates/ags/templates/config.yaml ================================================ colors: extension: .scss output: colors ================================================ FILE: .config/flavours/templates/ags/templates/default.mustache ================================================ @define-color theme-base00 #{{base00-hex}}; @define-color theme-base01 #{{base01-hex}}; @define-color theme-base02 #{{base02-hex}}; @define-color theme-base03 #{{base03-hex}}; @define-color theme-base04 #{{base04-hex}}; @define-color theme-base05 #{{base05-hex}}; @define-color theme-base06 #{{base06-hex}}; @define-color theme-base07 #{{base07-hex}}; @define-color theme-base08 #{{base08-hex}}; @define-color theme-base09 #{{base09-hex}}; @define-color theme-base0A #{{base0A-hex}}; @define-color theme-base0B #{{base0B-hex}}; @define-color theme-base0C #{{base0C-hex}}; @define-color theme-base0D #{{base0D-hex}}; @define-color theme-base0E #{{base0E-hex}}; @define-color theme-base0F #{{base0F-hex}}; ================================================ FILE: .config/flavours/templates/alacritty/templates/config.yaml ================================================ default: extension: .toml output: colors default-256: extension: -256.toml output: colors ================================================ FILE: .config/flavours/templates/alacritty/templates/default-256.mustache ================================================ # Base16 {{scheme-name}} 256 - alacritty color config # {{scheme-author}} # Default colors [colors.primary] background = '0x{{base00-hex}}' foreground = '0x{{base05-hex}}' # Colors the cursor will use if `custom_cursor_colors` is true [colors.cursor] text = '0x{{base00-hex}}' cursor = '0x{{base05-hex}}' # Normal colors [colors.normal] black = '0x{{base00-hex}}' red = '0x{{base08-hex}}' green = '0x{{base0B-hex}}' yellow = '0x{{base0A-hex}}' blue = '0x{{base0D-hex}}' magenta = '0x{{base0E-hex}}' cyan = '0x{{base0C-hex}}' white = '0x{{base05-hex}}' # Bright colors [colors.bright] black = '0x{{base03-hex}}' red = '0x{{base08-hex}}' green = '0x{{base0B-hex}}' yellow = '0x{{base0A-hex}}' blue = '0x{{base0D-hex}}' magenta = '0x{{base0E-hex}}' cyan = '0x{{base0C-hex}}' white = '0x{{base07-hex}}' [[colors.indexed_colors]] index = 16 color = "0x{{base09-hex}}" [[colors.indexed_colors]] index = 17 color = "0x{{base0F-hex}}" [[colors.indexed_colors]] index = 18 color = "0x{{base01-hex}}" [[colors.indexed_colors]] index = 19 color = "0x{{base02-hex}}" [[colors.indexed_colors]] index = 20 color = "0x{{base04-hex}}" [[colors.indexed_colors]] index = 21 color = "0x{{base06-hex}}" ================================================ FILE: .config/flavours/templates/alacritty/templates/default.mustache ================================================ # Base16 {{scheme-name}} - alacritty color config # {{scheme-author}} [colors] draw_bold_text_with_bright_colors = false # Default colors [colors.primary] background = '0x{{base00-hex}}' foreground = '0x{{base05-hex}}' # Colors the cursor will use if `custom_cursor_colors` is true [colors.cursor] text = '0x{{base00-hex}}' cursor = '0x{{base05-hex}}' # Normal colors [colors.normal] black = '0x{{base00-hex}}' red = '0x{{base08-hex}}' green = '0x{{base0B-hex}}' yellow = '0x{{base0A-hex}}' blue = '0x{{base0D-hex}}' magenta = '0x{{base0E-hex}}' cyan = '0x{{base0C-hex}}' white = '0x{{base05-hex}}' # Bright colors [colors.bright] black = '0x{{base03-hex}}' red = '0x{{base09-hex}}' green = '0x{{base01-hex}}' yellow = '0x{{base02-hex}}' blue = '0x{{base04-hex}}' magenta = '0x{{base06-hex}}' cyan = '0x{{base0F-hex}}' white = '0x{{base07-hex}}' ================================================ FILE: .config/flavours/templates/fnott/templates/config.yaml ================================================ default: extension: .ini output: colors ================================================ FILE: .config/flavours/templates/fnott/templates/default.mustache ================================================ background={{base00-hex}}bf border-color={{base0B-hex}}ff title-color={{base0B-hex}}ff progress-bar-color={{base0B-hex}}ff [low] background={{base00-hex}}bf title-color={{base0D-hex}}ff summary-color={{base05-hex}}ff body-color={{base05-hex}}ff # [normal] [critical] title-color={{base0A-hex}}ff ================================================ FILE: .config/flavours/templates/foot/templates/config.yaml ================================================ default: extension: .ini output: colors ================================================ FILE: .config/flavours/templates/foot/templates/default.mustache ================================================ # Base16 {{scheme-name}} - foot color config # {{scheme-author}} [colors] background={{base00-hex}} foreground={{base06-hex}} # Normal colors regular0={{base00-hex}} # Black, could also be base01 regular1={{base08-hex}} # Red regular2={{base0B-hex}} # Green regular3={{base0A-hex}} # Yellow regular4={{base0D-hex}} # Blue regular5={{base0E-hex}} # Magenta regular6={{base0C-hex}} # Cyan regular7={{base06-hex}} # White # Bright colors bright0={{base03-hex}} bright1={{base09-hex}} bright2={{base01-hex}} bright3={{base02-hex}} bright4={{base04-hex}} bright5={{base06-hex}} bright6={{base0F-hex}} bright7={{base07-hex}} ================================================ FILE: .config/flavours/templates/fuzzel/templates/config.yaml ================================================ default: extension: .ini output: colors ================================================ FILE: .config/flavours/templates/fuzzel/templates/default.mustache ================================================ [colors] background=#{{base00-hex}}df text=#{{base06-hex}}ff input=#{{base06-hex}}ff match=#{{base08-hex}}ff selection=#{{base0C-hex}}ff selection-text=#{{base00-hex}}df selection-match=#{{base08-hex}}ff border=#{{base0C-hex}}ff ================================================ FILE: .config/flavours/templates/gtk-flatcolor/templates/config.yaml ================================================ gtk-2: extension: -gtkrc output: gtk-2 gtk-3: extension: -gtk.css output: gtk-3 ================================================ FILE: .config/flavours/templates/gtk-flatcolor/templates/gtk-2.mustache ================================================ ## Base16 {{scheme-name}} # Scheme author: {{scheme-author}} # Template author: Tinted Theming (https://github.com/tinted-theming) # In file gtk-2.0/gtkrc, delete "gtk-color-scheme" including everything between quotes (don't delete gtk-auto-mnemonics) and inject this. gtk-color-scheme = "bg_color:#{{base00-hex}} color0:#{{base00-hex}} text_color:#{{base05-hex}} selected_bg_color:#{{base02-hex}} selected_fg_color:#{{base05-hex}} tooltip_bg_color:#{{base00-hex}} tooltip_fg_color:#{{base05-hex}} titlebar_bg_color:#{{base00-hex}} titlebar_fg_color:#{{base05-hex}} menu_bg_color:#{{base00-hex}} menu_fg_color:#{{base05-hex}} link_color:#{{base02-hex}}" ================================================ FILE: .config/flavours/templates/gtk-flatcolor/templates/gtk-3.mustache ================================================ /* Base16 {{scheme-name}} Scheme author: {{scheme-author}} Template author: Tinted Theming (https://github.com/tinted-theming) In files gtk-3.0/gtk.css and gtk-3.20/gtk.css, delete section "Default color scheme" and inject this */ @define-color bg_color #{{base00-hex}}; @define-color fg_color #{{base05-hex}}; @define-color base_color #{{base01-hex}}; @define-color text_color #{{base05-hex}}; @define-color text_color_disabled #{{base03-hex}}; @define-color selected_bg_color #{{base02-hex}}; @define-color selected_fg_color #{{base05-hex}}; @define-color tooltip_bg_color #{{base00-hex}}; @define-color tooltip_fg_color #{{base05-hex}}; ================================================ FILE: .config/flavours/templates/hyprland/templates/colors.mustache ================================================ # Base16 {{scheme-name}} # Author: {{scheme-author}} $base00 = 0xff{{base00-hex}} $base01 = 0xff{{base01-hex}} $base02 = 0xff{{base02-hex}} $base03 = 0xff{{base03-hex}} $base04 = 0xff{{base04-hex}} $base05 = 0xff{{base05-hex}} $base06 = 0xff{{base06-hex}} $base07 = 0xff{{base07-hex}} $base08 = 0xff{{base08-hex}} $base09 = 0xff{{base09-hex}} $base0A = 0xff{{base0A-hex}} $base0B = 0xff{{base0B-hex}} $base0C = 0xff{{base0C-hex}} $base0D = 0xff{{base0D-hex}} $base0E = 0xff{{base0E-hex}} $base0F = 0xff{{base0F-hex}} ================================================ FILE: .config/flavours/templates/hyprland/templates/config.yaml ================================================ colors: extension: .conf output: themes ================================================ FILE: .config/flavours/templates/imv/templates/config.yaml ================================================ default: extension: .ini output: colors ================================================ FILE: .config/flavours/templates/imv/templates/default.mustache ================================================ background = {{base00-hex}} overlay_text_color = {{base06-hex}} overlay_background_color = {{base00-hex}} ================================================ FILE: .config/flavours/templates/labwc/templates/config.yaml ================================================ default: output: colors ================================================ FILE: .config/flavours/templates/labwc/templates/default.mustache ================================================ !! Window colors window.active.title.bg.color: #{{base05-hex}} window.inactive.title.bg.color: #{{base00-hex}} window.active.label.text.color: #{{base00-hex}} window.inactive.label.text.color: #{{base05-hex}} window.active.border.color: #{{base05-hex}} window.inactive.border.color: #{{base00-hex}} window.active.button.iconify.pressed.image.color: #{{base00-hex}} window.active.button.iconify.disabled.image.color: #{{base0D-hex}} window.active.button.iconify.unpressed.image.color: #{{base00-hex}} window.active.button.iconify.toggled.pressed.image.color: #{{base00-hex}} window.active.button.iconify.toggled.unpressed.image.color: #{{base00-hex}} window.active.button.max.pressed.image.color: #{{base00-hex}} window.active.button.max.disabled.image.color: #{{base0D-hex}} window.active.button.max.unpressed.image.color: #{{base00-hex}} window.active.button.max.toggled.pressed.image.color: #{{base00-hex}} window.active.button.max.toggled.unpressed.image.color: #{{base00-hex}} window.active.button.close.pressed.image.color: #{{base00-hex}} window.active.button.close.disabled.image.color: #{{base0D-hex}} window.active.button.close.unpressed.image.color: #{{base00-hex}} window.active.button.close.toggled.pressed.image.color: #{{base00-hex}} window.active.button.close.toggled.unpressed.image.color: #{{base00-hex}} window.active.button.menu.pressed.image.color: #{{base00-hex}} window.active.button.menu.disabled.image.color: #{{base0D-hex}} window.active.button.menu.unpressed.image.color: #{{base00-hex}} window.active.button.menu.toggled.pressed.image.color: #{{base00-hex}} window.active.button.menu.toggled.unpressed.image.color: #{{base00-hex}} window.inactive.button.iconify.pressed.image.color: #{{base03-hex}} window.inactive.button.iconify.disabled.image.color: #{{base0D-hex}} window.inactive.button.iconify.unpressed.image.color: #{{base03-hex}} window.inactive.button.iconify.toggled.pressed.image.color: #{{base03-hex}} window.inactive.button.iconify.toggled.unpressed.image.color: #{{base03-hex}} window.inactive.button.max.pressed.image.color: #{{base03-hex}} window.inactive.button.max.disabled.image.color: #{{base0D-hex}} window.inactive.button.max.unpressed.image.color: #{{base03-hex}} window.inactive.button.max.toggled.pressed.image.color: #{{base06-hex}} window.inactive.button.max.toggled.unpressed.image.color: #{{base06-hex}} window.inactive.button.close.pressed.image.color: #{{base03-hex}} window.inactive.button.close.disabled.image.color: #{{base0D-hex}} window.inactive.button.close.unpressed.image.color: #{{base03-hex}} window.inactive.button.close.toggled.pressed.image.color: #{{base03-hex}} window.inactive.button.close.toggled.unpressed.image.color: #{{base03-hex}} window.inactive.button.menu.pressed.image.color: #{{base03-hex}} window.inactive.button.menu.disabled.image.color: #{{base0D-hex}} window.inactive.button.menu.unpressed.image.color: #{{base03-hex}} window.inactive.button.menu.toggled.pressed.image.color: #{{base03-hex}} window.inactive.button.menu.toggled.unpressed.image.color: #{{base03-hex}} !! Menu colors menu.items.bg.color: #{{base00-hex}} menu.items.text.color: #{{base05-hex}} menu.items.disabled.text.color: #{{base03-hex}} menu.items.active.bg.color: #{{base05-hex}} menu.items.active.text.color: #{{base00-hex}} menu.separator.color: #{{base05-hex}} menu.border.color: #{{base05-hex}} menu.title.bg.color: #{{base05-hex}} menu.title.text.color: #{{base00-hex}} !! OSD colors osd.border.color: #{{base05-hex}} osd.label.text.color: #{{base05-hex}} osd.bg.color: #{{base00-hex}} ================================================ FILE: .config/flavours/templates/nvim/templates/config.yaml ================================================ default: extension: .lua output: colors ================================================ FILE: .config/flavours/templates/nvim/templates/default.mustache ================================================ base00 = "none", base01 = "#{{base01-hex}}", base02 = "#{{base02-hex}}", base03 = "#{{base03-hex}}", base04 = "#{{base04-hex}}", base05 = "#{{base05-hex}}", base06 = "#{{base06-hex}}", base07 = "#{{base07-hex}}", base08 = "#{{base08-hex}}", base09 = "#{{base09-hex}}", base0A = "#{{base0A-hex}}", base0B = "#{{base0B-hex}}", base0C = "#{{base0C-hex}}", base0D = "#{{base0D-hex}}", base0E = "#{{base0E-hex}}", base0F = "#{{base0F-hex}}" ================================================ FILE: .config/flavours/templates/nvim-hardline/templates/config.yaml ================================================ default: extension: .lua output: colors ================================================ FILE: .config/flavours/templates/nvim-hardline/templates/default.mustache ================================================ custom_theme = { text = {gui = "#{{base00-hex}}", cterm = "235", cterm16 = "0"}, normal = {gui = "#{{base0D-hex}}", cterm = "109", cterm16 = "6"}, insert = {gui = "#{{base0B-hex}}", cterm = "142", cterm16 = "2"}, replace = {gui = "#{{base0A-hex}}", cterm = "214", cterm16 = "3"}, inactive_comment = {gui = "NONE", cterm = "NONE", cterm16 = "NONE"}, inactive_cursor = {gui = "NONE", cterm = "NONE", cterm16 = "NONE"}, inactive_menu = {gui = "NONE", cterm = "NONE", cterm16 = "NONE"}, visual = {gui = "#{{base0C-hex}}", cterm = "108", cterm16 = "6"}, command = {gui = "#{{base0E-hex}}", cterm = "132", cterm16 = "5"}, alt_text = {gui = "#{{base06-hex}}", cterm = "223", cterm16 = "7"}, warning = {gui = "#{{base08-hex}}", cterm = "167", cterm16 = "1"}, }, ================================================ FILE: .config/flavours/templates/river/templates/config.yaml ================================================ colors: extension: .sh output: colors ================================================ FILE: .config/flavours/templates/river/templates/default.mustache ================================================ riverctl background-color 0x{{base00-hex}}ff riverctl border-color-focused 0x{{base0C-hex}}ff riverctl border-color-unfocused 0x{{base00-hex}}ff ================================================ FILE: .config/flavours/templates/sway/templates/colors.mustache ================================================ ## Base16 {{scheme-name}} # Author: {{scheme-author}} set $base00 #{{base00-hex}} set $base01 #{{base01-hex}} set $base02 #{{base02-hex}} set $base03 #{{base03-hex}} set $base04 #{{base04-hex}} set $base05 #{{base05-hex}} set $base06 #{{base06-hex}} set $base07 #{{base07-hex}} set $base08 #{{base08-hex}} set $base09 #{{base09-hex}} set $base0A #{{base0A-hex}} set $base0B #{{base0B-hex}} set $base0C #{{base0C-hex}} set $base0D #{{base0D-hex}} set $base0E #{{base0E-hex}} set $base0F #{{base0F-hex}} ================================================ FILE: .config/flavours/templates/sway/templates/config.yaml ================================================ colors: extension: .config output: themes ================================================ FILE: .config/flavours/templates/swayimg/templates/config.yaml ================================================ colors: output: colors ================================================ FILE: .config/flavours/templates/swayimg/templates/default.mustache ================================================ [viewer] window = {{base00-hex}} transparency = grid scale = optimal fixed = yes antialiasing = yes slideshow = no slideshow_time = 7 history = 1 preload = 1 [gallery] size = 200 cache = 100 fill = yes antialiasing = no window = {{base00-hex}} background = {{base00-hex}} select = {{base06-hex}} border = {{base0C-hex}} shadow = {{base03-hex}} [list] order = alpha loop = yes recursive = no all = yes [font] name = monospace size = 14 color = {{base06-hex}} shadow = {{base03-hex}} ================================================ FILE: .config/flavours/templates/tmux/templates/config.yaml ================================================ default: output: colors ================================================ FILE: .config/flavours/templates/tmux/templates/default.mustache ================================================ custom_theme = { text = {gui = "#{{base00-hex}}", cterm = "235", cterm16 = "0"}, normal = {gui = "#{{base0D-hex}}", cterm = "109", cterm16 = "6"}, insert = {gui = "#{{base0B-hex}}", cterm = "142", cterm16 = "2"}, replace = {gui = "#{{base0A-hex}}", cterm = "214", cterm16 = "3"}, inactive_comment = {gui = "NONE", cterm = "NONE", cterm16 = "NONE"}, inactive_cursor = {gui = "NONE", cterm = "NONE", cterm16 = "NONE"}, inactive_menu = {gui = "NONE", cterm = "NONE", cterm16 = "NONE"}, visual = {gui = "#{{base0C-hex}}", cterm = "108", cterm16 = "6"}, command = {gui = "#{{base0E-hex}}", cterm = "132", cterm16 = "5"}, alt_text = {gui = "#{{base06-hex}}", cterm = "223", cterm16 = "7"}, warning = {gui = "#{{base08-hex}}", cterm = "167", cterm16 = "1"}, }, ================================================ FILE: .config/flavours/templates/waybar/templates/config.yaml ================================================ default: extension: .css output: colors ================================================ FILE: .config/flavours/templates/waybar/templates/default.mustache ================================================ /* * * Base16 {{scheme-name}} * Author: {{scheme-author}} * */ @define-color base00 #{{base00-hex}}; @define-color base01 #{{base01-hex}}; @define-color base02 #{{base02-hex}}; @define-color base03 #{{base03-hex}}; @define-color base04 #{{base04-hex}}; @define-color base05 #{{base05-hex}}; @define-color base06 #{{base06-hex}}; @define-color base07 #{{base07-hex}}; @define-color base08 #{{base08-hex}}; @define-color base09 #{{base09-hex}}; @define-color base0A #{{base0A-hex}}; @define-color base0B #{{base0B-hex}}; @define-color base0C #{{base0C-hex}}; @define-color base0D #{{base0D-hex}}; @define-color base0E #{{base0E-hex}}; @define-color base0F #{{base0F-hex}}; @define-color bg rgba({{base00-rgb-r}}, {{base00-rgb-g}}, {{base00-rgb-b}}, 0.90); @define-color accentDim rgba({{base0C-rgb-r}}, {{base0C-rgb-g}}, {{base0C-rgb-b}}, 0.35); ================================================ FILE: .config/flavours/templates/wayfire/templates/config.yaml ================================================ colors: extension: .ini output: colors ================================================ FILE: .config/flavours/templates/wayfire/templates/default.mustache ================================================ active_color = \#{{base0C-hex}FF inactive_color = \#{{base00-hex}}FF ================================================ FILE: .config/fontconfig/fonts.conf ================================================ rgb true hintfull true 8 sans-serif Noto Sans Ubuntu serif Noto Serif monospace Cascadia Mono Terminus (TTF) Hack Noto Sans Mono Ubuntu Mono emoji Noto Color Emoji Twemoji ================================================ FILE: .config/gtk-2.0/gtkfilechooser.ini ================================================ [Filechooser Settings] LocationMode=path-bar ShowHidden=true ShowSizeColumn=true GeometryX=0 GeometryY=0 GeometryWidth=889 GeometryHeight=662 SortColumn=name SortOrder=ascending StartupMode=recent ================================================ FILE: .config/gtk-2.0/gtkrc-2.0 ================================================ gtk-theme-name="Breeze" gtk-icon-theme-name="Breeze" gtk-font-name="Sans 11" gtk-cursor-theme-name="Kaela-Kovalskia-v2" gtk-cursor-theme-size=24 gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR gtk-button-images=0 gtk-menu-images=0 gtk-enable-event-sounds=1 gtk-enable-input-feedback-sounds=0 gtk-xft-antialias=1 gtk-xft-hinting=1 gtk-xft-hintstyle="hintslight" gtk-xft-rgba="rgb" ================================================ FILE: .config/gtk-3.0/settings.ini ================================================ [Settings] gtk-button-images=1 gtk-theme-name=Breeze gtk-icon-theme-name=Breeze gtk-font-name=Sans 11 gtk-cursor-theme-name=Kaela-Kovalskia-v2 gtk-cursor-theme-size=24 gtk-decoration-layout=icon:minimize,maximize,close gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR gtk-menu-images=1 gtk-enable-event-sounds=1 gtk-enable-input-feedback-sounds=0 gtk-xft-antialias=1 gtk-xft-hinting=1 gtk-xft-hintstyle=hintsmedium gtk-xft-rgba=rgb gtk-application-prefer-dark-theme=1 ================================================ FILE: .config/gtk-4.0/settings.ini ================================================ [Settings] gtk-application-prefer-dark-theme=true gtk-theme-name="Breeze" gtk-icon-theme-name=Breeze gtk-cursor-theme-name=Kaela-Kovalskia-v2 gtk-cursor-theme-size=24 gtk-can-change-accels=1 gtk-xft-antialias=1 gtk-xft-hinting=1 gtk-xft-hintstyle=hintmedium gtk-xft-rgba=rgb ================================================ FILE: .config/htop/htoprc ================================================ # Beware! This file is rewritten by htop when settings are changed in the interface. # The parser is also very primitive, and not human-friendly. htop_version=3.3.0 config_reader_min_version=3 fields=0 48 17 18 38 39 40 2 46 47 49 1 hide_kernel_threads=1 hide_userland_threads=1 hide_running_in_container=1 shadow_other_users=0 show_thread_names=0 show_program_path=1 highlight_base_name=1 highlight_deleted_exe=1 shadow_distribution_path_prefix=0 highlight_megabytes=1 highlight_threads=1 highlight_changes=0 highlight_changes_delay_secs=5 find_comm_in_cmdline=1 strip_exe_from_cmdline=1 show_merged_command=0 header_margin=1 screen_tabs=1 detailed_cpu_time=0 cpu_count_from_one=0 show_cpu_usage=1 show_cpu_frequency=0 show_cpu_temperature=1 degree_fahrenheit=0 update_process_names=0 account_guest_in_cpu_meter=0 color_scheme=0 enable_mouse=1 delay=15 hide_function_bar=0 topology_affinity=0 header_layout=two_50_50 column_meters_0=CPU Memory Swap NetworkIO column_meter_modes_0=1 1 1 2 column_meters_1=Tasks LoadAverage Uptime DiskIO column_meter_modes_1=2 2 2 2 tree_view=0 sort_key=47 tree_sort_key=47 sort_direction=-1 tree_sort_direction=-1 tree_view_always_by_pid=0 all_branches_collapsed=0 screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command .sort_key=PERCENT_MEM .tree_sort_key=PERCENT_MEM .tree_view_always_by_pid=0 .tree_view=0 .sort_direction=-1 .tree_sort_direction=-1 .all_branches_collapsed=0 screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command .sort_key=PID .tree_sort_key=PID .tree_view_always_by_pid=0 .tree_view=0 .sort_direction=1 .tree_sort_direction=1 .all_branches_collapsed=0 ================================================ FILE: .config/mimeapps.list ================================================ [Added Associations] image/gif=video.desktop; application/zip=lxqt-archiver.desktop; application/x-zerosize=text.desktop; application/x-trash=text.desktop; inode/symlink=text.desktop; application/xml=nvim.desktop; application/x-executable=nvim.desktop; image/webp=img.desktop; image/png=img.desktop; image/jpg=img.desktop; image/jpeg=img.desktop; [Default Applications] text/*=text.desktop; application/x-shellscript=text.desktop; application/octet-stream=text.desktop; application/x-wine-extension-ini=text.desktop; image/*=img.desktop; video/*=video.desktop; audio/*=video.desktop; x-scheme-handler/magnet=torrent.desktop; application/x-bittorrent=torrent.desktop; x-scheme-handler/mailto=mail.desktop; application/postscript=pdf.desktop; application/pdf=pdf.desktop; application/rss+xml=rss.desktop; x-scheme-handler/lbry=lbry.desktop; inode/directory=file.desktop; application/xml=nvim.desktop; x-scheme-handler/http=browser.desktop x-scheme-handler/https=browser.desktop x-scheme-handler/about=browser.desktop; x-scheme-handler/unknown=browser.desktop; text/html=browser.desktop ================================================ FILE: .config/mpv/input.conf ================================================ Ctrl+Shift+R write-watch-later-config ; loadfile ${path} F10 cycle_values video-rotate 90 180 270 0 F11 cycle-values loop-playlist yes no F12 playlist-shuffle ; show-text "${playlist}" 4000 Alt+P script-message save-playlist ================================================ FILE: .config/mpv/mpv.conf ================================================ # general hwdec=auto-safe hwdec-codecs=all deband=no interpolation=no vd-lavc-dr=yes drag-and-drop=append input-ipc-server=/tmp/mpvsocket screenshot-directory=pictures # window geometry=50%:50% autofit-larger=60%x60% autofit-smaller=60%x60% # video control keep-open=yes pause=yes volume=50 # cache cache=yes demuxer-max-bytes=20480KiB # youtube-dl ytdl-format=best[height<=?480]+bestaudio/best ytdl-raw-options=no-check-certificate= # osd osd-playing-msg = '${filename}' [protocol.https] osd-playing-msg = '${media-title}' term-playing-msg='$(media-title)' ================================================ FILE: .config/mpv/script-modules/user-input-module.lua ================================================ --[[ This is a module designed to interface with mpv-user-input https://github.com/CogentRedTester/mpv-user-input Loading this script as a module will return a table with two functions to format requests to get and cancel user-input requests. See the README for details. Alternatively, developers can just paste these functions directly into their script, however this is not recommended as there is no guarantee that the formatting of these requests will remain the same for future versions of user-input. ]] local API_VERSION = "0.1.0" local mp = require 'mp' local msg = require "mp.msg" local utils = require 'mp.utils' local mod = {} local name = mp.get_script_name() local counter = 1 local function pack(...) local t = {...} t.n = select("#", ...) return t end local request_mt = {} -- ensures the option tables are correctly formatted based on the input local function format_options(options, response_string) return { response = response_string, version = API_VERSION, id = name..'/'..(options.id or ""), source = name, request_text = ("[%s] %s"):format(options.source or name, options.request_text or options.text or "requesting user input:"), default_input = options.default_input, cursor_pos = tonumber(options.cursor_pos), queueable = options.queueable and true, replace = options.replace and true } end -- cancels the request function request_mt:cancel() assert(self.uid, "request object missing UID") mp.commandv("script-message-to", "user_input", "cancel-user-input/uid", self.uid) end -- updates the options for the request function request_mt:update(options) assert(self.uid, "request object missing UID") options = utils.format_json( format_options(options) ) mp.commandv("script-message-to", "user_input", "update-user-input/uid", self.uid, options) end -- sends a request to ask the user for input using formatted options provided -- creates a script message to recieve the response and call fn function mod.get_user_input(fn, options, ...) options = options or {} local response_string = name.."/__user_input_request/"..counter counter = counter + 1 local request = { uid = response_string, passthrough_args = pack(...), callback = fn, pending = true } -- create a callback for user-input to respond to mp.register_script_message(response_string, function(response) mp.unregister_script_message(response_string) request.pending = false response = utils.parse_json(response) request.callback(response.line, response.err, unpack(request.passthrough_args, 1, request.passthrough_args.n)) end) -- send the input command options = utils.format_json( format_options(options, response_string) ) mp.commandv("script-message-to", "user_input", "request-user-input", options) return setmetatable(request, { __index = request_mt }) end -- runs the request synchronously using coroutines -- takes the option table and an optional coroutine resume function function mod.get_user_input_co(options, co_resume) local co, main = coroutine.running() assert(not main and co, "get_user_input_co must be run from within a coroutine") local uid = {} local request = mod.get_user_input(function(line, err) if co_resume then co_resume(uid, line, err) else local success, er = coroutine.resume(co, uid, line, err) if not success then msg.warn(debug.traceback(co)) msg.error(er) end end end, options) -- if the uid was not sent then the coroutine was resumed by the user. -- we will treat this as a cancellation request local success, line, err = coroutine.yield(request) if success ~= uid then request:cancel() request.callback = function() end return nil, "cancelled" end return line, err end -- sends a request to cancel all input requests with the given id function mod.cancel_user_input(id) id = name .. '/' .. (id or "") mp.commandv("script-message-to", "user_input", "cancel-user-input/id", id) end return mod ================================================ FILE: .config/mpv/scripts/delete-current-video.lua ================================================ local utils = require 'mp.utils' function delete_current_file() local file_path = mp.get_property("path") if file_path == nil then mp.msg.error("No file is currently loaded.") return end local args = {"rm", file_path} local res = utils.subprocess({ args = args, cancellable = false }) if res.status == 0 then mp.msg.info("Deleted file: " .. file_path) -- Move to the next file in the playlist mp.command("playlist-next") else mp.msg.error("Failed to delete file: " .. file_path) end end mp.register_command("delete-current", delete_current_file, "Delete the currently playing file.") ================================================ FILE: .config/mpv/scripts/keep-session.lua ================================================ --[[ This script automatically saves the current playlist and can reload it if the player is started in idle mode (specifically if there are 0 files in the playlist), or if the correct command is sent via script-messages. It remembers the playlist position the player was in when shutdown and reloads the playlist at that entry. This can be disabled with script-opts The script saves a text file containing the previous session playlist in the watch_later directory (changeable via opts) This file is saved in plaintext with the exact file paths of each playlist entry. Note that since it uses the same file, only the latest mpv window to be closed will be saved The script attempts to correct relative playlist paths using the utils.join_path function. I've tried to automatically detect when any non-files are loaded (if it has the sequence :// in the path), so that it'll work with URLs You can disable the automatic stuff and use script messages to load/save playlists as well script-message save-session [session-file] script-message reload-session [session-file] [load_playlist] If not included `session-file` will use the default file specified in script-opts. `load_playlist` controls whether the whole playlist should be restored or just the one file, the value can be `yes` or `no`. If not included it defaults to the value of the `load_playlist` script opt. available at: https://github.com/CogentRedTester/mpv-scripts ]]-- local mp = require 'mp' local utils = require 'mp.utils' local opt = require 'mp.options' local msg = require 'mp.msg' local o = { --automatically save the prev session auto_save = true, --runs the script automatically when started in idle mode and no files are in the playlist auto_load = true, --reloads the full playlist from the previous session --can be individually overwritten when sending script-messages load_playlist = true, --file path of the default session file --save it as a .pls file to be able to open directly (though it will not maintain the playlist positions) session_file = "", --maintain position in the playlist --does nothing if load_playlist is disabled maintain_pos = true, } opt.read_options(o, 'keep_session', function() end) --sets the default session file to the watch_later directory or ~~/watch_later/ if o.session_file == "" then local watch_later = mp.get_property('watch-later-directory', "") if watch_later == "" then watch_later = "~~state/watch_later/" end if not watch_later:find("[/\\]$") then watch_later = watch_later..'/' end o.session_file = watch_later.."prev-session" end local save_file = mp.command_native({"expand-path", o.session_file}) --saves the current playlist as a json string local function save_playlist(file) if not file then file = save_file end msg.verbose('saving current session to', file) local playlist = mp.get_property_native('playlist') if #playlist == 0 then msg.verbose('session empty, aborting save') return end local session = io.open(file, 'w') if not session then return msg.error("Failed to write to file", file) end session:write("[playlist]\n") session:write(mp.get_property('playlist-pos') .. "\n") local working_directory = mp.get_property('working-directory') for _, v in ipairs(playlist) do msg.debug('adding ' .. v.filename .. ' to playlist') --if the file is available then it attempts to expand the path in-case of relative playlists --presumably if the file contains a protocol then it shouldn't be expanded if not v.filename:find("^%a*://") then v.filename = utils.join_path(working_directory, v.filename) msg.debug('expanded path: ' .. v.filename) end session:write("File=" .. v.filename .. "\n") end session:close() end --turns the previous json string into a table and adds all the files to the playlist local function load_prev_session(file, load_playlist) if not file or file == '' then file = save_file end if load_playlist == 'yes' then load_playlist = true elseif load_playlist == 'no' then load_playlist = false else load_playlist = o.load_playlist end --loads the previous session file msg.verbose('loading previous session from', file) local session = io.open(file, "r+") --this should only occur when loading the script for the first time, --or if someone manually deletes the previous session file if session == nil or session:read() ~= "[playlist]" then msg.verbose('no previous session, cancelling load') if session then session:close() end return end local previous_playlist_pos = session:read('*n') if load_playlist then msg.debug('reloading playlist') if not o.maintain_pos then mp.commandv('loadlist', file) else local prev_playlist_start = mp.get_property('playlist-start') msg.verbose("restoring playlist position", previous_playlist_pos) mp.set_property_number('playlist-start', previous_playlist_pos) mp.commandv('loadlist', file) -- restore the original value unless the `playlist-start` property has been otherwise modified if mp.get_property_number('playlist-start') ~= previous_playlist_pos then mp.set_property('playlist-start', prev_playlist_start) end end else msg.debug('discarding playlist') local files = {} for line in session:lines() do table.insert(files, string.match(line, 'File=(.+)')) end -- mpv and keep-session uses 0 based array indices, but lua uses 1-based mp.commandv('loadfile', files[previous_playlist_pos+1]) end session:close() end local function shutdown() if o.auto_save then save_playlist() end end mp.register_script_message('save-session', save_playlist) mp.register_script_message('reload-session', load_prev_session) mp.register_event('shutdown', shutdown) --Load the previous session if auto_load is enabled and the playlist is empty --the function is not called until the first property observation is triggered to let everything initialise --otherwise modifying playlist-start becomes unreliable if o.auto_load and (mp.get_property_number('playlist-count', 0) == 0) then local function temp() load_prev_session() mp.unobserve_property(temp) end mp.observe_property("idle", "string", temp) end ================================================ FILE: .config/mpv/scripts/mpv-scut.lua ================================================ local start_time = nil local segments = {} local osd_message_id = nil local osd_persistent = false local segments_file_path = nil -- Get the path for the segments file based on the video file name function getSegmentsFilePath() local input_file = mp.get_property("path") input_file = mp.command_native({"expand-path", input_file}) local file_dir = input_file:match("(.*/)") local file_name = input_file:match("([^/]+)%.%w+$") return string.format("%s/%s_segments.txt", file_dir, file_name) end -- Start segment at the current playback position function startSegment() start_time = mp.get_property_number("time-pos") osd_persistent = true osd_message_id = mp.osd_message("Segment start point set") end -- End segment at the current playback position function endSegment() local end_time = mp.get_property_number("time-pos") if start_time then table.insert(segments, {start = start_time, stop = end_time}) start_time = nil osd_persistent = true osd_message_id = mp.osd_message("Segment end point set") else osd_persistent = false osd_message_id = mp.osd_message("No start point set") end end -- Save segments to file function saveSegmentsToFile() if #segments == 0 then osd_persistent = false osd_message_id = mp.osd_message("No segments to save") return end segments_file_path = getSegmentsFilePath() local segments_file = io.open(segments_file_path, "w") if not segments_file then osd_persistent = false osd_message_id = mp.osd_message("Failed to create segments file") return end for _, segment in ipairs(segments) do segments_file:write(string.format("%s,%s\n", segment.start, segment.stop)) end segments_file:close() osd_persistent = true osd_message_id = mp.osd_message("Segments saved to file") end -- Load segments from file function loadSegmentsFromFile() segments_file_path = getSegmentsFilePath() local segments_file = io.open(segments_file_path, "r") if not segments_file then osd_persistent = false osd_message_id = mp.osd_message("Failed to read segments file") return end segments = {} for line in segments_file:lines() do local start, stop = line:match("([^,]+),([^,]+)") table.insert(segments, {start = tonumber(start), stop = tonumber(stop)}) end segments_file:close() end -- Process segments (cut and merge) function processSegments() if #segments == 0 then osd_persistent = false osd_message_id = mp.osd_message("No segments to process") return end saveSegmentsToFile() local input_file = mp.get_property("path") input_file = mp.command_native({"expand-path", input_file}) local file_dir = input_file:match("(.*/)") local file_name = input_file:match("([^/]+)%.%w+$") if not file_dir or not file_name then osd_persistent = false osd_message_id = mp.osd_message("Failed to determine video directory or file name") return end for i, segment in ipairs(segments) do local segment_file = string.format("%s/%s_segment_%d.mp4", file_dir, file_name, i) local command = string.format('ffmpeg -i "%s" -ss %s -to %s -c copy "%s"', input_file, segment.start, segment.stop, segment_file) print("Executing command:", command) os.execute(command) end local concat_file_path = string.format("%s/%s_concat.txt", file_dir, file_name) local concat_file = io.open(concat_file_path, "w") if not concat_file then osd_persistent = false osd_message_id = mp.osd_message("Failed to create concat file") return end for i, _ in ipairs(segments) do local segment_file = string.format("%s_segment_%d.mp4", file_name, i) concat_file:write(string.format("file '%s'\n", segment_file)) end concat_file:close() local output_file = string.format("%s/%s_merged.mp4", file_dir, file_name) local concat_command = string.format('ffmpeg -f concat -safe 0 -i "%s" -c copy "%s"', concat_file_path, output_file) print("Executing concat command:", concat_command) osd_persistent = true osd_message_id = mp.osd_message("Merging segments...") os.execute(concat_command) osd_message_id = mp.osd_message("Segments merged") os.remove(concat_file_path) for i, _ in ipairs(segments) do local segment_file = string.format("%s/%s_segment_%d.mp4", file_dir, file_name, i) os.remove(segment_file) end osd_persistent = false osd_message_id = mp.osd_message("Segments processed, temporary files deleted") end -- Retry processing segments using the segments file function retryProcessSegments() loadSegmentsFromFile() processSegments() end -- Update OSD message if persistent function updateOSDMessage(message) if osd_persistent then osd_message_id = mp.osd_message(message, osd_message_id) end end -- Key bindings mp.add_key_binding("c", "start_segment", startSegment) mp.add_key_binding("x", "end_segment", endSegment) mp.add_key_binding("z", "process_segments", processSegments) mp.add_key_binding("r", "retry_process_segments", retryProcessSegments) mp.add_key_binding("s", "save_segments_to_file", saveSegmentsToFile) -- Clear OSD on shutdown mp.register_event("shutdown", function() if osd_message_id then mp.osd_message("") end end) -- Periodic OSD update mp.add_periodic_timer(0.5, function() if osd_persistent and start_time then updateOSDMessage("Segment in progress...") end end) ================================================ FILE: .config/mpv/scripts/mpv-splice.lua ================================================ -- ----------------------------------------------------------------------------- -- -- MPV Splice -- URL: https://github.com/pvpscript/mpv-video-splice -- -- Requires: ffmpeg -- -- Description: -- -- This script provides the hability to create video slices by grabbing two -- timestamps, which generate a slice from timestamp A[i] to timestamp B[i], -- e.g.: -- -> Slice 1: 00:10:34.25 -> 00:15:00.00. -- -> Slice 2: 00:23:00.84 -> 00:24:10.00. -- ... -- -> Slice n: 01:44:22.47 -> 01:56:00.00. -- -- Then, all the slices from 1 to n are joined together, creating a new -- video. -- -- The output file will appear at the directory that the mpv command was ran, -- or in the environment variable set for it (see Environment variables below) -- -- Note: This script prevents the mpv player from closing when the video ends, -- so that the slices don't get lost. Keep this in mind if there's the option -- 'keep-open=no' in the current config file. -- -- Note: This script will also silence the terminal, so the script messages -- can be seen more clearly. -- -- ----------------------------------------------------------------------------- -- -- -- Usage: -- -- In the video screen, press Alt + T to grab the first timestamp and then -- press Alt + T again to get the second timestamp. This process will generate -- a time range, which represents a video slice. Repeat this process to create -- more slices. -- -- To see all the slices made, press Alt + P. All of the slices will appear -- in the terminal in order of creation, with their corresponding timestamps. -- Incomplete slices will show up as 'Slice N in progress', where N is the -- slice number. -- -- To reset an incomplete slice, press Alt + R. If the first part of a slice -- was created at the wrong time, this will reset the current slice. -- -- To delete a whole slice, start the slice deletion mode by pressing Alt + D. -- When in this mode, it's possible to press Alt + NUM, where NUM is any -- number between 0 inclusive and 9 inclusive. For each Alt + NUM pressed, a -- number will be concatenated to make the final number referring to the slice -- to be removed, then press Alt + D again to stop the slicing deletion mode -- and delete the slice corresponding to the formed number. -- -- Example 1: Deleting slice number 3 -- -> Alt + D # Start slice deletion mode -- -> Alt + 3 # Concatenate number 3 -- -> Alt + D # Exit slice deletion mode -- -- Example 2> Deleting slice number 76 -- -> Alt + D # Start slice deletion mode -- -> Alt + 7 # Concatenate number 7 -- -> Alt + 6 # Concatenate number 6 -- -> Alt + D # Exit slice deletion mode -- -- To fire up ffmpeg, which will slice up the video and concatenate the slices -- together, press Alt + C. It's important that there are at least one -- slice, otherwise no video will be created. -- -- Note: No cut will be made unless the user presses Alt + C. -- Also, the original video file won't be affected by the cutting. -- -- -- ----------------------------------------------------------------------------- -- -- -- Log level: -- -- Everytime a timestamp is grabbed, a text will appear on the screen showing -- the selected time. -- When Alt + P is pressed, besides showing the slices in the terminal, -- it will also show on the screen the total number of cuts (or slices) -- that were made. -- When the actual cutting and joining process begins, a message will be shown -- on the screen and the terminal telling that it began. When the process ends, -- a message will appear on the screen and the terminal displaying the full path -- of the generated video. It will also appear a message in the terminal telling -- that the process ended. -- -- Note: Every message that appears on the terminal has the log level of 'info'. -- -- -- ----------------------------------------------------------------------------- -- -- -- Environment Variables: -- -- This script uses environment variables to allow the user to -- set the temporary location of the video cuts and for setting the location for -- the resulting video. -- -- To set the temporary directory, set the variable MPV_SPLICE_TEMP; -- e.g.: export MPV_SPLICE_TEMP="$HOME/temporary_location" -- -- To set the video output directory, set the variable MPV_SPLICE_OUTPUT; -- e.g.: export MPV_SPLICE_OUTPUT="$HOME/output_location" -- -- Make sure the directories set in the variables really exist, or else the -- script might fail. -- -- ----------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Importing the mpv libraries local mp = require 'mp' local msg = require 'mp.msg' local opt = require 'mp.options' local utils = require 'mp.utils' -------------------------------------------------------------------------------- -- Setup os dependent stuff -- Not the best way to check OS, but it should work local _os = package.config:sub(1, 1) == "/" and "unix" or "windows" local _default_output_path = mp.get_property("working-directory") system_dependent = { default_output_path = _os == "unix" and _default_output_path or _default_output_path:gsub("\\", "/"), tmp_path = _os == "unix" and "/tmp" or string.format("%s/Temp", os.getenv("LOCALAPPDATA"):gsub("\\", "/")), mkdir = _os == "unix" and "mkdir" or "md", rm = _os == "unix" and "rm -rf" or "rd /s /q", } -------------------------------------------------------------------------------- -- Setup config local SCRIPT_NAME = "mpv-splice" local config = { concat_file_name = "concat", ffmpeg_cmd = "ffmpeg -hide_banner -loglevel warning", ffmpeg_filter = "-c copy -copyts -avoid_negative_ts make_zero", tmp_path = system_dependent.tmp_path, output_path = system_dependent.default_output_path, } opt.read_options(config, SCRIPT_NAME) -------------------------------------------------------------------------------- local function notify(message, duration) local duration = duration or 2 msg.info(message) mp.osd_message(message, duration) end local function seconds_to_clock(secs) local hours = math.floor(secs / 3600) local mins = math.floor((secs - hours * 3600) / 60) local secs = secs - hours * 3600 - mins * 60 return { h = hours, m = mins, s = secs, } end local function current_timestamp() local seconds = mp.get_property_number('time-pos') local time_data = seconds_to_clock(seconds) return string.format('%02d:%02d:%05.2f', time_data.h, time_data.m, time_data.s) end slice_data = { _start_timestamp_message = "[START TIMESTAMP]", _end_timestamp_message = "[END TIMESTAMP]", _timestamps = {}, _pieces = function(self) return #self._timestamps end, pieces = function(self) return self:_pieces() end, remove = { _ongoing = false, to_be_removed = "", append = function(self, value) self.to_be_removed = self.to_be_removed .. value end, is_ongoing = function(self) return self._ongoing end, is_empty = function(self) return self.to_be_removed == "" end, set_ongoing = function(self) self._ongoing = true end, clear = function(self) self._ongoing = false self.to_be_removed = "" notify("Exited slice deletion mode.") end, }, _pairs = function(self) return math.floor(self:_pieces() / 2) end, _has_incomplete_slice = function(self) return not (self:_pieces() % 2 == 0) end, _put_time = function(self, value) table.insert(self._timestamps, value) end, _add_piece = function(self, timestamp) self:_put_time(timestamp) local message = self:_has_incomplete_slice() and self._start_timestamp_message or self._end_timestamp_message notify(message) end, _as_pairs_coroutine_handler = nil, _as_pairs_coroutine_create = function(self) local function _as_pairs_coroutine_closure(self) local pair = 1 for piece = 1, self:_pieces(), 2 do coroutine.yield({ index = pair, p_start = self._timestamps[piece], p_end = self._timestamps[piece + 1], }) pair = pair + 1 end end self._as_pairs_coroutine_handler = coroutine.create(_as_pairs_coroutine_closure) end, as_pairs = function(self) self:_as_pairs_coroutine_create() return function() local _, ret = coroutine.resume(self._as_pairs_coroutine_handler, self) return ret end end, add_time = function(self) local timestamp = current_timestamp() slice_data:_add_piece(timestamp) end, show_timestamps = function(self) notify(string.format("Total cuts: %d", self:_pairs())) local pair = 1 for piece = 1, self:_pieces(), 2 do local t_start = self._timestamps[piece] local t_end = self._timestamps[piece + 1] msg.info(string.format("Slice %d: %s -> %s", pair, t_start, t_end)) pair = pair + 1 end if self:_has_incomplete_slice() then notify(string.format("Slice %d in progress.", self:_pairs() + 1)) end end, reset_current_slice = function(self) if self:_has_incomplete_slice() then notify(string.format("Slice %d reset.", self:_pairs() + 1)) table.remove(self._timestamps) end end, remove_slice = function(self) local pair_index = tonumber(self.remove.to_be_removed) local piece_index = pair_index * 2 - 1 if pair_index > 0 and pair_index <= self:_pairs() then table.remove(self._timestamps, piece_index) table.remove(self._timestamps, piece_index) notify(string.format("Removed slice %d", pair_index)) end end, add_number_key_bindings = function(self) -- Add shortcut keys to the interval {0..9}. for i = 0, 9, 1 do local key_code = "Alt+" .. i local binding_name = "num_key_" .. i local key_action = function() self.remove:append(i) notify(string.format("Slice to remove: %d", self.remove.to_be_removed), 1) end mp.add_key_binding(key_code, binding_name, key_action) end end, remove_number_key_bindings = function(self) for i = 0, 9, 1 do mp.remove_key_binding("num_key_" .. i) end end, delete_slice = function(self, index) if not self.remove:is_ongoing() then self.remove:set_ongoing() notify("Entered slice deletion mode.") self:add_number_key_bindings() elseif self.remove:is_ongoing() and self.remove:is_empty() then self.remove:clear() else self:remove_number_key_bindings() self:remove_slice() self.remove:clear() end end, } local quit = { _exit_count = 0, prevent_quit = function(self, pieces, name) if pieces > 0 then if self._exit_count >= 1 then mp.command(name) else notify("There are timestamp pieces set. Press again to quit.", 3) self._exit_count = self._exit_count + 1 end else mp.command(name) end end, } local random = { alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", _started = false, -- Better seed randomization _first_startup = function(self) if not self._started then math.randomseed(os.time()) for i = 1, 3, 1 do math.random() end self._started = true end end, random_string = function(self, size) self:_first_startup() local rnd_str = "" for i = 1, size, 1 do local rnd_index = math.floor(math.random() * #self.alphabet + 0.5) rnd_str = rnd_str .. self.alphabet:sub(rnd_index, rnd_index) end return rnd_str end, } concat_file = { _path = nil, _handler = nil, _create_file_path = function(self, tmp_path, name) local name = name or "concat" local file_name = string.format("%s.txt", name) return utils.join_path(tmp_path, file_name) end, get_path = function(self) return self._path end, create = function(self, tmp_path, name) self._path = self:_create_file_path(tmp_path, name) self._handler = io.open(self._path, "w") end, add_file = function(self, path) local path_line = string.format("file '%s'\n", path) self._handler:write(path_line) end, close = function(self) self._handler:close() end, } -------------------------------------------------------------------------------- local function add_time() slice_data:add_time() end local function show_timestamps() slice_data:show_timestamps() end local function reset_current_slice() slice_data:reset_current_slice() end local function delete_slice() slice_data:delete_slice() end -------------------------------------------------------------------------------- local function file_info() local path = mp.get_property('path') local name = mp.get_property('filename') local name_without_ext = mp.get_property('filename/no-ext') local ext = name == name_without_ext and "" or string.gsub(name, '.*%.(.*)$', '%1') return { path = path, full_name = name, name_only = name_without_ext, ext = ext } end local function make_temp_dir(tmp_path) local tmp_path_name = string.format( "%s_%s", "video-splice-tmp", random:random_string(10) ) local full_tmp_path = utils.join_path(tmp_path, tmp_path_name) local mkdir_cmd = string.format( "%s \"%s\" 2>&1", system_dependent.mkdir, full_tmp_path ) local handler = io.popen(mkdir_cmd) local cmd_output = handler:read("*l") handler:close() if cmd_output ~= nil then error(cmd_output) end return full_tmp_path end local function output_file_path(file_name, ext) local random_string = random:random_string(10) local output_file = string.format( "%s_%s_cut.%s", file_name, random_string, ext ) return utils.join_path(config.output_path, output_file) end local function make_cut_path(tmp_path, piece_index, ext) local random_string = random:random_string(10) local file_name = string.format( "slice_%s_%d.%s", random_string, piece_index, ext ) return utils.join_path(tmp_path, file_name) end local function run_ffmpeg_cut(piece, input_file_path, output_cut_path) local cmd = string.format( "%s -ss %s -i \"%s\" -to %s %s %s", config.ffmpeg_cmd, piece.p_start, input_file_path, piece.p_end, config.ffmpeg_filter, output_cut_path ) os.execute(cmd) end local function make_timestamp_cuts(tmp_path, curr_file_path, curr_file_ext) for piece in slice_data:as_pairs() do local cut_path = make_cut_path(tmp_path, piece.index, curr_file_ext) run_ffmpeg_cut(piece, curr_file_path, cut_path) concat_file:add_file(cut_path) end concat_file:close() end local function concat_pieces(cat_file_path, output_file) cmd = string.format( "%s -f concat -safe 0 -i \"%s\" -c copy \"%s\"", config.ffmpeg_cmd, cat_file_path, output_file ) os.execute(cmd) end local function cleanup(path) cmd = string.format( "%s \"%s\"", system_dependent.rm, path ) os.execute(cmd) msg.info(string.format("Directory \"%s\" removed!", path)) end function process_video() local file_info = file_info() local output_file = output_file_path(file_info.name_only, file_info.ext) local tmp_path = make_temp_dir(config.tmp_path) -- Make concat file concat_file:create(tmp_path, config.concat_file_name) notify("Process started!") -- Make timestamp cuts make_timestamp_cuts(tmp_path, file_info.path, file_info.ext) -- Make the concat cmd, using the concat.txt file concat_pieces(concat_file:get_path(), output_file) notify(string.format("File saved as: %s", output_file), 10) msg.info("Process ended!") -- Cleanup cleanup(tmp_path) end mp.set_property("keep-open", "yes") -- Prevent mpv from exiting when the video ends mp.set_property("quiet", "yes") -- Silence terminal. mp.add_key_binding('q', "quit", function() quit:prevent_quit(slice_data:pieces(), "quit") end) mp.add_key_binding('Shift+q', "quit-watch-later", function() quit:prevent_quit(slice_data:pieces(), "quit-watch-later") end) mp.add_key_binding('Alt+t', "put_time", add_time) mp.add_key_binding('Alt+p', "show_times", show_timestamps) mp.add_key_binding('Alt+c', "process_video", process_video) mp.add_key_binding('Alt+r', "reset_current_slice", reset_current_slice) mp.add_key_binding('Alt+d', "delete_slice", delete_slice) ================================================ FILE: .config/mpv/scripts/playlist-shuffle.lua ================================================ --[[ shuffles the playlist and moves the currently playing file to the start of the playlist available at: https://github.com/CogentRedTester/mpv-scripts ]]-- function main() mp.command('playlist-shuffle') local pos = mp.get_property_number('playlist-pos') mp.commandv('playlist-move', pos, 0) mp.osd_message('playlist shuffled') end mp.register_script_message('playlist-shuffle', main) ================================================ FILE: .config/mpv/scripts/save-playlist.lua ================================================ --[[ A script for saving m3u playlists based on mpvs current internal playlist. Users can set the name and directory to save the file in the initial script message, or can enter custom strings in the osd. Available at: https://github.com/CogentRedTester/mpv-scripts To support requesting user input this script requires that the script mpv-user-input be loaded by mpv in the ~~/scripts directory, and that user-input-module is in the ~~/script-modules directory. mpv-user-input is available here: https://github.com/CogentRedTester/mpv-user-input Syntax: script-message save-playlist [directory] [filename] [flags] If the directory and/or filename are missing, or are empty strings, then the user will be prompted for input. The filename will be appended with the .m3u extension. The flags are a string of options Flags: Currently there is only one flag: `relative` When relative is passed to the script the playlist will use paths relative to the saved playlist. This is currently very primitive, and only works with files that are children of the save directory. ]]-- local mp = require "mp" local msg = require "mp.msg" local utils = require "mp.utils" local input = dofile(mp.command_native({"expand-path", "~~/script-modules/user-input-module.lua"})) local working = mp.get_property("working-directory", "") local function save_playlist(directory, name, relative) if not directory or not name then return end directory = mp.command_native({"expand-path", directory}) local path = directory.."/"..name..".m3u" local file = io.open(path, "w") if not file then msg.error("could not open file '"..path.."' for writing") ; return end local playlist = mp.get_property_native("playlist") for _, item in ipairs(playlist) do local path = item.filename if not path:find("^%a+://") then path = utils.join_path(working, path) path = path:gsub("\\", "/") path = path:gsub("/./", "/") if relative then local _, finish = path:find(directory, 1, true) if finish then path = path:sub(finish+1) end end end msg.verbose("wrote", '"'..path..'"', "to playlist") file:write(path.."\n") end msg.info("Saved", #playlist, "files to", '"'..directory..'"') mp.osd_message("Saved "..(#playlist).." files to playlist") file:close() end local function handle_save_request(directory, name, relative) local need_dir = not directory or directory == "" local need_name = not name or name == "" relative = relative == "relative" if need_dir then input.get_user_input(function(res) if not need_name then save_playlist(res, name, relative) else directory = res end end, {id = "dir", text = "Enter save directory:"}) end if need_name then input.get_user_input(function(res) save_playlist(directory, res, relative) end, {id = "name", text = "Enter playlist name:"}) end end mp.add_key_binding("Ctrl+p", "save-playlist", handle_save_request) ================================================ FILE: .config/mpv/scripts/user-input.lua ================================================ local mp = require 'mp' local msg = require 'mp.msg' local utils = require 'mp.utils' local options = require 'mp.options' -- Default options local opts = { -- All drawing is scaled by this value, including the text borders and the -- cursor. Change it if you have a high-DPI display. scale = 1, -- Set the font used for the REPL and the console. This probably doesn't -- have to be a monospaced font. font = "", -- Set the font size used for the REPL and the console. This will be -- multiplied by "scale." font_size = 16, } options.read_options(opts, "user_input") local API_VERSION = "0.1.0" local API_MAJOR_MINOR = API_VERSION:match("%d+%.%d+") local co = nil local queue = {} local active_ids = {} local histories = {} local request = nil local line = '' --[[ The below code is a modified implementation of text input from mpv's console.lua: https://github.com/mpv-player/mpv/blob/7ca14d646c7e405f3fb1e44600e2a67fc4607238/player/lua/console.lua Modifications: removed support for log messages, sending commands, tab complete, help commands removed update timer Changed esc key to call handle_esc function handle_esc and handle_enter now resume the main coroutine with a response table made history specific to request ids localised all functions - reordered some to fit keybindings use new names ]]-- ------------------------------START ORIGINAL MPV CODE----------------------------------- ---------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------- -- Copyright (C) 2019 the mpv developers -- -- Permission to use, copy, modify, and/or distribute this software for any -- purpose with or without fee is hereby granted, provided that the above -- copyright notice and this permission notice appear in all copies. -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. local assdraw = require 'mp.assdraw' local function detect_platform() local o = {} -- Kind of a dumb way of detecting the platform but whatever if mp.get_property_native('options/vo-mmcss-profile', o) ~= o then return 'windows' elseif mp.get_property_native('options/macos-force-dedicated-gpu', o) ~= o then return 'macos' elseif os.getenv('WAYLAND_DISPLAY') then return 'wayland' end return 'x11' end -- Pick a better default font for Windows and macOS local platform = detect_platform() if platform == 'windows' then opts.font = 'Consolas' elseif platform == 'macos' then opts.font = 'Menlo' else opts.font = 'monospace' end local repl_active = false local insert_mode = false local cursor = 1 local key_bindings = {} local global_margin_y = 0 -- Escape a string for verbatim display on the OSD local function ass_escape(str) -- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if -- it isn't followed by a recognised character, so add a zero-width -- non-breaking space str = str:gsub('\\', '\\\239\187\191') str = str:gsub('{', '\\{') str = str:gsub('}', '\\}') -- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of -- consecutive newlines str = str:gsub('\n', '\239\187\191\\N') -- Turn leading spaces into hard spaces to prevent ASS from stripping them str = str:gsub('\\N ', '\\N\\h') str = str:gsub('^ ', '\\h') return str end -- Render the REPL and console as an ASS OSD local function update() local dpi_scale = mp.get_property_native("display-hidpi-scale", 1.0) dpi_scale = dpi_scale * opts.scale local screenx, screeny, aspect = mp.get_osd_size() screenx = screenx / dpi_scale screeny = screeny / dpi_scale -- Clear the OSD if the REPL is not active if not repl_active then mp.set_osd_ass(screenx, screeny, '') return end local ass = assdraw.ass_new() local style = '{\\r' .. '\\1a&H00&\\3a&H00&\\4a&H99&' .. '\\1c&Heeeeee&\\3c&H111111&\\4c&H000000&' .. '\\fn' .. opts.font .. '\\fs' .. opts.font_size .. '\\bord1\\xshad0\\yshad1\\fsp0\\q1}' local queue_style = '{\\r' .. '\\1a&H00&\\3a&H00&\\4a&H99&' .. '\\1c&Heeeeee&\\3c&H111111&\\4c&H000000&' .. '\\fn' .. opts.font .. '\\fs' .. opts.font_size .. '\\c&H66ccff&' .. '\\bord1\\xshad0\\yshad1\\fsp0\\q1}' -- Create the cursor glyph as an ASS drawing. ASS will draw the cursor -- inline with the surrounding text, but it sets the advance to the width -- of the drawing. So the cursor doesn't affect layout too much, make it as -- thin as possible and make it appear to be 1px wide by giving it 0.5px -- horizontal borders. local cheight = opts.font_size * 8 local cglyph = '{\\r' .. '\\1a&H44&\\3a&H44&\\4a&H99&' .. '\\1c&Heeeeee&\\3c&Heeeeee&\\4c&H000000&' .. '\\xbord0.5\\ybord0\\xshad0\\yshad1\\p4\\pbo24}' .. 'm 0 0 l 1 0 l 1 ' .. cheight .. ' l 0 ' .. cheight .. '{\\p0}' local before_cur = ass_escape(line:sub(1, cursor - 1)) local after_cur = ass_escape(line:sub(cursor)) ass:new_event() ass:an(1) ass:pos(2, screeny - 2 - global_margin_y * screeny) if (#queue == 2) then ass:append(queue_style .. string.format("There is 1 more request queued\\N")) elseif (#queue > 2) then ass:append(queue_style .. string.format("There are %d more requests queued\\N", #queue-1)) end ass:append(style .. request.text .. '\\N') ass:append('> ' .. before_cur) ass:append(cglyph) ass:append(style .. after_cur) -- Redraw the cursor with the REPL text invisible. This will make the -- cursor appear in front of the text. ass:new_event() ass:an(1) ass:pos(2, screeny - 2) ass:append(style .. '{\\alpha&HFF&}> ' .. before_cur) ass:append(cglyph) ass:append(style .. '{\\alpha&HFF&}' .. after_cur) mp.set_osd_ass(screenx, screeny, ass.text) end -- Naive helper function to find the next UTF-8 character in 'str' after 'pos' -- by skipping continuation bytes. Assumes 'str' contains valid UTF-8. local function next_utf8(str, pos) if pos > str:len() then return pos end repeat pos = pos + 1 until pos > str:len() or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf return pos end -- As above, but finds the previous UTF-8 charcter in 'str' before 'pos' local function prev_utf8(str, pos) if pos <= 1 then return pos end repeat pos = pos - 1 until pos <= 1 or str:byte(pos) < 0x80 or str:byte(pos) > 0xbf return pos end -- Insert a character at the current cursor position (any_unicode) local function handle_char_input(c) if insert_mode then line = line:sub(1, cursor - 1) .. c .. line:sub(next_utf8(line, cursor)) else line = line:sub(1, cursor - 1) .. c .. line:sub(cursor) end cursor = cursor + #c update() end -- Remove the character behind the cursor (Backspace) local function handle_backspace() if cursor <= 1 then return end local prev = prev_utf8(line, cursor) line = line:sub(1, prev - 1) .. line:sub(cursor) cursor = prev update() end -- Remove the character in front of the cursor (Del) local function handle_del() if cursor > line:len() then return end line = line:sub(1, cursor - 1) .. line:sub(next_utf8(line, cursor)) update() end -- Toggle insert mode (Ins) local function handle_ins() insert_mode = not insert_mode end -- Move the cursor to the next character (Right) local function next_char(amount) cursor = next_utf8(line, cursor) update() end -- Move the cursor to the previous character (Left) local function prev_char(amount) cursor = prev_utf8(line, cursor) update() end -- Clear the current line (Ctrl+C) local function clear() line = '' cursor = 1 insert_mode = false request.history.pos = #request.history.list + 1 update() end -- Close the REPL if the current line is empty, otherwise do nothing (Ctrl+D) local function maybe_exit() if line == '' then else handle_del() end end local function handle_esc() coroutine.resume(co, { line = nil, err = "exited" }) end -- Run the current command and clear the line (Enter) local function handle_enter() if request.history.list[#request.history.list] ~= line and line ~= "" then request.history.list[#request.history.list + 1] = line end coroutine.resume(co, { line = line }) end -- Go to the specified position in the command history local function go_history(new_pos) local old_pos = request.history.pos request.history.pos = new_pos -- Restrict the position to a legal value if request.history.pos > #request.history.list + 1 then request.history.pos = #request.history.list + 1 elseif request.history.pos < 1 then request.history.pos = 1 end -- Do nothing if the history position didn't actually change if request.history.pos == old_pos then return end -- If the user was editing a non-history line, save it as the last history -- entry. This makes it much less frustrating to accidentally hit Up/Down -- while editing a line. if old_pos == #request.history.list + 1 and line ~= '' and request.history.list[#request.history.list] ~= line then request.history.list[#request.history.list + 1] = line end -- Now show the history line (or a blank line for #history + 1) if request.history.pos <= #request.history.list then line = request.history.list[request.history.pos] else line = '' end cursor = line:len() + 1 insert_mode = false update() end -- Go to the specified relative position in the command history (Up, Down) local function move_history(amount) go_history(request.history.pos + amount) end -- Go to the first command in the command history (PgUp) local function handle_pgup() go_history(1) end -- Stop browsing history and start editing a blank line (PgDown) local function handle_pgdown() go_history(#request.history.list + 1) end -- Move to the start of the current word, or if already at the start, the start -- of the previous word. (Ctrl+Left) local function prev_word() -- This is basically the same as next_word() but backwards, so reverse the -- string in order to do a "backwards" find. This wouldn't be as annoying -- to do if Lua didn't insist on 1-based indexing. cursor = line:len() - select(2, line:reverse():find('%s*[^%s]*', line:len() - cursor + 2)) + 1 update() end -- Move to the end of the current word, or if already at the end, the end of -- the next word. (Ctrl+Right) local function next_word() cursor = select(2, line:find('%s*[^%s]*', cursor)) + 1 update() end -- Move the cursor to the beginning of the line (HOME) local function go_home() cursor = 1 update() end -- Move the cursor to the end of the line (END) local function go_end() cursor = line:len() + 1 update() end -- Delete from the cursor to the beginning of the word (Ctrl+Backspace) local function del_word() local before_cur = line:sub(1, cursor - 1) local after_cur = line:sub(cursor) before_cur = before_cur:gsub('[^%s]+%s*$', '', 1) line = before_cur .. after_cur cursor = before_cur:len() + 1 update() end -- Delete from the cursor to the end of the word (Ctrl+Del) local function del_next_word() if cursor > line:len() then return end local before_cur = line:sub(1, cursor - 1) local after_cur = line:sub(cursor) after_cur = after_cur:gsub('^%s*[^%s]+', '', 1) line = before_cur .. after_cur update() end -- Delete from the cursor to the end of the line (Ctrl+K) local function del_to_eol() line = line:sub(1, cursor - 1) update() end -- Delete from the cursor back to the start of the line (Ctrl+U) local function del_to_start() line = line:sub(cursor) cursor = 1 update() end -- Returns a string of UTF-8 text from the clipboard (or the primary selection) local function get_clipboard(clip) if platform == 'x11' then local res = utils.subprocess({ args = { 'xclip', '-selection', clip and 'clipboard' or 'primary', '-out' }, playback_only = false, }) if not res.error then return res.stdout end elseif platform == 'wayland' then local res = utils.subprocess({ args = { 'wl-paste', clip and '-n' or '-np' }, playback_only = false, }) if not res.error then return res.stdout end elseif platform == 'windows' then local res = utils.subprocess({ args = { 'powershell', '-NoProfile', '-Command', [[& { Trap { Write-Error -ErrorRecord $_ Exit 1 } $clip = "" if (Get-Command "Get-Clipboard" -errorAction SilentlyContinue) { $clip = Get-Clipboard -Raw -Format Text -TextFormatType UnicodeText } else { Add-Type -AssemblyName PresentationCore $clip = [Windows.Clipboard]::GetText() } $clip = $clip -Replace "`r","" $u8clip = [System.Text.Encoding]::UTF8.GetBytes($clip) [Console]::OpenStandardOutput().Write($u8clip, 0, $u8clip.Length) }]] }, playback_only = false, }) if not res.error then return res.stdout end elseif platform == 'macos' then local res = utils.subprocess({ args = { 'pbpaste' }, playback_only = false, }) if not res.error then return res.stdout end end return '' end -- Paste text from the window-system's clipboard. 'clip' determines whether the -- clipboard or the primary selection buffer is used (on X11 and Wayland only.) local function paste(clip) local text = get_clipboard(clip) local before_cur = line:sub(1, cursor - 1) local after_cur = line:sub(cursor) line = before_cur .. text .. after_cur cursor = cursor + text:len() update() end -- List of input bindings. This is a weird mashup between common GUI text-input -- bindings and readline bindings. local function get_bindings() local bindings = { { 'esc', handle_esc }, { 'enter', handle_enter }, { 'kp_enter', handle_enter }, { 'shift+enter', function() handle_char_input('\n') end }, { 'ctrl+j', handle_enter }, { 'ctrl+m', handle_enter }, { 'bs', handle_backspace }, { 'shift+bs', handle_backspace }, { 'ctrl+h', handle_backspace }, { 'del', handle_del }, { 'shift+del', handle_del }, { 'ins', handle_ins }, { 'shift+ins', function() paste(false) end }, { 'mbtn_mid', function() paste(false) end }, { 'left', function() prev_char() end }, { 'ctrl+b', function() prev_char() end }, { 'right', function() next_char() end }, { 'ctrl+f', function() next_char() end }, { 'up', function() move_history(-1) end }, { 'ctrl+p', function() move_history(-1) end }, { 'wheel_up', function() move_history(-1) end }, { 'down', function() move_history(1) end }, { 'ctrl+n', function() move_history(1) end }, { 'wheel_down', function() move_history(1) end }, { 'wheel_left', function() end }, { 'wheel_right', function() end }, { 'ctrl+left', prev_word }, { 'alt+b', prev_word }, { 'ctrl+right', next_word }, { 'alt+f', next_word }, { 'ctrl+a', go_home }, { 'home', go_home }, { 'ctrl+e', go_end }, { 'end', go_end }, { 'pgup', handle_pgup }, { 'pgdwn', handle_pgdown }, { 'ctrl+c', clear }, { 'ctrl+d', maybe_exit }, { 'ctrl+k', del_to_eol }, { 'ctrl+u', del_to_start }, { 'ctrl+v', function() paste(true) end }, { 'meta+v', function() paste(true) end }, { 'ctrl+bs', del_word }, { 'ctrl+w', del_word }, { 'ctrl+del', del_next_word }, { 'alt+d', del_next_word }, { 'kp_dec', function() handle_char_input('.') end }, } for i = 0, 9 do bindings[#bindings + 1] = {'kp' .. i, function() handle_char_input('' .. i) end} end return bindings end local function text_input(info) if info.key_text and (info.event == "press" or info.event == "down" or info.event == "repeat") then handle_char_input(info.key_text) end end local function define_key_bindings() if #key_bindings > 0 then return end for _, bind in ipairs(get_bindings()) do -- Generate arbitrary name for removing the bindings later. local name = "_userinput_" .. bind[1] key_bindings[#key_bindings + 1] = name mp.add_forced_key_binding(bind[1], name, bind[2], {repeatable = true}) end mp.add_forced_key_binding("any_unicode", "_userinput_text", text_input, {repeatable = true, complex = true}) key_bindings[#key_bindings + 1] = "_userinput_text" end local function undefine_key_bindings() for _, name in ipairs(key_bindings) do mp.remove_key_binding(name) end key_bindings = {} end -- Set the REPL visibility ("enable", Esc) local function set_active(active) if active == repl_active then return end if active then repl_active = true insert_mode = false define_key_bindings() else clear() repl_active = false undefine_key_bindings() collectgarbage() end update() end mp.observe_property("user-data/osc/margins", "native", function(_, val) if val then global_margins = val else global_margins = { t = 0, b = 0 } end update() end) -- Redraw the REPL when the OSD size changes. This is needed because the -- PlayRes of the OSD will need to be adjusted. mp.observe_property('osd-width', 'native', update) mp.observe_property('osd-height', 'native', update) mp.observe_property('display-hidpi-scale', 'native', update) ---------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------- -------------------------------END ORIGINAL MPV CODE------------------------------------ --[[ sends a response to the original script in the form of a json string it is expected that all requests get a response, if the input is nil then err should say why current error codes are: exited the user closed the input instead of pressing Enter already_queued a request with the specified id was already in the queue cancelled a script cancelled the request replace replaced by another request ]] local function send_response(res) if res.source then mp.commandv("script-message-to", res.source, res.response, (utils.format_json(res))) else mp.commandv("script-message", res.response, (utils.format_json(res))) end end -- push new request onto the queue -- if a request with the same id already exists and the queueable flag is not enabled then -- a nil result will be returned to the function function push_request(req) if active_ids[req.id] then if req.replace then for i, q_req in ipairs(queue) do if q_req.id == req.id then send_response{ err = "replaced", response = q_req.response, source = q_req.source } queue[i] = req if i == 1 then request = req end end end update() return end if not req.queueable then send_response{ err = "already_queued", response = req.response, source = req.source } return end end table.insert(queue, req) active_ids[req.id] = (active_ids[req.id] or 0) + 1 if #queue == 1 then coroutine.resume(co) end update() end -- safely removes an item from the queue and updates the set of active requests function remove_request(index) local req = table.remove(queue, index) active_ids[req.id] = active_ids[req.id] - 1 if active_ids[req.id] == 0 then active_ids[req.id] = nil end return req end --an infinite loop that moves through the request queue --uses a coroutine to handle asynchronous operations local function driver() while (true) do while queue[1] do request = queue[1] line = request.default_input cursor = request.cursor_pos if repl_active then update() else set_active(true) end res = coroutine.yield() if res then res.source, res.response = request.source, request.response send_response(res) remove_request(1) end end set_active(false) coroutine.yield() end end co = coroutine.create(driver) --cancels any input request that returns true for the given predicate function local function cancel_input_request(pred) for i = #queue, 1, -1 do if pred(i) then req = remove_request(i) send_response{ err = "cancelled", response = req.response, source = req.source } --if we're removing the first item then that means the coroutine is waiting for a response --we will need to tell the coroutine to resume, upon which it will move to the next request --if there is something in the buffer then save it to the history before erasing it if i == 1 then local old_line = line if old_line ~= "" then table.insert(histories[req.id].list, old_line) end clear() coroutine.resume(co) end end end end mp.register_script_message("cancel-user-input/uid", function(uid) cancel_input_request(function(i) return queue[i].response == uid end) end) -- removes all requests with the specified id from the queue mp.register_script_message("cancel-user-input/id", function(id) cancel_input_request(function(i) return queue[i].id == id end) end) -- ensures a request has the correct fields and is correctly formatted local function format_request_fields(req) assert(req.version, "input requests require an API version string") if not string.find(req.version, API_MAJOR_MINOR, 1, true) then error(("input request has invalid version: expected %s.x, got %s"):format(API_MAJOR_MINOR, req.version)) end assert(req.response, "input requests require a response string") assert(req.id, "input requests require an id string") req.text = ass_escape(req.request_text or "") req.default_input = req.default_input or "" req.cursor_pos = tonumber(req.cursor_pos) or 1 req.id = req.id or "mpv" if req.cursor_pos ~= 1 then if req.cursor_pos < 1 then req.cursor_pos = 1 elseif req.cursor_pos > #req.default_input then req.cursor_pos = #req.default_input + 1 end end if not histories[req.id] then histories[req.id] = {pos = 1, list = {}} end req.history = histories[req.id] return req end -- updates the fields of a specific request mp.register_script_message("update-user-input/uid", function(uid, req_opts) req_opts = utils.parse_json(req_opts) req_opts.response = uid for i, req in ipairs(queue) do if req.response == uid then local success, result = pcall(format_request_fields, req_opts) if not success then return msg.error(result) end queue[i] = result if i == 1 then request = queue[1] end update() return end end end) --the function that parses the input requests local function input_request(req) req = format_request_fields(req) push_request(req) end -- script message to recieve input requests, get-user-input.lua acts as an interface to call this script message mp.register_script_message("request-user-input", function(req) msg.debug(req) req = utils.parse_json(req) local success, err = pcall(input_request, req) if not success then send_response{ err = err, response = req.response, source = req.source} msg.error(err) end end) ================================================ FILE: .config/nano/nanorc ================================================ ## Sample initialization file for GNU nano. ## ## For the options that take parameters, the default value is shown. ## Other options are unset by default. To make sure that an option ## is disabled, you can use "unset