diff --git a/scripts/bin/lfcleaner b/scripts/bin/lfcleaner new file mode 100755 index 0000000..a9c2523 --- /dev/null +++ b/scripts/bin/lfcleaner @@ -0,0 +1,3 @@ +#!/bin/sh +# Nothing to clean for the previewer above, but lf requires this script. +exit 0 diff --git a/scripts/bin/lfextract b/scripts/bin/lfextract new file mode 100755 index 0000000..1925dd7 --- /dev/null +++ b/scripts/bin/lfextract @@ -0,0 +1,17 @@ +#!/bin/sh + +for file in "$@"; do + case "$file" in + *.tar) tar xvf "$file" ;; + *.tar.gz|*.tgz) tar xzvf "$file" ;; + *.tar.bz2|*.tbz2) tar xjvf "$file" ;; + *.tar.xz|*.txz) tar xJvf "$file" ;; + *.zip) unzip "$file" ;; + *.rar) unrar x "$file" ;; + *.7z) 7z x "$file" ;; + *.gz) gunzip "$file" ;; + *.bz2) bunzip2 "$file" ;; + *.xz) unxz "$file" ;; + *) echo "Unknown archive type: $file" ;; + esac +done diff --git a/scripts/bin/lfpreview b/scripts/bin/lfpreview new file mode 100755 index 0000000..91133af --- /dev/null +++ b/scripts/bin/lfpreview @@ -0,0 +1,30 @@ +#!/bin/sh +file="$1" +w="$2" +h="$3" + +case "$(file -Lb --mime-type "$file")" in + text/*|application/json|application/x-empty|inode/x-empty) + bat --theme="ansi" --color=always --style=numbers --line-range=:500 --terminal-width="$w" "$file" + ;; + image/*) + echo "Image: $file" + ;; + application/pdf) + pdftotext -l 10 -nopgbrk -q "$file" - | fold -s -w "$w" + ;; + application/zip|application/x-tar|application/x-rar|application/x-7z-compressed|application/gzip|application/x-bzip2|application/x-xz) + echo "Archive: $file" + echo + case "$file" in + *.zip) unzip -l "$file" ;; + *.tar|*.tar.*|*.tgz) tar tf "$file" ;; + *.rar) unrar l "$file" ;; + *.7z) 7z l "$file" ;; + *) echo "Archive listing not supported" ;; + esac + ;; + *) + file -Lb "$file" + ;; +esac diff --git a/scripts/bin/spawn-alacritty b/scripts/bin/spawn-alacritty new file mode 100755 index 0000000..697f5ac --- /dev/null +++ b/scripts/bin/spawn-alacritty @@ -0,0 +1,6 @@ +#!/bin/bash + +/usr/bin/alacritty & +sleep 0.1 +# xdotool windowactivate +/home/jason/.local/bin/tile diff --git a/scripts/bin/spawn-browser b/scripts/bin/spawn-browser new file mode 100755 index 0000000..81e695f --- /dev/null +++ b/scripts/bin/spawn-browser @@ -0,0 +1,6 @@ +#!/bin/bash + +/usr/bin/chromium --password-store=basic & +sleep 0.4 +# xdotool windowactivate +/home/jason/.local/bin/tile diff --git a/scripts/bin/tile b/scripts/bin/tile new file mode 100755 index 0000000..95d06cc --- /dev/null +++ b/scripts/bin/tile @@ -0,0 +1,200 @@ +#!/bin/bash +set -e +# --- CONFIG --- +TOP_BAR=36 +DECOR_H=30 +DECOR_W=5 + +MASTER_RATIO_NUM=1 +MASTER_RATIO_DEN=2 + +OUTER_GAP=8 +INNER_GAP=8 + +# Master selection: +# focused = currently focused window +# first = first window on desktop +# last = last window on desktop +MASTER_MODE="focused" + +# ---------------- + +# Get current screen resolution +read SCREEN_W SCREEN_H <<< $(xrandr | awk ' +/\*/ { + split($1,a,"x") + print a[1], a[2] + exit +}') + +USABLE_H=$((SCREEN_H - TOP_BAR)) + +# Work area after outer gaps +WORK_X=$OUTER_GAP +WORK_Y=$((TOP_BAR + OUTER_GAP)) +WORK_W=$((SCREEN_W - 2 * OUTER_GAP)) +WORK_H=$((USABLE_H - 2 * OUTER_GAP)) + +# --- focused window --- +FOCUSED=$(printf "0x%08x" "$(xdotool getactivewindow)") + +# --- current desktop --- +CUR_DESKTOP=$(xdotool get_desktop) + +# --- collect windows on current desktop --- +ALL_WINDOWS=$(wmctrl -l -x | awk '$2!="-1" {print $1}') + +WINDOWS=() + +for w in $ALL_WINDOWS; do + win_desktop=$(xdotool get_desktop_for_window "$(printf "%d" "$w")" 2>/dev/null) || continue + + if [ "$win_desktop" = "$CUR_DESKTOP" ]; then + WINDOWS+=("$w") + fi +done + +if [ ${#WINDOWS[@]} -eq 0 ]; then + echo "No windows found on current desktop." + exit 1 +fi + +# ---------------------------------------------------- +# Determine master window +# ---------------------------------------------------- + +case "$MASTER_MODE" in + focused) + MASTER="$FOCUSED" + ;; + first) + MASTER="${WINDOWS[0]}" + ;; + last) + MASTER="${WINDOWS[$((${#WINDOWS[@]} - 1))]}" + ;; + *) + echo "Invalid MASTER_MODE: $MASTER_MODE" + exit 1 + ;; +esac + +# --- separate master from stack --- +STACK=() + +for w in "${WINDOWS[@]}"; do + if [ "$w" != "$MASTER" ]; then + STACK+=("$w") + fi +done + +place() { + local id=$1 + local x=$2 + local y=$3 + local raw_w=$4 + local raw_h=$5 + local class decor_h decor_w x_offset y_offset + x_offset=0 + y_offset=0 + + class=$(xprop -id "$id" WM_CLASS 2>/dev/null | sed -r 's/.*"(.*)"$/\1/') + case "$class" in + Alacritty) + decor_h=42 + decor_w=8 + ;; + Chromium) + decor_h=42 + decor_w=5 + ;; + obsidian) + decor_h=5 + decor_w=0 + x_offset=-0 + y_offset=-0 + ;; + dev.zed.Zed) + decor_h=-19 + decor_w=-23 + x_offset=-13 + y_offset=-13 + ;; + *) + decor_h=$DECOR_H + decor_w=$DECOR_W + ;; + esac + + local w=$((raw_w - decor_w)) + local h=$((raw_h - decor_h)) + local fx=$((x + x_offset)) + local fy=$((y + y_offset)) + wmctrl -i -r "$id" -b remove,maximized_vert,maximized_horz + wmctrl -i -r "$id" -e 1,"$fx","$fy","$w","$h" +} + +# ---------------------------------------------------- +# Single window +# ---------------------------------------------------- + +if [ ${#WINDOWS[@]} -eq 1 ]; then + place \ + "$MASTER" \ + "$WORK_X" \ + "$WORK_Y" \ + "$WORK_W" \ + "$WORK_H" + + exit 0 +fi + +# ---------------------------------------------------- +# Master / Stack layout +# ---------------------------------------------------- + +MID=$((WORK_W * MASTER_RATIO_NUM / MASTER_RATIO_DEN)) + +MASTER_X=$WORK_X +MASTER_Y=$WORK_Y + +MASTER_W=$((MID - INNER_GAP / 2)) +MASTER_H=$WORK_H + +STACK_X=$((WORK_X + MID + INNER_GAP / 2)) +STACK_Y=$WORK_Y + +STACK_W=$((WORK_W - MID - INNER_GAP / 2)) +STACK_H=$WORK_H + +# --- place master --- +place \ + "$MASTER" \ + "$MASTER_X" \ + "$MASTER_Y" \ + "$MASTER_W" \ + "$MASTER_H" + +# --- place stack --- +COUNT=${#STACK[@]} + +if [ "$COUNT" -gt 0 ]; then + + SLOT_H=$(((STACK_H - INNER_GAP * (COUNT - 1)) / COUNT)) + + i=0 + + for w in "${STACK[@]}"; do + + SLOT_Y=$((STACK_Y + i * (SLOT_H + INNER_GAP))) + + place \ + "$w" \ + "$STACK_X" \ + "$SLOT_Y" \ + "$STACK_W" \ + "$SLOT_H" + + i=$((i + 1)) + done +fi diff --git a/scripts/bin/winselect b/scripts/bin/winselect new file mode 100755 index 0000000..a83f07a --- /dev/null +++ b/scripts/bin/winselect @@ -0,0 +1,78 @@ +#!/bin/bash +# focus-dir.sh - focus the nearest window in a given direction (h/j/k/l) +# Usage: focus-dir.sh h|j|k|l (or left/down/up/right) + +DIR=$1 + +if [ -z "$DIR" ]; then + echo "Usage: $0 h|j|k|l" + exit 1 +fi + +# --- get current desktop --- +CUR_DESKTOP=$(xdotool get_desktop) + +# --- get focused window geometry --- +FOCUSED=$(xdotool getactivewindow) +read -r FX FY FW FH < <(xdotool getwindowgeometry --shell "$FOCUSED" | awk -F= ' + /^X=/ {x=$2} /^Y=/ {y=$2} /^WIDTH=/ {w=$2} /^HEIGHT=/ {h=$2} + END {print x, y, w, h} +') +FCX=$((FX + FW / 2)) +FCY=$((FY + FH / 2)) + +# --- get list of normal windows on current desktop --- +ALL_WINDOWS=$(wmctrl -l -x | awk '$2!="-1" {print $1}') + +BEST="" +BEST_DIST="" + +for w in $ALL_WINDOWS; do + wid=$(printf "%d" "$w") + + [ "$wid" = "$FOCUSED" ] && continue + + win_desktop=$(xdotool get_desktop_for_window "$wid" 2>/dev/null) || continue + [ "$win_desktop" = "$CUR_DESKTOP" ] || continue + + read -r WX WY WW WH < <(xdotool getwindowgeometry --shell "$wid" | awk -F= ' + /^X=/ {x=$2} /^Y=/ {y=$2} /^WIDTH=/ {w=$2} /^HEIGHT=/ {h=$2} + END {print x, y, w, h} + ') + WCX=$((WX + WW / 2)) + WCY=$((WY + WH / 2)) + + DX=$((WCX - FCX)) + DY=$((WCY - FCY)) + + case "$DIR" in + h|left) + [ "$DX" -ge 0 ] && continue + ;; + l|right) + [ "$DX" -le 0 ] && continue + ;; + k|up) + [ "$DY" -ge 0 ] && continue + ;; + j|down) + [ "$DY" -le 0 ] && continue + ;; + *) + echo "Invalid direction: $DIR" + exit 1 + ;; + esac + + # Manhattan distance, weighted to prefer windows roughly in line + DIST=$(( (DX<0?-DX:DX) + (DY<0?-DY:DY) )) + + if [ -z "$BEST_DIST" ] || [ "$DIST" -lt "$BEST_DIST" ]; then + BEST_DIST=$DIST + BEST=$wid + fi +done + +if [ -n "$BEST" ]; then + xdotool windowactivate "$BEST" +fi