aboutsummaryrefslogtreecommitdiff
path: root/dot_zshrc
diff options
context:
space:
mode:
Diffstat (limited to 'dot_zshrc')
0 files changed, 0 insertions, 0 deletions
#!/usr/bin/env bash

set -u

direction="${1:-}"
terminal_pid="${2:-}"

case "$direction" in
  left|right|up|down)
    ;;
  *)
    printf 'usage: %s <left|right|up|down> <terminal-pid>\n' "$0" >&2
    exit 2
    ;;
esac

# Window titles can change with the workspace. Find a foreground Herdr
# process belonging to this terminal instead of relying on its title.
is_in_terminal() {
  local pid="$1"
  local parent

  while [[ "$pid" =~ ^[0-9]+$ && "$pid" -gt 1 ]]; do
    [[ "$pid" == "$terminal_pid" ]] && return 0
    parent="$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d '[:space:]')"
    [[ -n "$parent" && "$parent" != "$pid" ]] || return 1
    pid="$parent"
  done

  return 1
}

herdr_found=false
if [[ "$terminal_pid" =~ ^[0-9]+$ ]]; then
  while read -r pid process_group foreground_group; do
    # The server has no foreground terminal; a suspended client is not active.
    if [[ "$foreground_group" -gt 0 && "$process_group" == "$foreground_group" ]] &&
        is_in_terminal "$pid"; then
      herdr_found=true
      break
    fi
  done < <(ps -C herdr -o pid=,pgid=,tpgid= 2>/dev/null)
fi

if [[ "$herdr_found" != true ]]; then
  printf 'not-herdr\n'
  exit
fi

herdr_bin="${HERDR_BIN_PATH:-$HOME/.local/share/mise/installs/herdr/latest/herdr}"

if [[ ! -x "$herdr_bin" ]]; then
  printf 'hyprland\n'
  exit
fi

handled() {
  printf 'handled\n'
  exit
}

fall_through() {
  printf 'hyprland\n'
  exit
}

current="$("$herdr_bin" pane current --current 2>/dev/null)" || {
  fall_through
}

pane_id="$(jq -r '.result.pane.pane_id // empty' <<<"$current")"

if [[ -z "$pane_id" ]]; then
  fall_through
fi

process_info="$(
  "$herdr_bin" pane process-info --pane "$pane_id" 2>/dev/null || true
)"

nvim_pid="$(
  jq -r '
    [
      (.result.process_info.foreground_processes // [])[]
      | select(
          ((.name // "") | ascii_downcase) == "nvim"
          or ((.name // "") | ascii_downcase) == "vim"
        )
      | .pid
    ][0] // empty
  ' <<<"$process_info" 2>/dev/null
)"

if [[ -n "$nvim_pid" ]]; then
  safe_pane_id="${pane_id//[^a-zA-Z0-9_.-]/_}"
  runtime_dir="${XDG_RUNTIME_DIR:-/tmp}"

  socket_path="$runtime_dir/nvim-hypr-nav-pane-$safe_pane_id.sock"

  response="$(
    printf 'nav:%s\n' "$direction" |
      socat -T 0.25 -,ignoreeof "UNIX-CONNECT:$socket_path" 2>/dev/null ||
      true
  )"

  if [[ "$response" == *success* ]]; then
    handled
  fi
fi

neighbor="$(
  "$herdr_bin" pane neighbor \
    --pane "$pane_id" \
    --direction "$direction" \
    2>/dev/null
)" || {
  fall_through
}

# A zoomed pane deliberately falls through to Hyprland. Do not expose or
# navigate to another Herdr pane.
if jq -e '.result.neighbor.layout.zoomed == true' \
    >/dev/null 2>&1 <<<"$neighbor"; then
  fall_through
fi

neighbor_id="$(
  jq -r '.result.neighbor.neighbor_pane_id // empty' <<<"$neighbor"
)"

# Herdr 0.7.5 returns the current pane itself when there is no neighbour.
if [[ -z "$neighbor_id" || "$neighbor_id" == "$pane_id" ]]; then
  fall_through
fi

if "$herdr_bin" pane focus \
    --pane "$pane_id" \
    --direction "$direction" \
    >/dev/null 2>&1; then
  handled
else
  fall_through
fi