diff --git a/sway/.config/sway/scripts/smart-term.sh b/sway/.config/sway/scripts/smart-term.sh index 50677a0..32975ea 100755 --- a/sway/.config/sway/scripts/smart-term.sh +++ b/sway/.config/sway/scripts/smart-term.sh @@ -1,25 +1,109 @@ #!/bin/bash # Opens a new terminal, using the current terminal's working directory if focused window is a terminal +# Defaults to home directory (~) if no terminal is focused + +# Parse file URI to extract path +parse_file_uri() { + local uri="$1" + + # Remove file:// prefix + local path="${uri#file://}" + + # Handle localhost or hostname prefix: file://hostname/path -> /path + if [[ "$path" =~ ^localhost(/.*) ]] || [[ "$path" =~ ^[a-zA-Z0-9.-]+(/.*) ]]; then + path="${BASH_REMATCH[1]}" + fi + + echo "$path" +} + +# Try to get cwd from focused wezterm window +# Arguments: window_title from Sway's focused window +get_wezterm_cwd() { + local sway_window_title="$1" + + # Check if wezterm is available + if ! command -v wezterm &> /dev/null; then + return 1 + fi + + # Get list of wezterm windows/panes + local wezterm_data + wezterm_data=$(wezterm cli list --format json 2>/dev/null) || return 1 + + # Return early if no data + if [ -z "$wezterm_data" ]; then + return 1 + fi + + local cwd + + # Try to match the Sway window title with wezterm's window_title first + # (this handles windows with explicit titles set) + if [ -n "$sway_window_title" ] && [ "$sway_window_title" != "null" ]; then + cwd=$(echo "$wezterm_data" | jq -r --arg title "$sway_window_title" '.[] | select(.window_title == $title) | .cwd' | head -n 1) + fi + + # If no match by window_title, try matching by pane title + # When multiple matches exist, pick the highest window_id (most recent) + if [ -z "$cwd" ] || [ "$cwd" = "null" ]; then + cwd=$(echo "$wezterm_data" | jq -r --arg title "$sway_window_title" '[.[] | select(.title == $title)] | sort_by(.window_id) | .[-1] | .cwd' 2>/dev/null) + fi + + # If the Sway window title looks like an app (nvim, vim, pi, claude, etc), + # look for the pane with a visible cursor (likely the active app) + if [ -z "$cwd" ] || [ "$cwd" = "null" ]; then + local app_pattern="nvim|vim|pi|claude|less|more|man|htop|top|nano|emacs" + if [[ "$sway_window_title" =~ ^($app_pattern) ]]; then + # Try to find a pane with visible cursor (most likely the active one) + cwd=$(echo "$wezterm_data" | jq -r '.[] | select(.cursor_visibility == "Visible") | .cwd' | head -n 1) + fi + fi + + # Final fallback: just get most recent pane with valid cwd + if [ -z "$cwd" ] || [ "$cwd" = "null" ]; then + cwd=$(echo "$wezterm_data" | jq -r '[.[] | select(.cwd != null and .cwd != "")] | sort_by(.window_id) | .[-1] | .cwd' 2>/dev/null) + fi + + # If still nothing, fail + if [ -z "$cwd" ] || [ "$cwd" = "null" ]; then + return 1 + fi + + # Parse the URI if needed + if [[ "$cwd" == file://* ]]; then + cwd=$(parse_file_uri "$cwd") + fi + + # Verify path exists + if [ -d "$cwd" ]; then + echo "$cwd" + return 0 + fi + + return 1 +} + +# Main logic +cwd="" # Get focused window info from Sway -focused_info=$(swaymsg -t get_tree | jq -r '.. | select(.focused? == true) | {app_id: .app_id, name: .name}') -app_id=$(echo "$focused_info" | jq -r '.app_id') -window_name=$(echo "$focused_info" | jq -r '.name') - -if [ "$app_id" = "org.wezfurlong.wezterm" ]; then - # Match the Sway window title with wezterm's window_title to get the correct pane's cwd - cwd=$(wezterm cli list --format json 2>/dev/null | jq -r --arg title "$window_name" '.[] | select(.window_title == $title) | .cwd' | head -n 1) - - if [ -n "$cwd" ] && [ "$cwd" != "null" ]; then - # Remove file:// prefix and hostname (format: file://hostname/path) - cwd=$(echo "$cwd" | sed 's|^file://[^/]*/|/|') - - if [ -d "$cwd" ]; then - wezterm start --cwd "$cwd" & - exit 0 - fi +if command -v swaymsg &> /dev/null; then + focused_window=$(swaymsg -t get_tree 2>/dev/null | jq -r '.. | select(.focused? == true and .app_id? != null) | [.app_id, .name] | @tsv' | head -n 1) + + # Parse tab-separated values + app_id=$(echo "$focused_window" | cut -f1) + window_name=$(echo "$focused_window" | cut -f2) + + # Check if focused window is wezterm (app_id contains "wez") + if [ -n "$app_id" ] && [[ "$app_id" == *"wez"* ]]; then + cwd=$(get_wezterm_cwd "$window_name") fi fi -# Fallback: open terminal in home directory -wezterm & +# Open terminal with cwd if we found one, otherwise default to home +if [ -n "$cwd" ] && [ -d "$cwd" ]; then + wezterm start --cwd "$cwd" & +else + wezterm start --cwd "$HOME" & +fi