diff --git a/scripts/.local/bin/0x0 b/scripts/.local/bin/0x0

new file mode 100755

index 0000000000000000000000000000000000000000..a9726984aaf9d8671759db4f26a66d7530508a32

--- /dev/null

+++ b/scripts/.local/bin/0x0

@@ -0,0 +1,22 @@

+#!/bin/sh

+# Original repository

+# https://git.lapacz-kornel.dev/dotfiles

+

+filename=$1

+

+if [ -z "$filename" ]; then

+ echo "usage: 0x0 filename"

+ exit 1

+fi

+

+if [ ! -f "$filename" ]; then

+ echo "file $filename doesn't exist"

+ exit 1

+fi

+

+url=$(curl -F"file=@$filename" https://0x0.st)

+

+[ -z "$url" ] && exit 1

+

+echo "$url"

+echo "$url" | xclip -selection clipboard

diff --git a/scripts/.local/bin/barhide b/scripts/.local/bin/barhide

new file mode 100755

index 0000000000000000000000000000000000000000..46a53062ff29cb578e171e0035aae96ddaf6effe

--- /dev/null

+++ b/scripts/.local/bin/barhide

@@ -0,0 +1,9 @@

+#!/bin/sh

+

+id=$(xdo id -N "Polybar")

+

+if xprop -id $id | grep -q "Normal"; then

+ xdo hide -N "Polybar"

+ else

+ xdo show -N "Polybar"

+fi

diff --git a/scripts/.local/bin/dmenu_run_history b/scripts/.local/bin/dmenu_run_history

new file mode 100755

index 0000000000000000000000000000000000000000..8d436cada6df2b00fd7a270034feab8e199a9e95

--- /dev/null

+++ b/scripts/.local/bin/dmenu_run_history

@@ -0,0 +1,50 @@

+#!/bin/sh

+

+cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}

+if [ -d "$cachedir" ]; then

+ cache=$cachedir/dmenu_run

+ historyfile=$cachedir/dmenu_history

+else # if no xdg dir, fall back to dotfiles in ~

+ cache=$HOME/.dmenu_cache

+ historyfile=$HOME/.dmenu_history

+fi

+

+IFS=:

+if stest -dqr -n "$cache" $PATH; then

+ stest -flx $PATH | sort -u > "$cache"

+fi

+unset IFS

+

+awk -v histfile=$historyfile '

+ BEGIN {

+ while( (getline < histfile) > 0 ) {

+ sub("^[0-9]+\t","")

+ print

+ x[$0]=1

+ }

+ } !x[$0]++ ' "$cache" \

+ | dmenu "$@" \

+ | awk -v histfile=$historyfile '

+ BEGIN {

+ FS=OFS="\t"

+ while ( (getline < histfile) > 0 ) {

+ count=$1

+ sub("^[0-9]+\t","")

+ fname=$0

+ history[fname]=count

+ }

+ close(histfile)

+ }

+

+ {

+ history[$0]++

+ print

+ }

+

+ END {

+ if(!NR) exit

+ for (f in history)

+ print history[f],f | "sort -t '\t' -k1rn >" histfile

+ }

+ ' \

+ | while read cmd; do ${SHELL:-"/bin/sh"} -c "$cmd" & done

diff --git a/scripts/.local/bin/gcat b/scripts/.local/bin/gcat

new file mode 100755

index 0000000000000000000000000000000000000000..702da2f3210dbfcc532e039b590e3fa68e40f4e9

--- /dev/null

+++ b/scripts/.local/bin/gcat

@@ -0,0 +1,72 @@

+#!/usr/bin/env python3

+

+import cgi

+import os

+import socket

+import ssl

+import sys

+import urllib.parse

+

+def absolutise_url(base, relative):

+ # Absolutise relative links

+ if "://" not in relative:

+ # Python's URL tools somehow only work with known schemes?

+ base = base.replace("gemini://","http://")

+ relative = urllib.parse.urljoin(base, relative)

+ relative = relative.replace("http://", "gemini://")

+ return relative

+

+if len(sys.argv) != 2:

+ print("Usage:")

+ print("gcat gemini://gemini.circumlunar.space")

+ sys.exit(1)

+

+url = sys.argv[1]

+parsed_url = urllib.parse.urlparse(url)

+if parsed_url.scheme == "":

+ url = "gemini://"+url

+ parsed_url = urllib.parse.urlparse(url)

+

+if parsed_url.scheme != "gemini":

+ print("Sorry, Gemini links only.")

+ sys.exit(1)

+if parsed_url.port is not None:

+ useport = parsed_url.port

+else:

+ useport = 1965

+# Do the Gemini transaction

+while True:

+ s = socket.create_connection((parsed_url.hostname, useport))

+ context = ssl.SSLContext()

+ context.check_hostname = False

+ context.verify_mode = ssl.CERT_NONE

+ s = context.wrap_socket(s, server_hostname = parsed_url.netloc)

+ s.sendall((url + '\r\n').encode("UTF-8"))

+ # Get header and check for redirects

+ fp = s.makefile("rb")

+ header = fp.readline()

+ print(header.decode("UTF-8"), end="")

+ header = header.decode("UTF-8").strip()

+ status, mime = header.split()[:2]

+ # Handle input requests

+ if status.startswith("1"):

+ # Prompt

+ query = input("INPUT" + mime + "> ")

+ url += "?" + urllib.parse.quote(query) # Bit lazy...

+ # Follow redirects

+ elif status.startswith("3"):

+ url = absolutise_url(url, mime)

+ parsed_url = urllib.parse.urlparse(url)

+ # Otherwise, we're done.

+ else:

+ break

+# Fail if transaction was not successful

+if status.startswith("2"):

+ if mime.startswith("text/"):

+ # Decode according to declared charset

+ mime, mime_opts = cgi.parse_header(mime)

+ body = fp.read()

+ body = body.decode(mime_opts.get("charset","UTF-8"))

+ print(body, end="")

+ else:

+ print(fp.read(), end="")

diff --git a/scripts/.local/bin/md2gemini b/scripts/.local/bin/md2gemini

new file mode 100755

index 0000000000000000000000000000000000000000..f9c3f494acc6aa0f5dcf30222bd3cb5911638f5c

--- /dev/null

+++ b/scripts/.local/bin/md2gemini

@@ -0,0 +1,8 @@

+#!/usr/bin/python

+# -*- coding: utf-8 -*-

+import re

+import sys

+from md2gemini import main

+if __name__ == '__main__':

+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)? , '', sys.argv[0])

+ sys.exit(main())

diff --git a/scripts/.local/bin/rofi-files b/scripts/.local/bin/rofi-files

new file mode 100755

index 0000000000000000000000000000000000000000..0d7ec5c292335687be72059a27cc49a03e1b471b

--- /dev/null

+++ b/scripts/.local/bin/rofi-files

@@ -0,0 +1,20 @@

+#!/usr/bin/python

+

+import subprocess

+

+if __name__ == '__main__':

+

+ files = subprocess.run('fd', encoding='utf-8',

+ capture_output=True).stdout.split('\n')

+

+ title = 'rofi-files'

+ rofi_command = 'rofi -dmenu -i -p {}'.format(title)

+ rofi_input = '\n'.join(file for file in files)

+ cp = subprocess.run(rofi_command.split(), input=rofi_input,

+ encoding='utf-8', capture_output=True)

+

+ if cp.returncode == 0:

+ file = cp.stdout.strip()

+ xdg_command = ['xdg-open', file]

+ subprocess.run(xdg_command,

+ encoding='utf-8', capture_output=True)

diff --git a/scripts/.local/bin/sway-launcher-desktop.sh b/scripts/.local/bin/sway-launcher-desktop.sh

new file mode 100755

index 0000000000000000000000000000000000000000..6da01011775d9b4b846b327082a299a2a3397cd7

--- /dev/null

+++ b/scripts/.local/bin/sway-launcher-desktop.sh

@@ -0,0 +1,321 @@

+#!/usr/bin/env bash

+# terminal application launcher for sway, using fzf

+# Based on: https://gitlab.com/FlyingWombat/my-scripts/blob/master/sway-launcher

+# https://gist.github.com/Biont/40ef59652acf3673520c7a03c9f22d2a

+shopt -s nullglob globstar

+set -o pipefail

+if ! { exec 0>&3; } 1>/dev/null 2>&1; then

+ exec 3>/dev/null # If file descriptor 3 is unused in parent shell, output to /dev/null

+fi

+# shellcheck disable=SC2154

+trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR

+IFS= \n\t'

+DEL= \34'

+

+TERMINAL_COMMAND="${TERMINAL_COMMAND:="$TERM -e"}"

+GLYPH_COMMAND="${GLYPH_COMMAND- }"

+GLYPH_DESKTOP="${GLYPH_DESKTOP- }"

+CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/sway-launcher-desktop"

+PROVIDERS_FILE="${PROVIDERS_FILE:=providers.conf}"

+if [[ "${PROVIDERS_FILE#/}" == "${PROVIDERS_FILE}" ]]; then

+ # $PROVIDERS_FILE is a relative path, prepend $CONFIG_DIR

+ PROVIDERS_FILE="${CONFIG_DIR}/${PROVIDERS_FILE}"

+fi

+

+# Provider config entries are separated by the field separator \034 and have the following structure:

+# list_cmd,preview_cmd,launch_cmd

+declare -A PROVIDERS

+if [ -f "${PROVIDERS_FILE}" ]; then

+ eval "$(awk -F= '

+ BEGINFILE{ provider=""; }

+ /^\[.*\]/{sub("^\\[", "");sub("\\]$", "");provider=$0}

+ /^(launch|list|preview)_cmd/{st = index($0,"=");providers[provider][$1] = substr($0,st+1)}

+ ENDFILE{

+ for (key in providers){

+ if(!("list_cmd" in providers[key])){continue;}

+ if(!("launch_cmd" in providers[key])){continue;}

+ if(!("preview_cmd" in providers[key])){continue;}

+ for (entry in providers[key]){

+ gsub(/[\x27,\047]/,"\x27\"\x27\"\x27", providers[key][entry])

+ }

+ print "PROVIDERS[\x27" key "\x27]=\x27" providers[key]["list_cmd"] "\034" providers[key]["preview_cmd"] "\034" providers[key]["launch_cmd"] "\x27\n"

+ }

+ }' "${PROVIDERS_FILE}")"

+ if [[ ! -v HIST_FILE ]]; then

+ HIST_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/${0##*/}-${PROVIDERS_FILE##*/}-history.txt"

+ fi

+else

+ PROVIDERS['desktop']="${0} list-entries${DEL}${0} describe-desktop \"{1}\"${DEL}${0} run-desktop '{1}' {2}"

+ PROVIDERS['command']="${0} list-commands${DEL}${0} describe-command \"{1}\"${DEL}${TERMINAL_COMMAND} {1}"

+ if [[ ! -v HIST_FILE ]]; then

+ HIST_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/${0##*/}-history.txt"

+ fi

+fi

+PROVIDERS['user']="exit${DEL}exit${DEL}{1}" # Fallback provider that simply executes the exact command if there were no matches

+

+if [[ -n "${HIST_FILE}" ]]; then

+ mkdir -p "${HIST_FILE%/*}" && touch "$HIST_FILE"

+ readarray HIST_LINES <"$HIST_FILE"

+fi

+

+function describe() {

+ # shellcheck disable=SC2086

+ readarray -d ${DEL} -t PROVIDER_ARGS <<<${PROVIDERS[${1}]}

+ # shellcheck disable=SC2086

+ [ -n "${PROVIDER_ARGS[1]}" ] && eval "${PROVIDER_ARGS[1]//\{1\}/${2}}"

+}

+function describe-desktop() {

+ description=$(sed -ne '/^Comment=/{s/^Comment=//;p;q}' "$1")

+ echo -e "\033[33m$(sed -ne '/^Name=/{s/^Name=//;p;q}' "$1")\033[0m"

+ echo "${description:-No description}"

+}

+function describe-command() {

+ readarray arr < <(whatis -l "$1" 2>/dev/null)

+ description="${arr[0]}"

+ description="${description#* - }"

+ echo -e "\033[33m${1}\033[0m"

+ echo "${description:-No description}"

+}

+

+function provide() {

+ # shellcheck disable=SC2086

+ readarray -d ${DEL} -t PROVIDER_ARGS <<<${PROVIDERS[$1]}

+ eval "${PROVIDER_ARGS[0]}"

+}

+function list-commands() {

+ IFS=: read -ra path <<<"$PATH"

+ for dir in "${path[@]}"; do

+ printf '%s\n' "$dir/"* |

+ awk -F / -v pre="$GLYPH_COMMAND" '{print $NF "\034command\034\033[31m" pre "\033[0m" $NF;}'

+ done | sort -u

+}

+function list-entries() {

+ # Get locations of desktop application folders according to spec

+ # https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

+ IFS=':' read -ra DIRS <<<"${XDG_DATA_HOME-${HOME}/.local/share}:${XDG_DATA_DIRS-/usr/local/share:/usr/share}"

+ for i in "${!DIRS[@]}"; do

+ if [[ ! -d "${DIRS[i]}" ]]; then

+ unset -v 'DIRS[$i]'

+ else

+ DIRS[$i]="${DIRS[i]}/applications/**/*.desktop"

+ fi

+ done

+ # shellcheck disable=SC2068

+ entries ${DIRS[@]}

+}

+function entries() {

+ # shellcheck disable=SC2068

+ awk -v pre="$GLYPH_DESKTOP" -F= '

+ function desktopFileID(filename){

+ sub("^.*applications/", "", filename);

+ sub("/", "-", filename);

+ return filename

+ }

+ BEGINFILE{

+ application=0;

+ block="";

+ a=0

+

+ id=desktopFileID(FILENAME)

+ if(id in fileIds){

+ nextfile;

+ }else{

+ fileIds[id]=0

+ }

+ }

+ /^\[Desktop Entry\]/{block="entry"}

+ /^Type=Application/{application=1}

+ /^\[Desktop Action/{

+ sub("^\\[Desktop Action ", "");

+ sub("\\]$", "");

+ block="action";

+ a++;

+ actions[a,"key"]=$0

+ }

+ /^\[X-/{

+ sub("^\\[X-", "");

+ sub("\\]$", "");

+ block="action";

+ a++;

+ actions[a,"key"]=$0

+ }

+ /^Name=/{ (block=="action")? actions[a,"name"]=$2 : name=$2 }

+ ENDFILE{

+ if (application){

+ print FILENAME "\034desktop\034\033[33m" pre name "\033[0m";

+ if (a>0)

+ for (i=1; i<=a; i++)

+ print FILENAME "\034desktop\034\033[33m" pre name "\033[0m (" actions[i, "name"] ")\034" actions[i, "key"]

+ }

+ }' \

+ $@ </dev/null

+ # the empty stdin is needed in case no *.desktop files

+}

+function run-desktop() {

+ CMD="$("${0}" generate-command "$@" 2>&3)"

+ echo "Generated Launch command from .desktop file: ${CMD}" >&3

+ bash -c "${CMD}"

+}

+function generate-command() {

+ # Define the search pattern that specifies the block to search for within the .desktop file

+ PATTERN="^\\\\[Desktop Entry\\\\]"

+ if [[ -n $2 ]]; then

+ PATTERN="^\\\\[Desktop Action ${2}\\\\]"

+ fi

+ echo "Searching for pattern: ${PATTERN}" >&3

+ # 1. We see a line starting [Desktop, but we're already searching: deactivate search again

+ # 2. We see the specified pattern: start search

+ # 3. We see an Exec= line during search: remove field codes and set variable

+ # 3. We see a Path= line during search: set variable

+ # 4. Finally, build command line

+ awk -v pattern="${PATTERN}" -v terminal_cmd="${TERMINAL_COMMAND}" -F= '

+ BEGIN{a=0;exec=0;path=0}

+ /^\[Desktop/{

+ if(a){ a=0 }

+ }

+ $0 ~ pattern{ a=1 }

+ /^Terminal=/{

+ sub("^Terminal=", "");

+ if ($0 == "true") { terminal=1 }

+ }

+ /^Exec=/{

+ if(a && !exec){

+ sub("^Exec=", "");

+ gsub(" ?%[cDdFfikmNnUuv]", "");

+ exec=$0;

+ }

+ }

+ /^Path=/{

+ if(a && !path){ path=$2 }

+ }

+ END{

+ if(path){ printf "cd " path " && " }

+ if (terminal){ printf terminal_cmd " " }

+ print exec

+ }' "$1"

+}

+

+function autostart() {

+ for application in $(list-autostart); do

+ (exec setsid /bin/sh -c "$(run-desktop "${application}")" &>/dev/null &)

+ done

+}

+

+function list-autostart() {

+ # Get locations of desktop application folders according to spec

+ # https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

+ IFS=':' read -ra DIRS <<<"${XDG_CONFIG_HOME-${HOME}/.config}:${XDG_CONFIG_DIRS-/etc/xdg}"

+ for i in "${!DIRS[@]}"; do

+ if [[ ! -d "${DIRS[i]}" ]]; then

+ unset -v 'DIRS[$i]'

+ else

+ DIRS[$i]="${DIRS[i]}/autostart/*.desktop"

+ fi

+ done

+

+ # shellcheck disable=SC2068

+ awk -v pre="$GLYPH_DESKTOP" -F= '

+ function desktopFileID(filename){

+ sub("^.*autostart/", "", filename);

+ sub("/", "-", filename);

+ return filename

+ }

+ BEGINFILE{

+ application=0;

+ block="";

+ a=0

+

+ id=desktopFileID(FILENAME)

+ if(id in fileIds){

+ nextfile;

+ }else{

+ fileIds[id]=0

+ }

+ }

+ /^\[Desktop Entry\]/{block="entry"}

+ /^Type=Application/{application=1}

+ /^Name=/{ iname=$2 }

+ ENDFILE{

+ if (application){

+ print FILENAME;

+ }

+ }' \

+ ${DIRS[@]} </dev/null

+}

+

+case "$1" in

+describe | describe-desktop | describe-command | entries | list-entries | list-commands | list-autostart | generate-command | autostart | run-desktop | provide)

+ "$@"

+ exit

+ ;;

+esac

+echo "Starting launcher instance with the following providers:" "${!PROVIDERS[@]}" >&3

+

+FZFPIPE=$(mktemp -u)

+mkfifo "$FZFPIPE"

+trap 'rm "$FZFPIPE"' EXIT INT

+

+# Append Launcher History, removing usage count

+(printf '%s' "${HIST_LINES[@]#* }" >>"$FZFPIPE") &

+

+# Iterate over providers and run their list-command

+for PROVIDER_NAME in "${!PROVIDERS[@]}"; do

+ (bash -c "${0} provide ${PROVIDER_NAME}" >>"$FZFPIPE") &

+done

+

+readarray -t COMMAND_STR <<<$(

+ fzf --ansi +s -x -d '\034' --nth ..3 --with-nth 3 \

+ --print-query \

+ --preview "$0 describe {2} {1}" \

+ --preview-window=up:2:noborder \

+ --no-multi --cycle \

+ --prompt="${GLYPH_PROMPT-# }" \

+ --header='' --no-info --margin='1,2' \

+ --color='16,gutter:-1' \

+ <"$FZFPIPE"

+) || exit 1

+# Get the last line of the fzf output. If there were no matches, it contains the query which we'll treat as a custom command

+# If there were matches, it contains the selected item

+COMMAND_STR=$(printf '%s\n' "${COMMAND_STR[@]: -1}")

+# We still need to format the query to conform to our fallback provider.

+# We check for the presence of field separator character to determine if we're dealing with a custom command

+if [[ $COMMAND_STR != * \034'* ]]; then

+ COMMAND_STR="${COMMAND_STR}" \034user\034'"${COMMAND_STR}" \034'

+ SKIP_HIST=1 # I chose not to include custom commands in the history. If this is a bad idea, open an issue please

+fi

+

+[ -z "$COMMAND_STR" ] && exit 1

+

+if [[ -n "${HIST_FILE}" && ! "$SKIP_HIST" ]]; then

+ # update history

+ for i in "${!HIST_LINES[@]}"; do

+ if [[ "${HIST_LINES[i]}" == *" $COMMAND_STR" \n' ]]; then

+ HIST_COUNT=${HIST_LINES[i]%% *}

+ HIST_LINES[$i]="$((HIST_COUNT + 1)) $COMMAND_STR" \n'

+ match=1

+ break

+ fi

+ done

+ if ! ((match)); then

+ HIST_LINES+=("1 $COMMAND_STR" \n')

+ fi

+

+ printf '%s' "${HIST_LINES[@]}" | sort -nr >"$HIST_FILE"

+fi

+

+# shellcheck disable=SC2086

+readarray -d \034' -t PARAMS <<<${COMMAND_STR}

+# shellcheck disable=SC2086

+readarray -d ${DEL} -t PROVIDER_ARGS <<<${PROVIDERS[${PARAMS[1]}]}

+# Substitute {1}, {2} etc with the correct values

+COMMAND=${PROVIDER_ARGS[2]//\{1\}/${PARAMS[0]}}

+COMMAND=${COMMAND//\{2\}/${PARAMS[3]}}

+COMMAND=${COMMAND%%[[:space:]]}

+

+if [ -t 1 ]; then

+ echo "Launching command: ${COMMAND}" >&3

+ setsid /bin/sh -c "${COMMAND}" >&/dev/null </dev/null &

+ sleep 0.01

+else

+ echo "${COMMAND}"

+fi

diff --git a/scripts/installutilities.sh b/scripts/installutilities.sh

index 77bc0df0054d86f31142508e607c45f58d4aa300..18f8b2820938330ef5e70ec9714b3e885f336111 100755

--- a/scripts/installutilities.sh

+++ b/scripts/installutilities.sh

@@ -1,3 +1,4 @@

#!/bin/sh

sudo pacman -Sy alacritty sway swaylock swaybg swappy slurp swayidle wl-clipboard wlroots grim waybar trash-cli gammastep playerctl zsh powertop android-file-transfer qemu virt-manager git playonlinux udiskie ntfs-3g code breeze-gtk elementary-icon-theme ttf-hack ttf-font-awesome noto-fonts-cjk rsync alsa-lib alsa-oss alsa-utils alsa-tools alsa-utils alsa-firmware alsa-card-profiles lib32-alsa-plugins pulseaudio pulseaudio-alsa pulseaudio-jack fzf php edk2-ovmf firejail youtube-dl light neovim gimp telegram-desktop pcmanfm-gtk3 mpv chromium galculator vifm amfora dunst

+