diff --git a/dot_config/herdr/empty_dot_plugins.lock b/dot_config/herdr/empty_dot_plugins.lock deleted file mode 100644 index e69de29..0000000 diff --git a/dot_config/herdr/herdr-client.log b/dot_config/herdr/herdr-client.log deleted file mode 100644 index f9036a6..0000000 --- a/dot_config/herdr/herdr-client.log +++ /dev/null @@ -1,4 +0,0 @@ -2026-07-24T20:15:47.544152Z INFO herdr::logging: herdr starting event="app.startup" subsystem="client" outcome="started" pid=8768 -2026-07-24T20:15:47.544192Z INFO herdr::client: connecting to server path=/Users/zamp/.config/herdr/herdr-client.sock -2026-07-24T20:15:47.774089Z INFO herdr::client: handshake succeeded version=17 encoding=SemanticFrame -2026-07-27T08:17:29.705493Z INFO herdr::logging: herdr exiting event="app.shutdown" subsystem="client" outcome="completed" pid=8768 diff --git a/dot_config/herdr/herdr-server.log b/dot_config/herdr/herdr-server.log deleted file mode 100644 index 1588c09..0000000 --- a/dot_config/herdr/herdr-server.log +++ /dev/null @@ -1,670 +0,0 @@ -2026-07-24T20:15:47.495927Z INFO herdr::platform::macos: raised server file descriptor soft limit previous=256 target=8192 -2026-07-24T20:15:47.496202Z INFO herdr::api::server: api server listening path=/Users/zamp/.config/herdr/herdr.sock -2026-07-24T20:15:47.496722Z INFO herdr::app: using pane scrollback configuration pane_scrollback_limit_bytes=10000000 -2026-07-24T20:15:47.510661Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-24T20:15:47.515100Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=1 rows=24 cols=80 scrollback_limit_bytes=10000000 -2026-07-24T20:15:47.517632Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=1 pid=8794 -2026-07-24T20:15:47.517974Z INFO herdr::logging: workspace created event="workspace.create" subsystem="workspace" outcome="ok" workspace_id="w1" pane_id=1 -2026-07-24T20:15:47.517985Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w1" -2026-07-24T20:15:47.518010Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:15:47.518044Z INFO herdr::server::headless: created startup workspace cwd=/Users/zamp -2026-07-24T20:15:47.518254Z INFO herdr::server::headless: client protocol socket listening path=/Users/zamp/.config/herdr/herdr-client.sock -2026-07-24T20:15:47.518289Z INFO herdr::server::headless: herdr server started api_socket=/Users/zamp/.config/herdr/herdr.sock client_socket=/Users/zamp/.config/herdr/herdr-client.sock -2026-07-24T20:15:47.518602Z INFO herdr::logging: herdr starting event="app.startup" subsystem="server" outcome="started" pid=8769 -2026-07-24T20:15:47.774119Z INFO herdr::server::headless: client connected client_id=2 cols=216 rows=61 cell_width_px=0 cell_height_px=0 render_encoding=SemanticFrame -2026-07-24T20:15:52.523465Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:16:19.387859Z INFO herdr::pane: agent changed pane=1 previous_agent=None agent=Some(Codex) process=codex pgid=Some(9125) -2026-07-24T20:16:24.558399Z INFO herdr::pane: agent changed pane=1 previous_agent=Some(Codex) agent=None pgid=Some(8794) -2026-07-24T20:16:53.702239Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=2 rows=60 cols=190 scrollback_limit_bytes=10000000 -2026-07-24T20:16:53.707432Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=2 pid=9204 -2026-07-24T20:16:53.707741Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:16:58.718080Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:17:00.098164Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=2 status="ExitStatus { code: 0, signal: None }" -2026-07-24T20:17:00.098404Z INFO herdr::pane: pane session terminated pane=2 pid=9204 signal=Hangup -2026-07-24T20:17:05.103386Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:19:32.845531Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=3 rows=60 cols=190 scrollback_limit_bytes=10000000 -2026-07-24T20:19:32.853251Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=3 pid=9357 -2026-07-24T20:19:32.853741Z INFO herdr::logging: workspace created event="workspace.create" subsystem="workspace" outcome="ok" workspace_id="w2" pane_id=3 -2026-07-24T20:19:32.853805Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w2" -2026-07-24T20:19:32.853986Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w2" tab_id="w2:t1" -2026-07-24T20:19:35.669009Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w1" -2026-07-24T20:19:35.669587Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:19:36.322288Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w2" -2026-07-24T20:19:36.322643Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w2" tab_id="w2:t1" -2026-07-24T20:19:36.894143Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w1" -2026-07-24T20:19:36.894634Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:19:40.710704Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w2" -2026-07-24T20:19:40.711158Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w2" tab_id="w2:t1" -2026-07-24T20:19:40.885895Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w2" -2026-07-24T20:19:40.886509Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w2" tab_id="w2:t1" -2026-07-24T20:19:41.652479Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w2" -2026-07-24T20:19:41.652930Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w2" tab_id="w2:t1" -2026-07-24T20:19:44.824051Z INFO herdr::logging: workspace closed event="workspace.close" subsystem="workspace" outcome="ok" workspace_id="w2" -2026-07-24T20:19:44.825788Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=3 status="ExitStatus { code: 1, signal: None }" -2026-07-24T20:19:44.846478Z INFO herdr::pane: pane session terminated pane=3 pid=9357 signal=Hangup -2026-07-24T20:19:44.846780Z WARN herdr::app::actions: PaneDied for unknown pane pane=3 -2026-07-24T20:19:49.853275Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:23:03.120646Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:server:reload-config" method="server.reload_config" changes_ui=true -2026-07-24T20:23:03.121645Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:server:reload-config" method="server.reload_config" -2026-07-24T20:27:56.051742Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=4 rows=61 cols=188 scrollback_limit_bytes=10000000 -2026-07-24T20:27:56.059988Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=4 pid=10184 -2026-07-24T20:27:56.060708Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:01.068501Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:28:03.484689Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:03.484817Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:03.484853Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:03.484898Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:03.854267Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:03.854376Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:03.854411Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:03.854440Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:03.988757Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:03.988858Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:03.988891Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:03.988918Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:04.140185Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:04.140300Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.140337Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.140365Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:04.219212Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:04.219322Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.219353Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.219384Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:04.349179Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:04.349296Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.349332Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.349361Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:04.396051Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:04.396151Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.396179Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.396227Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:04.512651Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:04.512742Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.512771Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.512801Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:04.595812Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:04.595897Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.595931Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.595960Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:04.736016Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:04.736118Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.736151Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:04.736180Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:05.059772Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:05.059874Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:05.059910Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:05.059937Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:05.329296Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:05.329399Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:05.329433Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:05.329460Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:05.572759Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:05.572861Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:05.572894Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:05.572932Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:06.126137Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:06.126241Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:06.126275Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:06.126302Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:06.367841Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:06.367947Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:06.367981Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:06.368007Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:08.880422Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=5 rows=61 cols=94 scrollback_limit_bytes=10000000 -2026-07-24T20:28:08.888439Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=5 pid=10510 -2026-07-24T20:28:08.889393Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t2" -2026-07-24T20:28:10.493117Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:11.439894Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t2" -2026-07-24T20:28:12.083552Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:14.070228Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t2" -2026-07-24T20:28:14.842639Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:16.199704Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:16.199808Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:16.199844Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:16.199875Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:18.846218Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:18.846633Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:18.846675Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:18.846704Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:19.555043Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:19.555154Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:19.555190Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:19.555220Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:19.887077Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:19.887175Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:19.887211Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:19.887240Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:24.892830Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:28:43.487460Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:43.487559Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:43.487593Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:43.487620Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:44.050842Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:44.050945Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.050980Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.051008Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:44.367429Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:44.367515Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.367549Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.367577Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:44.567157Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:44.567267Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.567301Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.567332Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:44.755395Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:44.755487Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.755520Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.755553Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:44.883669Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:44.883761Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.883794Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:44.883821Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:45.109183Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:45.109278Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:45.109314Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:45.109345Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:45.358467Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:45.358568Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:45.358602Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:45.358629Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:47.622638Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=6 rows=60 cols=94 scrollback_limit_bytes=10000000 -2026-07-24T20:28:47.627635Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=6 pid=11042 -2026-07-24T20:28:47.627926Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:51.147656Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=6 status="ExitStatus { code: 1, signal: None }" -2026-07-24T20:28:51.167453Z INFO herdr::pane: pane session terminated pane=6 pid=11042 signal=Hangup -2026-07-24T20:28:51.168762Z WARN herdr::app::actions: PaneDied for unknown pane pane=6 -2026-07-24T20:28:52.245707Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:28:52.245804Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:52.245839Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:28:52.245886Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:28:57.255281Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:29:01.690454Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:29:01.690556Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:29:01.690591Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:29:01.690617Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:29:02.356107Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=4 status="ExitStatus { code: 1, signal: None }" -2026-07-24T20:29:02.378950Z INFO herdr::pane: pane session terminated pane=4 pid=10184 signal=Hangup -2026-07-24T20:29:02.380356Z WARN herdr::app::actions: PaneDied for unknown pane pane=4 -2026-07-24T20:29:07.384503Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:29:08.117360Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w1" -2026-07-24T20:29:08.117845Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:29:08.118208Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t2" -2026-07-24T20:29:08.121378Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=5 status="ExitStatus { code: 1, signal: None }" -2026-07-24T20:29:08.140690Z INFO herdr::pane: pane session terminated pane=5 pid=10510 signal=Hangup -2026-07-24T20:29:08.142026Z WARN herdr::app::actions: PaneDied for unknown pane pane=5 -2026-07-24T20:29:13.144294Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:29:14.368664Z INFO herdr::server::headless: client resize client_id=2 cols=216 rows=63 cell_width_px=0 cell_height_px=0 -2026-07-24T20:29:55.026465Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=7 rows=63 cols=188 scrollback_limit_bytes=10000000 -2026-07-24T20:29:55.034370Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=7 pid=11194 -2026-07-24T20:29:55.035200Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:30:00.260708Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=7 status="ExitStatus { code: 1, signal: None }" -2026-07-24T20:30:00.283775Z INFO herdr::pane: pane session terminated pane=7 pid=11194 signal=Hangup -2026-07-24T20:30:00.285320Z WARN herdr::app::actions: PaneDied for unknown pane pane=7 -2026-07-24T20:30:05.292500Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:37:31.320771Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=8 rows=63 cols=188 scrollback_limit_bytes=10000000 -2026-07-24T20:37:31.323406Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=8 pid=14997 -2026-07-24T20:37:31.323602Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:37:36.330791Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:39:29.429357Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:39:29.429466Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:39:29.429500Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:39:29.429532Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:39:34.437047Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:39:49.443605Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:39:49.443713Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:39:49.443751Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:39:49.443780Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:39:50.986759Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=8 status="ExitStatus { code: 1, signal: None }" -2026-07-24T20:39:51.009203Z INFO herdr::pane: pane session terminated pane=8 pid=14997 signal=Hangup -2026-07-24T20:39:51.010458Z WARN herdr::app::actions: PaneDied for unknown pane pane=8 -2026-07-24T20:39:56.013104Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:45:47.507377Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-24T20:48:10.440858Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=9 rows=63 cols=188 scrollback_limit_bytes=10000000 -2026-07-24T20:48:10.448173Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=9 pid=18572 -2026-07-24T20:48:10.448699Z INFO herdr::logging: tab renamed event="tab.rename" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T20:48:10.448952Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T20:48:15.460482Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:48:16.971538Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:48:21.981885Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:48:25.785934Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=10 rows=62 cols=188 scrollback_limit_bytes=10000000 -2026-07-24T20:48:25.794666Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=10 pid=18695 -2026-07-24T20:48:25.795478Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:48:27.872492Z INFO herdr::pane: agent changed pane=10 previous_agent=None agent=Some(Codex) process=codex pgid=Some(18777) -2026-07-24T20:48:30.805081Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:48:45.389622Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:48:45.389730Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:48:45.389768Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:48:45.389796Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:48:50.398066Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:49:29.975339Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:49:29.975447Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:49:29.975483Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:49:29.975513Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:49:34.981613Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:51:22.915523Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:51:22.915626Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:22.915659Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:22.915691Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:51:23.760451Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:51:23.760555Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:23.760592Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:23.760621Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:51:24.474175Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:51:24.474303Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:24.474344Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:24.474376Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:51:24.979965Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:51:24.980079Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:24.980112Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:51:24.980139Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:51:29.985734Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:57:01.048251Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:57:06.060548Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:57:46.869917Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T20:57:46.870032Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:57:46.870089Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:57:46.870122Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T20:57:51.877083Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T20:57:53.710265Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T20:57:58.719990Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:00:26.212153Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:02:39.786251Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:06:20.511195Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:06:21.779877Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:06:26.789479Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:06:49.204781Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:06:54.213071Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:07:02.222091Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:07:07.230383Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:07:18.660887Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:07:22.499473Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:07:27.332116Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=11 rows=62 cols=212 scrollback_limit_bytes=10000000 -2026-07-24T21:07:27.339837Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=11 pid=20255 -2026-07-24T21:07:27.340448Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:07:32.347272Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:07:43.146396Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:07:44.572325Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:07:44.572390Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:07:44.572399Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:07:44.572426Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:07:49.580441Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:08:14.437071Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:08:15.777810Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:08:15.777886Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:08:15.777902Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:08:15.777937Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:08:20.781601Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:11:07.825989Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:11:11.140914Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:11:11.140989Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:11:11.141005Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:11:11.141033Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:11:16.146935Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:12:09.439364Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:12:14.443736Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:12:18.452091Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:12:20.209770Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:12:25.220470Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:14:02.865464Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:14:07.873823Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:14:37.745692Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:14:37.745757Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:14:37.745767Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:14:37.745797Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:14:42.751030Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:15:47.514610Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-24T21:19:07.660869Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:19:12.668963Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:26:03.469834Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:26:08.480447Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:27:50.532495Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:27:55.544999Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:32:14.768807Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:32:14.768872Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:32:14.768887Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:32:14.768917Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:32:19.777694Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:33:04.426832Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:33:09.439697Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:36:01.598714Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T21:36:06.613697Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:38:49.966643Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:38:51.093872Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:38:51.093930Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:38:51.093942Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:38:51.093969Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:38:56.103494Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:41:27.064655Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:resize" method="pane.resize" changes_ui=true -2026-07-24T21:41:27.064757Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:resize" method="pane.resize" -2026-07-24T21:41:28.837157Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:resize" method="pane.resize" changes_ui=true -2026-07-24T21:41:28.837256Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:resize" method="pane.resize" -2026-07-24T21:41:29.581641Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:41:29.581693Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:41:29.581705Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:41:29.581730Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:41:34.587134Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:43:30.874776Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:43:35.889111Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:45:47.516638Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-24T21:45:54.626666Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:45:54.626748Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:45:54.626762Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:45:54.626793Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:45:59.635321Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:49:08.994570Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:49:08.994650Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:49:08.994679Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:49:08.994712Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:49:14.002985Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:52:13.003183Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:52:13.003242Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:52:13.003253Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:52:13.003277Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:52:18.012305Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:53:26.751038Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:53:26.751109Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:53:26.751124Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:53:26.751152Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:53:31.757250Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T21:57:46.030420Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T21:57:46.030493Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:57:46.030507Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T21:57:46.030537Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T21:57:51.039160Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:01:40.805870Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:01:45.817930Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:01:54.710020Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T22:01:54.710073Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:01:54.710082Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:01:54.710105Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T22:01:59.529421Z INFO herdr::app::actions: copied selection to clipboard -2026-07-24T22:01:59.720718Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:02:00.407938Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:02:05.417311Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:04:30.290820Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:04:35.301373Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:05:06.520174Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T22:05:06.520243Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:05:06.520256Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:05:06.520284Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T22:05:11.530318Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:05:19.850836Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T22:05:24.858198Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:05:32.018640Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:05:37.029531Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:05:48.426692Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T22:05:53.436963Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:06:01.164550Z INFO herdr::app::actions: copied selection to clipboard -2026-07-24T22:06:02.103445Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:06:03.184718Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:06:08.197923Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:07:10.241276Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T22:07:10.241340Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:07:10.241349Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:07:10.241380Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T22:07:15.244260Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:07:33.896022Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-24T22:07:36.790544Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:07:41.800511Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-24T22:09:20.154594Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-24T22:09:20.154659Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:09:20.154669Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-24T22:09:20.154699Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-24T22:09:25.163183Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T03:20:52.664554Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-25T08:33:40.425668Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:33:40.425733Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:33:40.425746Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:33:40.425779Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:33:45.439002Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:34:14.220647Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:34:14.221769Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:34:14.221794Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:34:14.221831Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:34:18.468246Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:34:18.468321Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:34:18.468338Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:34:18.468368Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:34:23.476684Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:35:23.015877Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:35:28.032512Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:37:58.545558Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:38:02.481869Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:38:02.482722Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:38:02.482738Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:38:02.482770Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:38:07.492669Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:38:10.772436Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:38:15.780131Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:41:53.205279Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:41:58.222280Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:42:00.144382Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:42:00.144449Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:42:00.144458Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:42:00.144487Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:42:05.151595Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:47:43.263886Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=12 rows=62 cols=106 scrollback_limit_bytes=10000000 -2026-07-25T08:47:43.269625Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=12 pid=28595 -2026-07-25T08:47:43.269860Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:47:48.277627Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:47:50.558718Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:47:50.558780Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:47:50.558791Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:47:50.558825Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:47:55.564254Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:48:08.070987Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:48:08.071053Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:08.071065Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:08.071093Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:48:09.887251Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:48:09.887303Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:09.887313Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:09.887345Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:48:14.891509Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:48:23.083718Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:48:23.083794Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:23.083809Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:23.083840Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:48:28.089241Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:48:39.175711Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:44.186460Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:48:47.336661Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:52.346317Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:48:59.110141Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:48:59.110210Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:59.110224Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:48:59.110254Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:49:04.117759Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:49:19.315625Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:49:19.315717Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:49:19.315735Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:49:19.315771Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:49:24.322972Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:56:00.518594Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:56:00.518693Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:56:00.518713Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:56:00.518746Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:56:05.523856Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T08:56:13.147947Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-25T08:57:22.557892Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:57:22.557968Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:57:22.557982Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:57:22.558016Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:57:23.381280Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T08:57:23.381337Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:57:23.381347Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T08:57:23.381377Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T08:57:28.384413Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:01:14.040058Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=13 rows=31 cols=106 scrollback_limit_bytes=10000000 -2026-07-25T09:01:14.049736Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=13 pid=29177 -2026-07-25T09:01:14.050307Z INFO herdr::logging: tab renamed event="tab.rename" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:01:14.050404Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:01:17.569986Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:01:21.332959Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=12 status="ExitStatus { code: 1, signal: None }" -2026-07-25T09:01:21.352047Z INFO herdr::pane: pane session terminated pane=12 pid=28595 signal=Hangup -2026-07-25T09:01:21.353403Z WARN herdr::app::actions: PaneDied for unknown pane pane=12 -2026-07-25T09:01:22.456339Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:01:27.464643Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:04:38.947773Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:04:43.958494Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:04:44.920527Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-25T09:04:46.791110Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:04:49.847732Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:04:51.464113Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:04:56.474945Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:05:05.746218Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:05:07.638231Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:05:12.645021Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:06:29.197143Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=14 rows=62 cols=212 scrollback_limit_bytes=10000000 -2026-07-25T09:06:29.204615Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=14 pid=29271 -2026-07-25T09:06:29.205045Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:06:34.210446Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:06:37.525010Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:06:37.525078Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:06:37.525096Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:06:37.525125Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:06:42.533462Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:06:55.876025Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:06:55.876117Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:06:55.876133Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:06:55.876168Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:07:00.881839Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:07:22.906891Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:07:22.906967Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:07:22.906983Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:07:22.907020Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:07:27.910421Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:07:56.330518Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:07:56.330585Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:07:56.330596Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:07:56.330627Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:08:01.340699Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:08:02.853921Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:08:02.853990Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:08:02.854001Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:08:02.854030Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:08:07.862980Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:15:47.482698Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-25T09:15:52.490243Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:17:15.436479Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:17:19.487520Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:17:19.487587Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:17:19.487596Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:17:19.487626Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:17:24.495824Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:19:07.888874Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:19:09.664094Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:19:13.805505Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:19:15.805554Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:19:20.814809Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:19:37.170473Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:19:37.170556Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:19:37.170571Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:19:37.170603Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:19:42.177066Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:22:31.663169Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t3" -2026-07-25T09:22:36.672066Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:23:33.068860Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:23:38.081380Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:26:13.183920Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-25T09:27:18.062214Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:27:23.072259Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:28:02.470711Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:28:07.480177Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:30:03.106417Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:30:03.106487Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:30:03.106502Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:30:03.106528Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:30:05.528427Z INFO herdr::pane: agent changed pane=14 previous_agent=None agent=Some(Codex) process=codex pgid=Some(30779) -2026-07-25T09:30:08.110643Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:30:11.304221Z INFO herdr::pane: agent changed pane=14 previous_agent=Some(Codex) agent=None pgid=Some(29271) -2026-07-25T09:30:15.845291Z INFO herdr::pane: agent changed pane=14 previous_agent=None agent=Some(Codex) process=codex pgid=Some(30989) -2026-07-25T09:31:36.914954Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:31:41.919085Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T09:32:23.005800Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-25T09:32:23.005867Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:32:23.005876Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t4" -2026-07-25T09:32:23.005908Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-25T09:32:24.769763Z INFO herdr::pane: agent changed pane=14 previous_agent=Some(Codex) agent=None pgid=Some(29271) -2026-07-25T09:32:25.294189Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=14 status="ExitStatus { code: 1, signal: None }" -2026-07-25T09:32:25.314788Z INFO herdr::pane: pane session terminated pane=14 pid=29271 signal=Hangup -2026-07-25T09:32:25.316478Z WARN herdr::app::actions: PaneDied for unknown pane pane=14 -2026-07-25T09:32:26.951276Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-25T09:32:31.961966Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-25T10:13:30.232263Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-25T11:16:23.997646Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-25T11:46:24.000054Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-25T12:16:24.002870Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-25T21:27:21.050030Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-26T05:41:02.085859Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-26T21:23:23.272165Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-27T08:17:12.366384Z INFO herdr::logging: api request received event="api.request.start" subsystem="api" outcome="started" request_id="cli:pane:focus" method="pane.focus_direction" changes_ui=true -2026-07-27T08:17:12.366679Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-27T08:17:12.366693Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w1" tab_id="w1:t1" -2026-07-27T08:17:12.366729Z INFO herdr::logging: api request completed event="api.request.complete" subsystem="api" outcome="ok" request_id="cli:pane:focus" method="pane.focus_direction" -2026-07-27T08:17:13.176887Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=10 status="ExitStatus { code: 1, signal: None }" -2026-07-27T08:17:13.195909Z INFO herdr::pane: pane session terminated pane=10 pid=18695 signal=Hangup -2026-07-27T08:17:13.196693Z WARN herdr::app::actions: PaneDied for unknown pane pane=10 -2026-07-27T08:17:14.600139Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=1 status="ExitStatus { code: 1, signal: None }" -2026-07-27T08:17:14.620176Z INFO herdr::pane: pane session terminated pane=1 pid=8794 signal=Hangup -2026-07-27T08:17:14.621568Z WARN herdr::app::actions: PaneDied for unknown pane pane=1 -2026-07-27T08:17:15.556356Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=9 status="ExitStatus { code: 1, signal: None }" -2026-07-27T08:17:15.577929Z INFO herdr::pane: pane session terminated pane=9 pid=18572 signal=Hangup -2026-07-27T08:17:15.579241Z WARN herdr::app::actions: PaneDied for unknown pane pane=9 -2026-07-27T08:17:16.216807Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=11 status="ExitStatus { code: 1, signal: None }" -2026-07-27T08:17:16.238969Z INFO herdr::pane: pane session terminated pane=11 pid=20255 signal=Hangup -2026-07-27T08:17:16.240401Z WARN herdr::app::actions: PaneDied for unknown pane pane=11 -2026-07-27T08:17:16.875575Z INFO herdr::logging: workspace closed event="workspace.close" subsystem="workspace" outcome="ok" workspace_id="w1" -2026-07-27T08:17:16.879383Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=13 status="ExitStatus { code: 1, signal: None }" -2026-07-27T08:17:16.898617Z INFO herdr::pane: pane session terminated pane=13 pid=29177 signal=Hangup -2026-07-27T08:17:16.900560Z WARN herdr::app::actions: PaneDied for unknown pane pane=13 -2026-07-27T08:17:16.900799Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=15 rows=63 cols=212 scrollback_limit_bytes=10000000 -2026-07-27T08:17:16.910328Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=15 pid=37908 -2026-07-27T08:17:16.910899Z INFO herdr::logging: workspace created event="workspace.create" subsystem="workspace" outcome="ok" workspace_id="w3" pane_id=15 -2026-07-27T08:17:16.910964Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w3" -2026-07-27T08:17:16.910994Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w3" tab_id="w3:t1" -2026-07-27T08:17:19.902825Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=15 status="ExitStatus { code: 0, signal: None }" -2026-07-27T08:17:19.903131Z INFO herdr::pane: pane session terminated pane=15 pid=37908 signal=Hangup -2026-07-27T08:17:19.903230Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=16 rows=63 cols=212 scrollback_limit_bytes=10000000 -2026-07-27T08:17:19.906898Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=16 pid=37972 -2026-07-27T08:17:19.907051Z INFO herdr::logging: workspace created event="workspace.create" subsystem="workspace" outcome="ok" workspace_id="w4" pane_id=16 -2026-07-27T08:17:19.907058Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w4" -2026-07-27T08:17:19.907064Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w4" tab_id="w4:t1" -2026-07-27T08:17:21.725815Z INFO herdr::logging: pane child exited event="pane.exit" subsystem="pane" outcome="completed" pane_id=16 status="ExitStatus { code: 0, signal: None }" -2026-07-27T08:17:21.726361Z INFO herdr::pane: pane session terminated pane=16 pid=37972 signal=Hangup -2026-07-27T08:17:21.726515Z INFO herdr::logging: spawning pane terminal event="pane.spawn.start" subsystem="pane" outcome="started" pane_id=17 rows=63 cols=212 scrollback_limit_bytes=10000000 -2026-07-27T08:17:21.732198Z INFO herdr::logging: pane child spawned event="pane.spawned" subsystem="pane" outcome="ok" pane_id=17 pid=38019 -2026-07-27T08:17:21.732424Z INFO herdr::logging: workspace created event="workspace.create" subsystem="workspace" outcome="ok" workspace_id="w5" pane_id=17 -2026-07-27T08:17:21.732435Z INFO herdr::logging: workspace focused event="workspace.focus" subsystem="workspace" outcome="ok" workspace_id="w5" -2026-07-27T08:17:21.732443Z INFO herdr::logging: tab focused event="tab.focus" subsystem="tab" outcome="ok" workspace_id="w5" tab_id="w5:t1" -2026-07-27T08:17:26.742162Z INFO herdr::logging: session saved event="persist.save" subsystem="persist" outcome="ok" path=/Users/zamp/.config/herdr/session.json workspaces=1 -2026-07-27T08:17:29.704424Z INFO herdr::server::headless: client detach requested via keybind client_id=2 -2026-07-27T08:17:29.709419Z INFO herdr::server::headless: client disconnected client_id=2 -2026-07-27T08:22:06.703297Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-27T09:32:36.426244Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-27T10:56:16.883118Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-27T11:26:16.857274Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-27T11:56:16.872766Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-27T12:26:16.877180Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-27T22:00:33.686857Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T07:19:40.075642Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T07:49:40.084916Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T08:19:40.096188Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T08:49:40.089294Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T09:19:40.067308Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T09:49:40.090768Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T10:54:13.991411Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T11:32:26.492804Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T12:02:26.482344Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T12:32:26.474783Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T13:02:26.488631Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T13:32:26.464326Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T14:02:26.496166Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T15:54:34.086319Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T18:11:57.017781Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T18:44:07.003930Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T19:14:06.972607Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T19:44:06.959635Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T20:14:06.999784Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T20:44:07.011166Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" -2026-07-28T21:34:00.934106Z INFO herdr::logging: checking for updates event="update.check.start" subsystem="update" outcome="started" diff --git a/dot_config/herdr/plugins.json b/dot_config/herdr/plugins.json deleted file mode 100644 index 31d5f40..0000000 --- a/dot_config/herdr/plugins.json +++ /dev/null @@ -1,122 +0,0 @@ -[ - { - "plugin_id": "herdr-splits", - "name": "Herdr Splits", - "version": "0.5.1", - "min_herdr_version": "0.7.0", - "description": "Seamless navigation and resizing between Herdr panes and Neovim splits", - "manifest_path": "/Users/zamp/.config/herdr/plugins/github/herdr-splits-d880c4924f2b/herdr-plugin.toml", - "plugin_root": "/Users/zamp/.config/herdr/plugins/github/herdr-splits-d880c4924f2b", - "enabled": true, - "platforms": [ - "linux", - "macos" - ], - "actions": [ - { - "id": "nav-down", - "title": "Navigate down (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-nav.sh", - "down" - ] - }, - { - "id": "nav-left", - "title": "Navigate left (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-nav.sh", - "left" - ] - }, - { - "id": "nav-right", - "title": "Navigate right (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-nav.sh", - "right" - ] - }, - { - "id": "nav-up", - "title": "Navigate up (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-nav.sh", - "up" - ] - }, - { - "id": "resize-down", - "title": "Resize down (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-resize.sh", - "down" - ] - }, - { - "id": "resize-left", - "title": "Resize left (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-resize.sh", - "left" - ] - }, - { - "id": "resize-right", - "title": "Resize right (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-resize.sh", - "right" - ] - }, - { - "id": "resize-up", - "title": "Resize up (Neovim/Herder)", - "contexts": [ - "global" - ], - "command": [ - "bash", - "scripts/herdr-resize.sh", - "up" - ] - } - ], - "source": { - "kind": "github", - "owner": "lmilojevicc", - "repo": "herdr-splits.nvim", - "resolved_commit": "107273e004e4f7ef07f13c83164d2cb2c51df65d", - "managed_path": "/Users/zamp/.config/herdr/plugins/github/herdr-splits-d880c4924f2b", - "installed_unix_ms": 1784924593009 - } - } -] \ No newline at end of file diff --git a/dot_config/herdr/plugins/config/herdr-splits/herdr-splits.conf b/dot_config/herdr/plugins/config/herdr-splits/herdr-splits.conf deleted file mode 100644 index c16b7dc..0000000 --- a/dot_config/herdr/plugins/config/herdr-splits/herdr-splits.conf +++ /dev/null @@ -1,15 +0,0 @@ -# herdr-splits-generated-v1 -# herdr-splits plugin config — GENERATED by herdr-splits.nvim setup(). -# Regenerated from defaults + setup() opts on every setup(); do not edit by hand. -# A headerless/legacy conf is adopted once on migration (see the startup -# notice), then overwritten thereafter — remove an opt in setup() to revert. -nav_key_left=ctrl+h -nav_key_down=ctrl+j -nav_key_up=ctrl+k -nav_key_right=ctrl+l -resize_key_left=alt+h -resize_key_down=alt+j -resize_key_up=alt+k -resize_key_right=alt+l -unzoom_on_nav=true -nav_at_edge=wrap diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/CONTRIBUTING.md b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/CONTRIBUTING.md deleted file mode 100644 index 3cdd672..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/CONTRIBUTING.md +++ /dev/null @@ -1,126 +0,0 @@ -# Contributing to herdr-splits.nvim - -Thanks for your interest in improving herdr-splits.nvim! This guide covers how -to set up a local development environment and submit changes. - -herdr-splits.nvim is a Neovim plugin (Lua) that also ships a Herdr-side plugin -(the bash scripts under `scripts/` plus the `herdr-plugin.toml` manifest). The -two halves cooperate — please consider both when making changes to navigation -or resize behaviour. - -## Requirements - -- Neovim ≥ 0.10 -- [Herdr](https://herdr.dev) ≥ 0.7.0 (only needed to exercise cross-pane - behaviour; you can develop the Lua side without a running Herdr session) -- A Herdr-compatible terminal with Option/Alt enabled (see the README's macOS - notes if you're on macOS) - -## Repository layout - -``` -plugin/herdr-splits.lua Neovim entrypoint -lua/herdr-splits/ Neovim plugin source - init.lua setup() + public API - nav.lua resize.lua navigation and resizing - win.lua float / sidebar classification - sync.lua Herdr-side script syncing - config.lua herdr.lua config + core - health.lua :checkhealth herdr-splits -scripts/herdr-nav.sh Herdr-side navigation action -scripts/herdr-resize.sh Herdr-side resize action -scripts/minimal_init.lua Isolated Neovim test bootstrap -tests/ mini.test suites -Makefile Local and CI validation commands -herdr-plugin.toml Herdr plugin manifest (actions + metadata) -``` - -## Local development setup - -### Neovim side - -Point your plugin manager at a local clone instead of the published repo: - -```lua --- lazy.nvim -{ - dir = '~/Projects/herdr-splits', - cond = vim.env.HERDR_ENV == '1', - config = function() - require('herdr-splits').setup({}) - end, -} -``` - -Changes to files under `lua/` take effect after `:source` or a Neovim restart -(unless your plugin manager hot-reloads). - -### Herdr side - -Link the clone so Herdr loads its scripts from your working tree: - -```bash -herdr plugin link /path/to/herdr-splits -``` - -After changing `scripts/*.sh` or `herdr-plugin.toml`, run -`herdr server reload-config` to pick them up. - -## Coding style - -- Match the surrounding Lua style — indentation, quoting, and table layout in - the file you're editing are the source of truth. -- Run [StyLua](https://github.com/JohnnyMorganz/StyLua) if you use it, but note - that no `.stylua.toml` is committed yet; when one is added it will be the - canonical formatter config. -- Run [luacheck](https://github.com/mpeterv/luacheck) where practical to catch - undefined globals and unused variables. -- Keep the bash scripts POSIX-friendly where possible; they run on both Linux - and macOS as declared in `herdr-plugin.toml`. - -## Validation - -The Make targets initialize and update the pinned test dependency automatically. -To prepare it separately, run `make deps`. - -Run the automated checks with: - -```bash -make test # isolated mini.test suite in headless Neovim -make check-shell # bash syntax checks for both shipped scripts -make check # all of the above -``` - -Cross-pane behaviour still requires manual validation in a Herdr session: - -1. Load the plugin in Neovim inside a Herdr session (`HERDR_ENV=1`). -2. Run `:checkhealth herdr-splits` and confirm it reports no failures. -3. Exercise navigation (``) and resizing (``) across both - Neovim splits and Herdr panes, including the edge cases you changed: - - `at_edge` behaviour (`wrap` / `stop` / `split` / custom) - - count prefixes (e.g. `3`) - - floating windows and embedded-sidebar floats - - auto-unzoom when crossing into a sibling Herdr pane - -## Submitting changes - -1. Fork the repo and create a branch from `main`. -2. Make focused commits with descriptive messages. -3. Open a pull request against `main` and fill in the PR template — include the - manual validation steps you ran. -4. If your change affects user-facing behaviour or config, update `README.md` - and, for manifest-level changes, `herdr-plugin.toml`. - -Keep PRs scoped to one concern. Large changes are easier to review when split -into smaller, independently understandable commits. - -## Reporting bugs and ideas - -Use the GitHub issue templates (bug report / feature request). Include the -output of `nvim --version`, your plugin manager, the Herdr version -(`herdr --version`), and a minimal reproduction. - -## License - -By contributing you agree that your contributions are licensed under the MIT -License, the same terms as the rest of the project (see `LICENSE`). diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/LICENSE b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/LICENSE deleted file mode 100644 index 511d507..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 Luka - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/Makefile b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/Makefile deleted file mode 100644 index d8a3be9..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -ROOT := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -NVIM ?= nvim - -.PHONY: deps test check-shell check - -deps: - @if git -C "$(ROOT)" ls-files --error-unmatch deps/mini.test >/dev/null 2>&1; then \ - git -C "$(ROOT)" submodule update --init --depth 1 --checkout deps/mini.test; \ - else \ - test -f "$(ROOT)/deps/mini.test/lua/mini/test.lua"; \ - fi - -test: deps - cd "$(ROOT)" && "$(NVIM)" --headless --noplugin -i NONE \ - -u "$(ROOT)/scripts/minimal_init.lua" -c "lua MiniTest.run()" - -check-shell: - bash -n "$(ROOT)/scripts/herdr-nav.sh" - bash -n "$(ROOT)/scripts/herdr-resize.sh" - -check: check-shell test diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/README.md b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/README.md deleted file mode 100644 index 7f9cd53..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/README.md +++ /dev/null @@ -1,445 +0,0 @@ -# herdr-splits.nvim - -Seamless navigation and resizing between Neovim splits and [Herdr](https://herdr.dev) panes. Makes Herdr terminal splits behave like native Neovim windows — move and resize as if they were all part of the same editor. - -Inspired by [smart-splits.nvim](https://github.com/mrjones2014/smart-splits.nvim), ported to Herdr's CLI. - -## Features - -- **Seamless navigation**: Same keys work in Neovim and plain shells — Herdr forwards them to Neovim when appropriate, Neovim delegates to Herdr at edges. -- **Seamless resizing**: `` resizes Neovim splits natively, delegates to Herdr when a window fills the terminal. -- **at_edge behaviours**: `wrap` (default), `stop`, `split`, or a custom function. -- **Plugin-aware**: Ignores snacks/neo-tree/dadbod-ui/aerial sidebars and embedded floats (zindex < 50) by default — your keybinds never get trapped inside a picker. -- **Smart unzoom + wrap-around**: Auto-unzooms when leaving a zoomed pane. At a layout edge, navigation wraps to the opposite side — crossing into a sibling Herdr pane when one exists (e.g. `pane | nvim` → `ctrl+l` wraps to the pane), otherwise wrapping within Neovim. Herdr-pane navigation also wraps around at edges (past the last pane → the first). Does not unzoom when moving between Neovim splits in one pane. -- **Count prefix support**: `3` moves three splits left; `5` resizes five steps right. - -## Requirements - -- Neovim ≥ 0.10 -- [Herdr](https://herdr.dev) ≥ 0.7.0 (for plugin actions) - -## Installation - -Three steps — install on both the Herdr side and the Neovim side, then add keybinds. - -### 1. Install the Herdr plugin - -This provides the `nav-*` and `resize-*` actions that Herdr keybinds invoke. - -```bash -# From GitHub (once published): -herdr plugin install lmilojevicc/herdr-splits.nvim - -# Local development: -herdr plugin link /path/to/herdr-splits -``` - -### 2. Install the Neovim plugin - -## lazy.nvim - -```lua -{ - 'lmilojevicc/herdr-splits.nvim', - -- For local development, swap the repo line for `dir = '/path/to/herdr-splits'` - -- (see "Local development" below). - cond = vim.env.HERDR_ENV == '1', - event = 'VeryLazy', - -- Optional: auto-sync the Herdr-side scripts when lazy updates this plugin. - -- Requires `auto_sync_herdr = true` in setup() below to take effect. - -- build = 'lua require("herdr-splits").sync_herdr()', - config = function() - require('herdr-splits').setup({ - -- Defaults shown. All fields optional. - default_amount = 0.03, -- Herdr resize ratio - neovim_amount = 3, -- Neovim resize cells - at_edge = 'wrap', -- 'wrap' | 'stop' | 'split' | function - ignored_buftypes = { 'nofile', 'quickfix', 'prompt', 'help', 'terminal' }, - ignored_filetypes = { - 'NvimTree', - -- sidebars - 'neo-tree', - 'snacks_dashboard', - 'snacks_explorer', - 'snacks_picker', - -- DB / REPL / data sidebars - 'dadbod-ui', - 'dbout', - -- outlines / symbols - 'aerial', - 'Outline', - -- diagnostics / quick lists - 'Trouble', - 'quickfix', - }, - move_cursor_same_row = false, - herdr_bin = nil, -- auto-detected from HERDR_BIN_PATH - floating_zindex_max = 50, -- floats with zindex < this are treated as embedded sidebars - ignore_previewwindows = false, -- opt-in: also treat previewwindow windows (e.g. .dbout) as sidebars - -- auto_sync_herdr = true, -- opt-in: sync Herdr-side scripts on update - -- Managed keys — written to the generated herdr-splits.conf so the - -- Herdr-side scripts agree. Pass Neovim notation (e.g. ). - nav_keys = { left = '', down = '', up = '', right = '' }, - resize_keys = { left = '', down = '', up = '', right = '' }, - unzoom_on_nav = true, -- auto-unzoom when navigating away from a zoomed pane - nav_at_edge = 'wrap', -- 'wrap' | 'stop' — Herdr pane-boundary wrap (distinct from at_edge) - }) - end, - keys = { - { '', function() require('herdr-splits').move_cursor_left() end, desc = 'Navigate left' }, - { '', function() require('herdr-splits').move_cursor_down() end, desc = 'Navigate down' }, - { '', function() require('herdr-splits').move_cursor_up() end, desc = 'Navigate up' }, - { '', function() require('herdr-splits').move_cursor_right() end, desc = 'Navigate right' }, - { '', function() require('herdr-splits').resize_left() end, desc = 'Resize left' }, - { '', function() require('herdr-splits').resize_down() end, desc = 'Resize down' }, - { '', function() require('herdr-splits').resize_up() end, desc = 'Resize up' }, - { '', function() require('herdr-splits').resize_right() end, desc = 'Resize right' }, - }, -} -``` - -## packer.nvim - -```lua -use { - 'lmilojevicc/herdr-splits.nvim', - config = function() - require('herdr-splits').setup() - end, -} -``` - -### 3. Add keybinds to Herdr config - -Add these to `~/.config/herdr/config.toml`, then run `herdr server reload-config`: - -```toml -[[keys.command]] -key = "ctrl+h" -type = "plugin_action" -command = "herdr-splits.nav-left" - -[[keys.command]] -key = "ctrl+j" -type = "plugin_action" -command = "herdr-splits.nav-down" - -[[keys.command]] -key = "ctrl+k" -type = "plugin_action" -command = "herdr-splits.nav-up" - -[[keys.command]] -key = "ctrl+l" -type = "plugin_action" -command = "herdr-splits.nav-right" - -[[keys.command]] -key = "alt+h" -type = "plugin_action" -command = "herdr-splits.resize-left" - -[[keys.command]] -key = "alt+j" -type = "plugin_action" -command = "herdr-splits.resize-down" - -[[keys.command]] -key = "alt+k" -type = "plugin_action" -command = "herdr-splits.resize-up" - -[[keys.command]] -key = "alt+l" -type = "plugin_action" -command = "herdr-splits.resize-right" -``` - -> **Note for macOS**: Terminals treat Option as a special character modifier by default. You need to set Option = Alt/Meta: -> -> - **Ghostty**: `macos-option-as-alt = true` -> - **Alacritty**: `option_as_alt = "Both"` -> - **kitty**: `macos_option_as_alt yes` -> - **iTerm**: Profiles → Keys → Left Option key → Esc+ -> -> If you're using [smart-splits.nvim](https://github.com/mrjones2014/smart-splits.nvim) for tmux, add `cond = vim.env.HERDR_ENV ~= '1'` to its spec so the two plugins don't conflict. - -### Auto-unzoom and wrap-around - -**Auto-unzoom.** When you navigate away from a **zoomed** pane, herdr-splits -unzooms first so the destination is visible — whether you're crossing into a -sibling Herdr pane or wrapping at a layout edge. It does not unzoom when -moving between Neovim splits inside the same pane. - -**Wrap-around.** When you reach a layout edge in the direction you pressed -(nowhere further to go that way), the default `wrap` behaviour continues on -the opposite side: - -- If a Herdr pane sits on the opposite side, focus crosses into it — so - `pane | nvim` wraps `ctrl+l` back to the pane, and - `pane | nvim win1 | win2` wraps from win2 to the pane. With `nav_at_edge=stop` - (see below) this cross-to-opposite-pane is suppressed and the wrap stays - within Neovim instead. -- Otherwise it wraps within Neovim (smart-splits default). -- Between plain Herdr panes, navigation wraps around at edges too (past the - last pane → the first). -- Wrap works even when you're on a sidebar (dbui, neo-tree, quickfix, ...), - so you can leave it at an edge; only embedded floating overlays are gated. - -**To disable auto-unzoom entirely**, pass `unzoom_on_nav = false` to `setup()`: - -```lua -require('herdr-splits').setup({ unzoom_on_nav = false }) -``` - -These options are written to a generated `herdr-splits.conf` (default -`~/.config/herdr/plugins/config/herdr-splits/herdr-splits.conf`; print the -path with `herdr plugin config-dir herdr-splits`) so the Herdr-side scripts -agree — you configure them once, from `setup()`. **Do not hand-edit that -file:** it is regenerated on every `setup()`. Any values already present are -adopted once the first time `setup()` runs after an upgrade, then -overwritten thereafter. Set `HERDR_SPLITS_CONFIG` to override the path on -both sides. - -**To stop at layout edges instead of wrapping**, pass `nav_at_edge = 'stop'`: - -```lua -require('herdr-splits').setup({ nav_at_edge = 'stop' }) -``` - -This single switch controls wrap-across-boundary on **both** sides: - -- **Plain Herdr panes:** `wrap` (the default) wraps to the opposite pane at an - edge; `stop` halts. -- **Neovim edge wrap:** when Neovim's `at_edge='wrap'`, `wrap` (the default) - lets the wrap cross to the Herdr pane on the opposite side (e.g. `ctrl+l` from - the last nvim split lands on the pane); `stop` keeps the wrap within Neovim - (e.g. `ctrl+l` from the last split cycles to the first split instead of - leaving Neovim). `at_edge='stop'` halts regardless of `nav_at_edge`. - -Note: `at_edge` (Neovim window-edge behaviour: `wrap`/`stop`/`split`/function) -and `nav_at_edge` (Herdr pane-boundary wrap: `wrap`/`stop`) are two different -things despite the shared name — `at_edge` is Neovim-side only and is not -written to the conf. - -Note: when a pane is zoomed and `unzoom_on_nav=false`, the edge flags can't be -trusted so `stop` can't be detected on the plain-pane side — navigation proceeds -in the requested direction in that case. With the default `unzoom_on_nav=true`, -pressing toward an edge while zoomed first unzooms the pane (so the edge can be -detected) and then halts — the pane unzooms even though focus doesn't move. - -**To remap the keys forwarded into Neovim**, pass `nav_keys` / `resize_keys` -to `setup()` in Neovim notation (e.g. ``). Override only the -directions you rebind; the rest keep their defaults. By default the scripts -forward `ctrl+h/j/k/l` for navigation and `alt+h/j/k/l` for resizing — the -chords the documented Neovim keymaps bind: - -```lua -require('herdr-splits').setup({ - nav_keys = { left = '', down = '', up = '', right = '' }, - resize_keys = { left = '', down = '', up = '', right = '' }, -}) -``` - -- Pass Neovim notation in `setup()` (``, ``); it is translated to the Herdr chord notation (`ctrl+h`, `alt+left`) the generated conf writes and `herdr pane send-keys` accepts. -- Any direction left unset keeps its default. -- The chord forwarded into Neovim must match the Neovim keymap that catches it: `` in `setup()` is the same key `alt+left` the script forwards, so keep your `vim.keymap.set` in sync with `nav_keys`. - -> **Eager load required for custom keys.** The generated conf is written by -> `setup()`, so custom `nav_keys`/`resize_keys` need `setup()` to run eagerly -> or at `VeryLazy` — do **not** lazy-load this plugin *only* from the same -> custom key mappings it must publish. Otherwise the conf carrying your custom -> chords isn't written before Herdr forwards them, and those keys can't reach -> Neovim to trigger the lazy load. The recommended spec above already uses -> `event = 'VeryLazy'`. - -## Local development - -Both sides load straight from your clone, so edits take effect immediately -(on the Herdr side; Neovim picks them up on reload/restart). - -1. **Link the Herdr plugin** to your local repo: - - ```bash - herdr plugin link /path/to/herdr-splits - ``` - -2. **Point lazy.nvim at the same path** — change the first line of the spec - from the GitHub repo to `dir`: - - ```lua - { - dir = '/path/to/herdr-splits', - cond = vim.env.HERDR_ENV == '1', - -- ...rest of the spec unchanged - } - ``` - -Run `herdr plugin list` to confirm it shows `herdr-splits ... [local:/...]`. -To switch back to the published version: `herdr plugin unlink herdr-splits`, -then `herdr plugin install lmilojevicc/herdr-splits.nvim`, and revert the -lazy spec to `'lmilojevicc/herdr-splits.nvim'`. - -## Lua API - -```lua -require('herdr-splits').setup(opts) - --- Resize (amount defaults to config.default_amount, multiplied by count prefix) -require('herdr-splits').resize_left(amount) -require('herdr-splits').resize_down(amount) -require('herdr-splits').resize_up(amount) -require('herdr-splits').resize_right(amount) - --- Navigate (opts can override same_row and at_edge per-call) -require('herdr-splits').move_cursor_left({ same_row = true, at_edge = 'stop' }) -require('herdr-splits').move_cursor_down(opts) -require('herdr-splits').move_cursor_up(opts) -require('herdr-splits').move_cursor_right(opts) -``` - -## Compatibility - -`herdr-splits.nvim` ships with an opinionated default `ignored_filetypes` list so your resize keybinds don't get trapped inside common sidebars and pickers. These filetypes are treated as sidebars: `split`-at-edge and Herdr resize delegation are skipped from them, and the flag is passed to a custom `at_edge` function as `is_sidebar`. `wrap`, however, still works from a sidebar so you can leave it (e.g. `ctrl+l` on a `dadbod-ui` drawer wraps to the opposite side); only embedded floating overlays are gated. - -The default `ignored_filetypes` covers: - -- `NvimTree` — `nvim-tree/nvim-tree.lua` default file tree (`buftype=nofile`, `winfixwidth`). -- `neo-tree` — `nvim-neo-tree/neo-tree.nvim` LazyVim default (`winfixwidth` sidebar). -- `snacks_dashboard` / `snacks_explorer` / `snacks_picker` — `folke/snacks` sidebar/picker windows (the float case is handled by `is_embedded_floating_window` below). -- `dadbod-ui` / `dbout` — `kristijanhusak/vim-dadbod-ui` drawer and `tpope/vim-dadbod` preview result buffer. -- `aerial` / `Outline` — code-outline sidebars. -- `Trouble` / `quickfix` — diagnostics and quickfix lists. - -The default `ignored_buftypes` covers `nofile`, `quickfix`, `prompt`, `help`, and `terminal`. - -**Embedded floating windows** (snacks explorer in float mode, neo-tree in float mode, aerial in float mode) are detected via the `zindex < floating_zindex_max` heuristic (default threshold 50, Neovim's default float zindex) and treated as sidebars for navigation/resize decisions. Override the threshold via the `floating_zindex_max` config field. - -**Add your own at runtime** from any `VeryLazy` autocmd: - -```lua -require('herdr-splits').add_ignored_filetype('lazy') -require('herdr-splits').add_ignored_buftype('help') -``` - -**Debug with `:checkhealth herdr-splits`** (Neovim ≥ 0.10) to see which filetypes/buftypes are ignored, whether Herdr is in session, and whether the current window is classified as a sidebar. - -If you want to **completely replace** the default list (e.g. to opt out of one of the entries), note that `vim.tbl_deep_extend('force', M, opts)` **concatenates** the `ignored_filetypes` / `ignored_buftypes` tables you pass; you keep what you pass AND the defaults are appended. To opt out, assign directly after `setup()`: - -```lua -require('herdr-splits').setup({ ignored_filetypes = {} }) -- inherit nothing -require('herdr-splits').add_ignored_filetype('mything') -- then add back what you want -``` - -## How It Works - -Two sides cooperate for seamless two-way navigation: - -```text -You press C-h in a Herdr pane: - - ┌─ Herdr intercepts the key (plugin_action keybind) - │ - ├─ Is the focused pane running Neovim? - │ │ - │ ├─ YES → forward "ctrl+h" into that pane - │ │ └─ Neovim plugin receives it - │ │ ├─ Has a window to the left? → wincmd h - │ │ └─ At Neovim edge? → herdr pane focus --direction left - │ │ - │ └─ NO (plain shell, etc.) → herdr pane focus --direction left - │ - └─ Result: same keys move you everywhere -``` - -### Navigation - -```text -1. Try moving within Neovim (wincmd h/j/k/l) - ├─ Window changed → done (stayed within Neovim splits) - └─ Window didn't change → at Neovim edge - ├─ Zoomed? → unzoom first (neighbours are reliable once visible) - ├─ Check if Herdr is running (HERDR_ENV=1) - ├─ Check if Herdr pane has a neighbour in this direction - │ └─ Yes → herdr pane focus --direction → done - └─ No (at both Neovim AND Herdr edge) → - apply at_edge behaviour (`wrap` crosses to the opposite Herdr - pane if one exists and nav_at_edge=wrap (the default), else - wraps within Neovim) -``` - -### Resizing - -```text -1. Only one Neovim window in this dimension AND fills terminal? - └─ Yes → herdr pane resize --direction --amount → done -2. Otherwise: - └─ Native Neovim resize with position-aware +/- operators -``` - -### Float and embedded-float classification - -Two predicates classify the current window before any nav/resize decision: - -- `win.is_floating(winid)` — `nvim_win_get_config(winid).relative ~= ''` (Neovim's built-in float check). -- `win.is_embedded_floating_window(winid)` — true only for floats with `zindex < floating_zindex_max` (default 50); matches snacks/neo-tree/aerial float-mode sidebars. - -True floats forward to Herdr; embedded floats behave as sidebars (no movement, no Herdr delegation). - -## Herdr Detection - -Detected automatically through environment variables Herdr injects into every pane: - -- `HERDR_ENV=1` — set when running inside a Herdr-managed pane -- `HERDR_PANE_ID` — the public pane ID (e.g., `w1:p1`) -- `HERDR_BIN_PATH` — path to the herdr binary (for subprocess calls) - -## Comparison with vim-herdr-navigation - -| Feature | vim-herdr-navigation | herdr-splits.nvim | -| --------------------------- | -------------------- | ---------------------------- | -| Navigation | ✓ | ✓ | -| Resizing | ✗ | ✓ | -| at_edge behaviours | ✗ | wrap / stop / split / custom | -| Count prefix | ✗ | ✓ (3 = move 3 left) | -| Auto-unzoom + wrap-around | ✗ | ✓ | -| Floating window handling | ✗ | ✓ | -| Herdr plugin (for keybinds) | ✓ | ✓ | -| Neovim plugin | ✓ | ✓ | - -## Updating - -The Neovim side (lua) auto-updates via lazy.nvim — it pulls `main` on -`LazySync`. The Herdr side (the bash scripts under the Herdr-managed -checkout) does **not** auto-update by default: Herdr v1 has no -`herdr plugin update`, so a managed checkout stays frozen at the commit it -was installed from. - -**Option A — opt into automatic sync (recommended):** set -`auto_sync_herdr = true` in `setup()`. The plugin then reinstalls the -Herdr-managed checkout pinned to the exact commit lazy fetched, so the bash -scripts always match the lua side. It is a no-op when already in sync, when -in local-dev (`plugin link`) mode, or when the `herdr` binary is unavailable. - -For maximum efficiency, also add a `build` hook so the sync fires only when -lazy actually updates the plugin, instead of on every Neovim startup: - -```lua -{ - 'lmilojevicc/herdr-splits.nvim', - build = 'lua require("herdr-splits").sync_herdr()', - config = function() - require('herdr-splits').setup({ auto_sync_herdr = true }) - end, -} -``` - -**Option B — manual:** after an update, re-run -`herdr plugin install lmilojevicc/herdr-splits.nvim` to refresh the -Herdr-side scripts. - -Release notes for each version live in [GitHub Releases](https://github.com/lmilojevicc/herdr-splits.nvim/releases). - -## License - -MIT diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/deps/mini.test/.keep b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/deps/mini.test/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/FETCH_HEAD b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/FETCH_HEAD deleted file mode 100644 index c02fa3c..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/FETCH_HEAD +++ /dev/null @@ -1 +0,0 @@ -107273e004e4f7ef07f13c83164d2cb2c51df65d https://github.com/lmilojevicc/herdr-splits.nvim diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/HEAD b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/HEAD deleted file mode 100644 index c367d86..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/HEAD +++ /dev/null @@ -1 +0,0 @@ -107273e004e4f7ef07f13c83164d2cb2c51df65d diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/config b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/config deleted file mode 100644 index 35a60e8..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/config +++ /dev/null @@ -1,10 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true - precomposeunicode = true -[remote "origin"] - url = https://github.com/lmilojevicc/herdr-splits.nvim.git - fetch = +refs/heads/*:refs/remotes/origin/* diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/description b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/description deleted file mode 100644 index 498b267..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_applypatch-msg.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_applypatch-msg.sample deleted file mode 100644 index a5d7b84..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_applypatch-msg.sample +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message taken by -# applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. The hook is -# allowed to edit the commit message file. -# -# To enable this hook, rename this file to "applypatch-msg". - -. git-sh-setup -commitmsg="$(git rev-parse --git-path hooks/commit-msg)" -test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} -: diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_commit-msg.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_commit-msg.sample deleted file mode 100644 index b58d118..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_commit-msg.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message. -# Called by "git commit" with one argument, the name of the file -# that has the commit message. The hook should exit with non-zero -# status after issuing an appropriate message if it wants to stop the -# commit. The hook is allowed to edit the commit message file. -# -# To enable this hook, rename this file to "commit-msg". - -# Uncomment the below to add a Signed-off-by line to the message. -# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -# hook is more suited to it. -# -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" - -# This example catches duplicate Signed-off-by lines. - -test "" = "$(grep '^Signed-off-by: ' "$1" | - sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { - echo >&2 Duplicate Signed-off-by lines. - exit 1 -} diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_fsmonitor-watchman.sample deleted file mode 100644 index 23e856f..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_fsmonitor-watchman.sample +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use IPC::Open2; - -# An example hook script to integrate Watchman -# (https://facebook.github.io/watchman/) with git to speed up detecting -# new and modified files. -# -# The hook is passed a version (currently 2) and last update token -# formatted as a string and outputs to stdout a new update token and -# all files that have been modified since the update token. Paths must -# be relative to the root of the working tree and separated by a single NUL. -# -# To enable this hook, rename this file to "query-watchman" and set -# 'git config core.fsmonitor .git/hooks/query-watchman' -# -my ($version, $last_update_token) = @ARGV; - -# Uncomment for debugging -# print STDERR "$0 $version $last_update_token\n"; - -# Check the hook interface version -if ($version ne 2) { - die "Unsupported query-fsmonitor hook version '$version'.\n" . - "Falling back to scanning...\n"; -} - -my $git_work_tree = get_working_dir(); - -my $retry = 1; - -my $json_pkg; -eval { - require JSON::XS; - $json_pkg = "JSON::XS"; - 1; -} or do { - require JSON::PP; - $json_pkg = "JSON::PP"; -}; - -launch_watchman(); - -sub launch_watchman { - my $o = watchman_query(); - if (is_work_tree_watched($o)) { - output_result($o->{clock}, @{$o->{files}}); - } -} - -sub output_result { - my ($clockid, @files) = @_; - - # Uncomment for debugging watchman output - # open (my $fh, ">", ".git/watchman-output.out"); - # binmode $fh, ":utf8"; - # print $fh "$clockid\n@files\n"; - # close $fh; - - binmode STDOUT, ":utf8"; - print $clockid; - print "\0"; - local $, = "\0"; - print @files; -} - -sub watchman_clock { - my $response = qx/watchman clock "$git_work_tree"/; - die "Failed to get clock id on '$git_work_tree'.\n" . - "Falling back to scanning...\n" if $? != 0; - - return $json_pkg->new->utf8->decode($response); -} - -sub watchman_query { - my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') - or die "open2() failed: $!\n" . - "Falling back to scanning...\n"; - - # In the query expression below we're asking for names of files that - # changed since $last_update_token but not from the .git folder. - # - # To accomplish this, we're using the "since" generator to use the - # recency index to select candidate nodes and "fields" to limit the - # output to file names only. Then we're using the "expression" term to - # further constrain the results. - my $last_update_line = ""; - if (substr($last_update_token, 0, 1) eq "c") { - $last_update_token = "\"$last_update_token\""; - $last_update_line = qq[\n"since": $last_update_token,]; - } - my $query = <<" END"; - ["query", "$git_work_tree", {$last_update_line - "fields": ["name"], - "expression": ["not", ["dirname", ".git"]] - }] - END - - # Uncomment for debugging the watchman query - # open (my $fh, ">", ".git/watchman-query.json"); - # print $fh $query; - # close $fh; - - print CHLD_IN $query; - close CHLD_IN; - my $response = do {local $/; }; - - # Uncomment for debugging the watch response - # open ($fh, ">", ".git/watchman-response.json"); - # print $fh $response; - # close $fh; - - die "Watchman: command returned no output.\n" . - "Falling back to scanning...\n" if $response eq ""; - die "Watchman: command returned invalid output: $response\n" . - "Falling back to scanning...\n" unless $response =~ /^\{/; - - return $json_pkg->new->utf8->decode($response); -} - -sub is_work_tree_watched { - my ($output) = @_; - my $error = $output->{error}; - if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { - $retry--; - my $response = qx/watchman watch "$git_work_tree"/; - die "Failed to make watchman watch '$git_work_tree'.\n" . - "Falling back to scanning...\n" if $? != 0; - $output = $json_pkg->new->utf8->decode($response); - $error = $output->{error}; - die "Watchman: $error.\n" . - "Falling back to scanning...\n" if $error; - - # Uncomment for debugging watchman output - # open (my $fh, ">", ".git/watchman-output.out"); - # close $fh; - - # Watchman will always return all files on the first query so - # return the fast "everything is dirty" flag to git and do the - # Watchman query just to get it over with now so we won't pay - # the cost in git to look up each individual file. - my $o = watchman_clock(); - $error = $output->{error}; - - die "Watchman: $error.\n" . - "Falling back to scanning...\n" if $error; - - output_result($o->{clock}, ("/")); - $last_update_token = $o->{clock}; - - eval { launch_watchman() }; - return 0; - } - - die "Watchman: $error.\n" . - "Falling back to scanning...\n" if $error; - - return 1; -} - -sub get_working_dir { - my $working_dir; - if ($^O =~ 'msys' || $^O =~ 'cygwin') { - $working_dir = Win32::GetCwd(); - $working_dir =~ tr/\\/\//; - } else { - require Cwd; - $working_dir = Cwd::cwd(); - } - - return $working_dir; -} diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_post-update.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_post-update.sample deleted file mode 100644 index ec17ec1..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_post-update.sample +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare a packed repository for use over -# dumb transports. -# -# To enable this hook, rename this file to "post-update". - -exec git update-server-info diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-applypatch.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-applypatch.sample deleted file mode 100644 index 4142082..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-applypatch.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed -# by applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-applypatch". - -. git-sh-setup -precommit="$(git rev-parse --git-path hooks/pre-commit)" -test -x "$precommit" && exec "$precommit" ${1+"$@"} -: diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-commit.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-commit.sample deleted file mode 100644 index 29ed5ee..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-commit.sample +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-commit". - -if git rev-parse --verify HEAD >/dev/null 2>&1 -then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=$(git hash-object -t tree /dev/null) -fi - -# If you want to allow non-ASCII filenames set this variable to true. -allownonascii=$(git config --type=bool hooks.allownonascii) - -# Redirect output to stderr. -exec 1>&2 - -# Cross platform projects tend to avoid non-ASCII filenames; prevent -# them from being added to the repository. We exploit the fact that the -# printable range starts at the space character and ends with tilde. -if [ "$allownonascii" != "true" ] && - # Note that the use of brackets around a tr range is ok here, (it's - # even required, for portability to Solaris 10's /usr/bin/tr), since - # the square bracket bytes happen to fall in the designated range. - test $(git diff-index --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -then - cat <<\EOF -Error: Attempt to add a non-ASCII file name. - -This can cause problems if you want to work with people on other platforms. - -To be portable it is advisable to rename the file. - -If you know what you are doing you can disable this check using: - - git config hooks.allownonascii true -EOF - exit 1 -fi - -# If there are whitespace errors, print the offending file names and fail. -exec git diff-index --check --cached $against -- diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-merge-commit.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-merge-commit.sample deleted file mode 100644 index 399eab1..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-merge-commit.sample +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git merge" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message to -# stderr if it wants to stop the merge commit. -# -# To enable this hook, rename this file to "pre-merge-commit". - -. git-sh-setup -test -x "$GIT_DIR/hooks/pre-commit" && - exec "$GIT_DIR/hooks/pre-commit" -: diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-push.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-push.sample deleted file mode 100644 index 4ce688d..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-push.sample +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh - -# An example hook script to verify what is about to be pushed. Called by "git -# push" after it has checked the remote status, but before anything has been -# pushed. If this script exits with a non-zero status nothing will be pushed. -# -# This hook is called with the following parameters: -# -# $1 -- Name of the remote to which the push is being done -# $2 -- URL to which the push is being done -# -# If pushing without using a named remote those arguments will be equal. -# -# Information about the commits which are being pushed is supplied as lines to -# the standard input in the form: -# -# -# -# This sample shows how to prevent push of commits where the log message starts -# with "WIP" (work in progress). - -remote="$1" -url="$2" - -zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" - exit 1 - fi - fi -done - -exit 0 diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-rebase.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-rebase.sample deleted file mode 100644 index 6cbef5c..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-rebase.sample +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006, 2008 Junio C Hamano -# -# The "pre-rebase" hook is run just before "git rebase" starts doing -# its job, and can prevent the command from running by exiting with -# non-zero status. -# -# The hook is called with the following parameters: -# -# $1 -- the upstream the series was forked from. -# $2 -- the branch being rebased (or empty when rebasing the current branch). -# -# This sample shows how to prevent topic branches that are already -# merged to 'next' branch from getting rebased, because allowing it -# would result in rebasing already published history. - -publish=next -basebranch="$1" -if test "$#" = 2 -then - topic="refs/heads/$2" -else - topic=`git symbolic-ref HEAD` || - exit 0 ;# we do not interrupt rebasing detached HEAD -fi - -case "$topic" in -refs/heads/??/*) - ;; -*) - exit 0 ;# we do not interrupt others. - ;; -esac - -# Now we are dealing with a topic branch being rebased -# on top of master. Is it OK to rebase it? - -# Does the topic really exist? -git show-ref -q "$topic" || { - echo >&2 "No such branch $topic" - exit 1 -} - -# Is topic fully merged to master? -not_in_master=`git rev-list --pretty=oneline ^master "$topic"` -if test -z "$not_in_master" -then - echo >&2 "$topic is fully merged to master; better remove it." - exit 1 ;# we could allow it, but there is no point. -fi - -# Is topic ever merged to next? If so you should not be rebasing it. -only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` -only_next_2=`git rev-list ^master ${publish} | sort` -if test "$only_next_1" = "$only_next_2" -then - not_in_topic=`git rev-list "^$topic" master` - if test -z "$not_in_topic" - then - echo >&2 "$topic is already up to date with master" - exit 1 ;# we could allow it, but there is no point. - else - exit 0 - fi -else - not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` - /usr/bin/perl -e ' - my $topic = $ARGV[0]; - my $msg = "* $topic has commits already merged to public branch:\n"; - my (%not_in_next) = map { - /^([0-9a-f]+) /; - ($1 => 1); - } split(/\n/, $ARGV[1]); - for my $elem (map { - /^([0-9a-f]+) (.*)$/; - [$1 => $2]; - } split(/\n/, $ARGV[2])) { - if (!exists $not_in_next{$elem->[0]}) { - if ($msg) { - print STDERR $msg; - undef $msg; - } - print STDERR " $elem->[1]\n"; - } - } - ' "$topic" "$not_in_next" "$not_in_master" - exit 1 -fi - -<<\DOC_END - -This sample hook safeguards topic branches that have been -published from being rewound. - -The workflow assumed here is: - - * Once a topic branch forks from "master", "master" is never - merged into it again (either directly or indirectly). - - * Once a topic branch is fully cooked and merged into "master", - it is deleted. If you need to build on top of it to correct - earlier mistakes, a new topic branch is created by forking at - the tip of the "master". This is not strictly necessary, but - it makes it easier to keep your history simple. - - * Whenever you need to test or publish your changes to topic - branches, merge them into "next" branch. - -The script, being an example, hardcodes the publish branch name -to be "next", but it is trivial to make it configurable via -$GIT_DIR/config mechanism. - -With this workflow, you would want to know: - -(1) ... if a topic branch has ever been merged to "next". Young - topic branches can have stupid mistakes you would rather - clean up before publishing, and things that have not been - merged into other branches can be easily rebased without - affecting other people. But once it is published, you would - not want to rewind it. - -(2) ... if a topic branch has been fully merged to "master". - Then you can delete it. More importantly, you should not - build on top of it -- other people may already want to - change things related to the topic as patches against your - "master", so if you need further changes, it is better to - fork the topic (perhaps with the same name) afresh from the - tip of "master". - -Let's look at this example: - - o---o---o---o---o---o---o---o---o---o "next" - / / / / - / a---a---b A / / - / / / / - / / c---c---c---c B / - / / / \ / - / / / b---b C \ / - / / / / \ / - ---o---o---o---o---o---o---o---o---o---o---o "master" - - -A, B and C are topic branches. - - * A has one fix since it was merged up to "next". - - * B has finished. It has been fully merged up to "master" and "next", - and is ready to be deleted. - - * C has not merged to "next" at all. - -We would want to allow C to be rebased, refuse A, and encourage -B to be deleted. - -To compute (1): - - git rev-list ^master ^topic next - git rev-list ^master next - - if these match, topic has not merged in next at all. - -To compute (2): - - git rev-list master..topic - - if this is empty, it is fully merged to "master". - -DOC_END diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-receive.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-receive.sample deleted file mode 100644 index a1fd29e..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_pre-receive.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to make use of push options. -# The example simply echoes all push options that start with 'echoback=' -# and rejects all pushes when the "reject" push option is used. -# -# To enable this hook, rename this file to "pre-receive". - -if test -n "$GIT_PUSH_OPTION_COUNT" -then - i=0 - while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" - do - eval "value=\$GIT_PUSH_OPTION_$i" - case "$value" in - echoback=*) - echo "echo from the pre-receive-hook: ${value#*=}" >&2 - ;; - reject) - exit 1 - esac - i=$((i + 1)) - done -fi diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_prepare-commit-msg.sample deleted file mode 100644 index 10fa14c..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_prepare-commit-msg.sample +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare the commit log message. -# Called by "git commit" with the name of the file that has the -# commit message, followed by the description of the commit -# message's source. The hook's purpose is to edit the commit -# message file. If the hook fails with a non-zero status, -# the commit is aborted. -# -# To enable this hook, rename this file to "prepare-commit-msg". - -# This hook includes three examples. The first one removes the -# "# Please enter the commit message..." help message. -# -# The second includes the output of "git diff --name-status -r" -# into the message, just before the "git status" output. It is -# commented because it doesn't cope with --amend or with squashed -# commits. -# -# The third example adds a Signed-off-by line to the message, that can -# still be edited. This is rarely a good idea. - -COMMIT_MSG_FILE=$1 -COMMIT_SOURCE=$2 -SHA1=$3 - -/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" - -# case "$COMMIT_SOURCE,$SHA1" in -# ,|template,) -# /usr/bin/perl -i.bak -pe ' -# print "\n" . `git diff --cached --name-status -r` -# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; -# *) ;; -# esac - -# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" -# if test -z "$COMMIT_SOURCE" -# then -# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" -# fi diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_push-to-checkout.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_push-to-checkout.sample deleted file mode 100644 index af5a0c0..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_push-to-checkout.sample +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh - -# An example hook script to update a checked-out tree on a git push. -# -# This hook is invoked by git-receive-pack(1) when it reacts to git -# push and updates reference(s) in its repository, and when the push -# tries to update the branch that is currently checked out and the -# receive.denyCurrentBranch configuration variable is set to -# updateInstead. -# -# By default, such a push is refused if the working tree and the index -# of the remote repository has any difference from the currently -# checked out commit; when both the working tree and the index match -# the current commit, they are updated to match the newly pushed tip -# of the branch. This hook is to be used to override the default -# behaviour; however the code below reimplements the default behaviour -# as a starting point for convenient modification. -# -# The hook receives the commit with which the tip of the current -# branch is going to be updated: -commit=$1 - -# It can exit with a non-zero status to refuse the push (when it does -# so, it must not modify the index or the working tree). -die () { - echo >&2 "$*" - exit 1 -} - -# Or it can make any necessary changes to the working tree and to the -# index to bring them to the desired state when the tip of the current -# branch is updated to the new commit, and exit with a zero status. -# -# For example, the hook can simply run git read-tree -u -m HEAD "$1" -# in order to emulate git fetch that is run in the reverse direction -# with git push, as the two-tree form of git read-tree -u -m is -# essentially the same as git switch or git checkout that switches -# branches while keeping the local changes in the working tree that do -# not interfere with the difference between the branches. - -# The below is a more-or-less exact translation to shell of the C code -# for the default behaviour for git's push-to-checkout hook defined in -# the push_to_deploy() function in builtin/receive-pack.c. -# -# Note that the hook will be executed from the repository directory, -# not from the working tree, so if you want to perform operations on -# the working tree, you will have to adapt your code accordingly, e.g. -# by adding "cd .." or using relative paths. - -if ! git update-index -q --ignore-submodules --refresh -then - die "Up-to-date check failed" -fi - -if ! git diff-files --quiet --ignore-submodules -- -then - die "Working directory has unstaged changes" -fi - -# This is a rough translation of: -# -# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX -if git cat-file -e HEAD 2>/dev/null -then - head=HEAD -else - head=$(git hash-object -t tree --stdin &2 - exit 1 -} - -unset GIT_DIR GIT_WORK_TREE -cd "$worktree" && - -if grep -q "^diff --git " "$1" -then - validate_patch "$1" -else - validate_cover_letter "$1" -fi && - -if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" -then - git config --unset-all sendemail.validateWorktree && - trap 'git worktree remove -ff "$worktree"' EXIT && - validate_series -fi diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_update.sample b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_update.sample deleted file mode 100644 index c4d426b..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/hooks/executable_update.sample +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -# -# An example hook script to block unannotated tags from entering. -# Called by "git receive-pack" with arguments: refname sha1-old sha1-new -# -# To enable this hook, rename this file to "update". -# -# Config -# ------ -# hooks.allowunannotated -# This boolean sets whether unannotated tags will be allowed into the -# repository. By default they won't be. -# hooks.allowdeletetag -# This boolean sets whether deleting tags will be allowed in the -# repository. By default they won't be. -# hooks.allowmodifytag -# This boolean sets whether a tag may be modified after creation. By default -# it won't be. -# hooks.allowdeletebranch -# This boolean sets whether deleting branches will be allowed in the -# repository. By default they won't be. -# hooks.denycreatebranch -# This boolean sets whether remotely creating branches will be denied -# in the repository. By default this is allowed. -# - -# --- Command line -refname="$1" -oldrev="$2" -newrev="$3" - -# --- Safety check -if [ -z "$GIT_DIR" ]; then - echo "Don't run this script from the command line." >&2 - echo " (if you want, you could supply GIT_DIR then run" >&2 - echo " $0 )" >&2 - exit 1 -fi - -if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "usage: $0 " >&2 - exit 1 -fi - -# --- Config -allowunannotated=$(git config --type=bool hooks.allowunannotated) -allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) -denycreatebranch=$(git config --type=bool hooks.denycreatebranch) -allowdeletetag=$(git config --type=bool hooks.allowdeletetag) -allowmodifytag=$(git config --type=bool hooks.allowmodifytag) - -# check for no description -projectdesc=$(sed -e '1q' "$GIT_DIR/description") -case "$projectdesc" in -"Unnamed repository"* | "") - echo "*** Project description file hasn't been set" >&2 - exit 1 - ;; -esac - -# --- Check types -# if $newrev is 0000...0000, it's a commit to delete a ref. -zero=$(git hash-object --stdin &2 - echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 - exit 1 - fi - ;; - refs/tags/*,delete) - # delete tag - if [ "$allowdeletetag" != "true" ]; then - echo "*** Deleting a tag is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/tags/*,tag) - # annotated tag - if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 - then - echo "*** Tag '$refname' already exists." >&2 - echo "*** Modifying a tag is not allowed in this repository." >&2 - exit 1 - fi - ;; - refs/heads/*,commit) - # branch - if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then - echo "*** Creating a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/heads/*,delete) - # delete branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/remotes/*,commit) - # tracking branch - ;; - refs/remotes/*,delete) - # delete tracking branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a tracking branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - *) - # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 - exit 1 - ;; -esac - -# --- Finished -exit 0 diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/index b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/index deleted file mode 100644 index 0d60dea..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/index and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/info/exclude b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/info/exclude deleted file mode 100644 index a5196d1..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/logs/HEAD b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/logs/HEAD deleted file mode 100644 index 26d428e..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 107273e004e4f7ef07f13c83164d2cb2c51df65d Pablu 1784924592 +0200 checkout: moving from main to FETCH_HEAD diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/00/readonly_5337796b0a74934b058105cc428c5616fd0f0d b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/00/readonly_5337796b0a74934b058105cc428c5616fd0f0d deleted file mode 100644 index 33e7d1c..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/00/readonly_5337796b0a74934b058105cc428c5616fd0f0d and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/0a/readonly_fc9295e33d59a441e3be5e0e642938ffbda0e0 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/0a/readonly_fc9295e33d59a441e3be5e0e642938ffbda0e0 deleted file mode 100644 index 1e4b2a1..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/0a/readonly_fc9295e33d59a441e3be5e0e642938ffbda0e0 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/10/readonly_7273e004e4f7ef07f13c83164d2cb2c51df65d b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/10/readonly_7273e004e4f7ef07f13c83164d2cb2c51df65d deleted file mode 100644 index 5b3aea4..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/10/readonly_7273e004e4f7ef07f13c83164d2cb2c51df65d and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/16/readonly_d0b0db945ddf3d303278b53db08991f21ee859 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/16/readonly_d0b0db945ddf3d303278b53db08991f21ee859 deleted file mode 100644 index 390cb64..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/16/readonly_d0b0db945ddf3d303278b53db08991f21ee859 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/17/readonly_63803d3dbf5f7131e57db9486568c5fb744450 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/17/readonly_63803d3dbf5f7131e57db9486568c5fb744450 deleted file mode 100644 index af4be11..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/17/readonly_63803d3dbf5f7131e57db9486568c5fb744450 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/27/readonly_4f4a2cc4bd8534e7df9f92f3fe62c91693463e b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/27/readonly_4f4a2cc4bd8534e7df9f92f3fe62c91693463e deleted file mode 100644 index cf16489..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/27/readonly_4f4a2cc4bd8534e7df9f92f3fe62c91693463e and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/27/readonly_52c3623b72f8cad4b4f68f961bc9a12df4fe84 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/27/readonly_52c3623b72f8cad4b4f68f961bc9a12df4fe84 deleted file mode 100644 index dfa926d..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/27/readonly_52c3623b72f8cad4b4f68f961bc9a12df4fe84 +++ /dev/null @@ -1 +0,0 @@ -xS͎0kBӪ=Cpcldվ{&R6ZRo0g>}kQX3Ip܌3|_2?rS~Ga(ܢW42ZpeQ3^Rl\T('m兾*;"T:{pqupϠFw ( j{n.D,d>wqJO->8X7X[Q ƺ;%kAHV:#ɩ{Ӻ3ئ74W>сD׈5/\Gh0dlN:^+lƒSOzJ l#ZжCb=q{w1:U%# )QG~gBQ,VFӖ(!ĕwm>A/NJ1LZO`e[߆b;_ϸ}@pzM֊.E \ No newline at end of file diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/37/readonly_51026d393d97f55d261e1e20dbce0bb707b784 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/37/readonly_51026d393d97f55d261e1e20dbce0bb707b784 deleted file mode 100644 index f5ce5f8..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/37/readonly_51026d393d97f55d261e1e20dbce0bb707b784 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/37/readonly_8209034800d64adf3487b3819bd6a531ae0606 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/37/readonly_8209034800d64adf3487b3819bd6a531ae0606 deleted file mode 100644 index 40d199f..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/37/readonly_8209034800d64adf3487b3819bd6a531ae0606 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/3c/readonly_dd672a9627ea5b0f567efa2a860492622b1415 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/3c/readonly_dd672a9627ea5b0f567efa2a860492622b1415 deleted file mode 100644 index 7aeda8d..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/3c/readonly_dd672a9627ea5b0f567efa2a860492622b1415 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/3f/readonly_e8254ac9e3b167cd84e4c427d87f8af76e23ea b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/3f/readonly_e8254ac9e3b167cd84e4c427d87f8af76e23ea deleted file mode 100644 index cb29c04..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/3f/readonly_e8254ac9e3b167cd84e4c427d87f8af76e23ea +++ /dev/null @@ -1 +0,0 @@ -xPKj0 ڧN )&zrrw +I66xߞlW 9#̠p+W:}ޱ_@$ \ No newline at end of file diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/41/readonly_399a89bfca1a0095f7a53d1f89810861242e79 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/41/readonly_399a89bfca1a0095f7a53d1f89810861242e79 deleted file mode 100644 index df88450..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/41/readonly_399a89bfca1a0095f7a53d1f89810861242e79 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/47/readonly_f6821b845d7069c2c68f7c7082be8e2c152b04 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/47/readonly_f6821b845d7069c2c68f7c7082be8e2c152b04 deleted file mode 100644 index 470206c..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/47/readonly_f6821b845d7069c2c68f7c7082be8e2c152b04 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/4d/readonly_32363ad9bc23df7acbbd83598565e140168682 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/4d/readonly_32363ad9bc23df7acbbd83598565e140168682 deleted file mode 100644 index fa1342d..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/4d/readonly_32363ad9bc23df7acbbd83598565e140168682 +++ /dev/null @@ -1,2 +0,0 @@ -xuR0D%)hh'rto"IrGa*nnn1́sq s(Gt"9eu5Uv9@oɣ;I[GmZ)Cyq'Mp!.zC\> -+wv5{T#;*vsPEd-dZ׆8!TGJy(8.rJkfߥ&Wė8*Пy4 \ No newline at end of file diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/51/readonly_1d507c6ba403c265e84aa3d6b5a66aef442953 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/51/readonly_1d507c6ba403c265e84aa3d6b5a66aef442953 deleted file mode 100644 index 4f5f5da..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/51/readonly_1d507c6ba403c265e84aa3d6b5a66aef442953 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/52/readonly_f002f346b87b770ebb3747d801684ff4d5f56a b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/52/readonly_f002f346b87b770ebb3747d801684ff4d5f56a deleted file mode 100644 index 5751358..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/52/readonly_f002f346b87b770ebb3747d801684ff4d5f56a and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/56/readonly_ecca37040cae81738e7dc8c44e8e705d7f744c b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/56/readonly_ecca37040cae81738e7dc8c44e8e705d7f744c deleted file mode 100644 index 2c6d3f6..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/56/readonly_ecca37040cae81738e7dc8c44e8e705d7f744c and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/6f/readonly_ecb9315d55b29f0f5f1a0efcc21b4ee10e6507 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/6f/readonly_ecb9315d55b29f0f5f1a0efcc21b4ee10e6507 deleted file mode 100644 index d9c674a..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/6f/readonly_ecb9315d55b29f0f5f1a0efcc21b4ee10e6507 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/7b/readonly_ecca042405c772eac6ec40f362327ad8e36693 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/7b/readonly_ecca042405c772eac6ec40f362327ad8e36693 deleted file mode 100644 index 07a152a..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/7b/readonly_ecca042405c772eac6ec40f362327ad8e36693 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/7f/readonly_9cd53e889a0af1c8ac06d90a7f529692fb7082 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/7f/readonly_9cd53e889a0af1c8ac06d90a7f529692fb7082 deleted file mode 100644 index 1988750..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/7f/readonly_9cd53e889a0af1c8ac06d90a7f529692fb7082 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/8e/readonly_9f3e285bae904c5dad085e888395b10ceeab26 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/8e/readonly_9f3e285bae904c5dad085e888395b10ceeab26 deleted file mode 100644 index eca2d30..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/8e/readonly_9f3e285bae904c5dad085e888395b10ceeab26 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/8f/readonly_bc9e7a54d4cd045744e453334f71ee63780c03 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/8f/readonly_bc9e7a54d4cd045744e453334f71ee63780c03 deleted file mode 100644 index 50f03f5..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/8f/readonly_bc9e7a54d4cd045744e453334f71ee63780c03 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/92/readonly_188bae7a779d87d71fb99f7953ed0bda60c6eb b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/92/readonly_188bae7a779d87d71fb99f7953ed0bda60c6eb deleted file mode 100644 index da37f6d..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/92/readonly_188bae7a779d87d71fb99f7953ed0bda60c6eb and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/99/readonly_2c6604f456443ea726645083a1e33ab3ba3abc b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/99/readonly_2c6604f456443ea726645083a1e33ab3ba3abc deleted file mode 100644 index e5186ab..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/99/readonly_2c6604f456443ea726645083a1e33ab3ba3abc and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/9c/readonly_dbbb7b9d0d61f7384a4d05f12dc7e2075fba7c b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/9c/readonly_dbbb7b9d0d61f7384a4d05f12dc7e2075fba7c deleted file mode 100644 index 401326d..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/9c/readonly_dbbb7b9d0d61f7384a4d05f12dc7e2075fba7c and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/a3/readonly_e4fc94c4ef9904a9c3dc43a7692439c8692023 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/a3/readonly_e4fc94c4ef9904a9c3dc43a7692439c8692023 deleted file mode 100644 index 9b63bf5..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/a3/readonly_e4fc94c4ef9904a9c3dc43a7692439c8692023 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/a5/readonly_485ad8e3a1602c46b2e9811abd0452761c1e70 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/a5/readonly_485ad8e3a1602c46b2e9811abd0452761c1e70 deleted file mode 100644 index aa72db6..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/a5/readonly_485ad8e3a1602c46b2e9811abd0452761c1e70 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/ae/readonly_cd3e093eccea0460991fdc918bdda0b58c5c11 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/ae/readonly_cd3e093eccea0460991fdc918bdda0b58c5c11 deleted file mode 100644 index d7f1b13..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/ae/readonly_cd3e093eccea0460991fdc918bdda0b58c5c11 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/c8/readonly_312fd11e35846f0f2f2fb994b40fe1dc4cf948 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/c8/readonly_312fd11e35846f0f2f2fb994b40fe1dc4cf948 deleted file mode 100644 index 9c63a8c..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/c8/readonly_312fd11e35846f0f2f2fb994b40fe1dc4cf948 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/ca/readonly_d3716f06cd3b80418b5bd06b7ddcf844502a58 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/ca/readonly_d3716f06cd3b80418b5bd06b7ddcf844502a58 deleted file mode 100644 index 18edeb5..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/ca/readonly_d3716f06cd3b80418b5bd06b7ddcf844502a58 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d1/readonly_7b920f681623037f9c4d83442aae19716c0744 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d1/readonly_7b920f681623037f9c4d83442aae19716c0744 deleted file mode 100644 index 742e5aa..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d1/readonly_7b920f681623037f9c4d83442aae19716c0744 and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d4/readonly_09b5ac3451619c127ef249a2d75e8e4f0693be b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d4/readonly_09b5ac3451619c127ef249a2d75e8e4f0693be deleted file mode 100644 index bd8b876..0000000 Binary files a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d4/readonly_09b5ac3451619c127ef249a2d75e8e4f0693be and /dev/null differ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d8/readonly_a3be96e59ca11039dd2bd5c482613e90fc0c76 b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d8/readonly_a3be96e59ca11039dd2bd5c482613e90fc0c76 deleted file mode 100644 index 4cca567..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_git/objects/d8/readonly_a3be96e59ca11039dd2bd5c482613e90fc0c76 +++ /dev/null @@ -1,2 +0,0 @@ -x[K1}m~Ű>k}hiUb"Bn&.T;I܇0MsNu'chwY%V\Y\5sv6n泧u?|-r f*Bwhx` - 4. ... - validations: - required: true - - type: textarea - id: expected - attributes: - label: Expected behaviour - validations: - required: true - - type: textarea - id: actual - attributes: - label: Actual behaviour - validations: - required: true - - type: textarea - id: checkhealth - attributes: - label: ":checkhealth herdr-splits output" - description: Paste the relevant output of `:checkhealth herdr-splits` (Neovim ≥ 0.10). - render: shell - validations: - required: false - - type: textarea - id: config - attributes: - label: Setup / config - description: Your `setup({})` call and any relevant keybinds. - render: lua - validations: - required: false - - type: textarea - id: os - attributes: - label: OS / terminal - description: Operating system and terminal emulator (note if Option-as-Alt is enabled on macOS). - placeholder: "macOS 14 / Ghostty (macos-option-as-alt = true)" - validations: - required: false diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/ISSUE_TEMPLATE/feature_request.yml b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/ISSUE_TEMPLATE/feature_request.yml deleted file mode 100644 index 6fecb93..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/ISSUE_TEMPLATE/feature_request.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Feature request -description: Suggest an idea or improvement for herdr-splits.nvim -labels: [enhancement] -body: - - type: textarea - id: problem - attributes: - label: Problem - description: What problem does this solve? What's currently hard or impossible to do? - validations: - required: true - - type: textarea - id: solution - attributes: - label: Proposed solution - description: What would you like herdr-splits.nvim to do instead? - validations: - required: true - - type: textarea - id: alternatives - attributes: - label: Alternatives considered - description: Any workarounds or other approaches you've tried. - validations: - required: false - - type: textarea - id: context - attributes: - label: Additional context - description: Anything else relevant — links, screenshots, related config. - validations: - required: false diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/PULL_REQUEST_TEMPLATE.md b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 992c660..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,31 +0,0 @@ - - -## Summary - - - -## Changes - - - -- - -## Validation - - - -- [ ] `make test` passes -- [ ] `make check-shell` passes -- [ ] Plugin loads with no errors in a Neovim + Herdr session (`HERDR_ENV=1`) -- [ ] `:checkhealth herdr-splits` reports no failures -- [ ] Navigation (``) works across Neovim splits and Herdr panes -- [ ] Resizing (``) works across Neovim splits and Herdr panes -- [ ] Edge cases relevant to this change exercised (at_edge, count prefix, - floats, auto-unzoom) -- [ ] `README.md` / `herdr-plugin.toml` updated (if user-facing) - -## Notes for review - - - -Closes #NN diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/workflows/ci.yml b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/workflows/ci.yml deleted file mode 100644 index 2752c36..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_github/workflows/ci.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: CI - -on: - push: - branches: [main] - pull_request: - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - shell: - name: Bash syntax - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - persist-credentials: false - - run: make check-shell - - test: - name: Neovim ${{ matrix.neovim-version }} - runs-on: ubuntu-latest - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - neovim-version: [v0.10.0, stable] - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - persist-credentials: false - submodules: true - - uses: rhysd/action-setup-vim@febef33995d6649302e9d88dda81e071b68f16a7 # v1.6.1 - with: - neovim: true - version: ${{ matrix.neovim-version }} - - run: make test diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_gitignore b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_gitignore deleted file mode 100644 index f35b8b8..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_gitignore +++ /dev/null @@ -1 +0,0 @@ -.pi-subagents/ diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_gitmodules b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_gitmodules deleted file mode 100644 index 8fbc9e7..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/dot_gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "deps/mini.test"] - path = deps/mini.test - url = https://github.com/nvim-mini/mini.test.git diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/herdr-plugin.toml b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/herdr-plugin.toml deleted file mode 100644 index df6d5ae..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/herdr-plugin.toml +++ /dev/null @@ -1,62 +0,0 @@ -id = "herdr-splits" -name = "Herdr Splits" -version = "0.5.1" -min_herdr_version = "0.7.0" -description = "Seamless navigation and resizing between Herdr panes and Neovim splits" -platforms = ["linux", "macos"] - -# Herdr-side navigation actions. These check if the focused pane is running -# Neovim and either forward the key chord or move Herdr pane focus. -# Bind them in ~/.config/herdr/config.toml: -# [[keys.command]] -# key = "ctrl+h" -# type = "plugin_action" -# command = "herdr-splits.nav-left" - -[[actions]] -id = "nav-left" -title = "Navigate left (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-nav.sh", "left"] - -[[actions]] -id = "nav-down" -title = "Navigate down (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-nav.sh", "down"] - -[[actions]] -id = "nav-up" -title = "Navigate up (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-nav.sh", "up"] - -[[actions]] -id = "nav-right" -title = "Navigate right (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-nav.sh", "right"] - -[[actions]] -id = "resize-left" -title = "Resize left (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-resize.sh", "left"] - -[[actions]] -id = "resize-down" -title = "Resize down (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-resize.sh", "down"] - -[[actions]] -id = "resize-up" -title = "Resize up (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-resize.sh", "up"] - -[[actions]] -id = "resize-right" -title = "Resize right (Neovim/Herder)" -contexts = ["global"] -command = ["bash", "scripts/herdr-resize.sh", "right"] diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/conf.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/conf.lua deleted file mode 100644 index d17b920..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/conf.lua +++ /dev/null @@ -1,236 +0,0 @@ ----herdr-splits shared config file (generated artifact) + notation translator. ----Owns everything about `herdr-splits.conf`: path resolution, reading existing ----managed values, translating Neovim key notation to Herdr chord notation, ----and writing the resolved config back (atomically). Requires nothing else ----from this plugin (avoiding a require-cycle with config.lua). ----@class HerdrSplitsConf -local M = {} - --- Neovim modifier prefix -> Herdr modifier name. -local MOD = { C = 'ctrl', M = 'alt', A = 'alt', S = 'shift', D = 'cmd' } --- Herdr's documented specials: lowercase the terminal key when present. -local SPECIAL = { - left = 'left', right = 'right', up = 'up', down = 'down', - enter = 'enter', ['return'] = 'enter', tab = 'tab', - esc = 'esc', escape = 'esc', space = 'space', backspace = 'backspace', - del = 'delete', delete = 'delete', home = 'home', - ['end'] = 'end', pageup = 'pageup', pagedown = 'pagedown', -} - --- Marker line stamped into every generated conf. Its presence means the file --- is the plugin's own output: setup() is authoritative, so read_managed() does --- NOT adopt it back (removing an opt reverts to the default on the next start). -local MARKER = '# herdr-splits-generated-v1' - -local uv = vim.uv or vim.loop - --- Lazily-resolved cache of the shared config path, so setup() shells out to --- `herdr plugin config-dir` at most once per process. -local resolved_path - ----Resolve the herdr binary: a config.herdr_bin override (when the config ----module is loaded), then HERDR_BIN_PATH, then 'herdr'. pcall-required so ----conf.lua never hard-requires config.lua at load time (cycle-safe). ----@return string -local function resolve_herdr_bin() - local ok, cfg = pcall(require, 'herdr-splits.config') - if ok and cfg.herdr_bin then return cfg.herdr_bin end - return vim.env.HERDR_BIN_PATH or 'herdr' -end - ----Best-effort `herdr plugin config-dir herdr-splits` query. Returns the ----directory printed by herdr (trimmed), or nil on any failure / empty output. ----@return string|nil -local function query_config_dir() - local ok, obj = pcall(vim.system, { resolve_herdr_bin(), 'plugin', 'config-dir', 'herdr-splits' }, { text = true }) - if not ok or not obj then return nil end - local wok, res = pcall(obj.wait, obj) - if not wok or not res or res.code ~= 0 then return nil end - local out = (res.stdout or ''):gsub('^%s+', ''):gsub('%s+$', '') - return out ~= '' and out or nil -end - ----Path to the shared herdr-splits config file (same file the Herdr-side ----scripts read). Precedence: (1) HERDR_SPLITS_CONFIG; (2) HERDR_PLUGIN_CONFIG_DIR ----+ `/herdr-splits.conf`; (3) `herdr plugin config-dir herdr-splits` (via the ----herdr binary) + `/herdr-splits.conf`; (4) XDG_CONFIG_HOME / ~/.config ----fallback. Resolved once and cached, so setup() shells out at most once. ----@return string -function M.path() - if resolved_path then return resolved_path end - if vim.env.HERDR_SPLITS_CONFIG and vim.env.HERDR_SPLITS_CONFIG ~= '' then - resolved_path = vim.env.HERDR_SPLITS_CONFIG - return resolved_path - end - if vim.env.HERDR_PLUGIN_CONFIG_DIR and vim.env.HERDR_PLUGIN_CONFIG_DIR ~= '' then - resolved_path = vim.env.HERDR_PLUGIN_CONFIG_DIR .. '/herdr-splits.conf' - return resolved_path - end - local dir = query_config_dir() - if dir then - resolved_path = dir .. '/herdr-splits.conf' - return resolved_path - end - local xdg = vim.env.XDG_CONFIG_HOME - local base = (xdg and xdg:sub(1, 1) == '/') and xdg - or ((vim.env.HOME or '~') .. '/.config') - resolved_path = base .. '/herdr/plugins/config/herdr-splits/herdr-splits.conf' - return resolved_path -end - ----Translate a Neovim key notation (e.g. ``, ``, `h`) into the ----Herdr chord notation the scripts and `herdr pane send-keys` expect ----(e.g. `ctrl+h`, `alt+left`, `h`). Returns nil for modifier-only / empty ----input so callers can fall back to a per-direction default. ----@param nvim_key string ----@return string|nil -function M.to_herdr(nvim_key) - if type(nvim_key) ~= 'string' or nvim_key == '' then return nil end - if not nvim_key:match('^<.+>$') then return nvim_key:lower() end -- plain "h" -> "h" - local inner = nvim_key:sub(2, -2) - local mods, key = {}, nil - for part in inner:gmatch('[^-]+') do - local m = MOD[part:upper()] - if m then - mods[#mods + 1] = m - else - key = SPECIAL[part:lower()] or part:lower() - end - end - if not key then return nil end - mods[#mods + 1] = key - return table.concat(mods, '+') -end - ----Parse the shared config file for the managed keys only. When the file ----carries the generated MARKER it is the plugin's own output and is NOT read ----back (setup() is authoritative — removing an opt reverts to default). When ----the MARKER is absent (a legacy/hand-edited conf) the managed values are ----parsed and adopted once; the second return value is true only when at ----least one managed value was found, so the caller can emit a one-time ----migration notice. Returns `({}, false)` for a missing/marker-tagged file; ----last occurrence wins (matches the scripts' `tail -n 1`). ----@return table values, boolean adopted -function M.read_managed() - local f = io.open(M.path(), 'r') - if not f then return {}, false end - local out = { nav_keys = {}, resize_keys = {} } - for line in f:lines() do - -- Generated marker anywhere => our own output; do not adopt it back. - if line:match('^%s*' .. vim.pesc(MARKER) .. '%s*$') then - f:close() - return {}, false - end - local k, v = line:match('^%s*([%w_]+)%s*=%s*([^%s#]+)') - if k and v then - local dir = k:match('^nav_key_(%a+)$') - if dir then - out.nav_keys[dir] = v - else - dir = k:match('^resize_key_(%a+)$') - if dir then - out.resize_keys[dir] = v - elseif k == 'unzoom_on_nav' then - out.unzoom_on_nav = (v ~= 'false') - elseif k == 'nav_at_edge' then - out.nav_at_edge = (v == 'stop' and 'stop' or 'wrap') - end - end - end - end - f:close() - local adopted = false - for _, t in pairs({ out.nav_keys, out.resize_keys }) do - for _ in pairs(t) do adopted = true; break end - end - if out.unzoom_on_nav ~= nil or out.nav_at_edge ~= nil then adopted = true end - return out, adopted -end - ----Write the full managed key set to the shared config with a generated-file ----header (including the MARKER), atomically via a unique same-dir temp + ----os.rename so a script never observes a partial write and two concurrent ----Neovim instances don't share a temp inode. Skips the write entirely when the ----content is unchanged (preserves mtime, reduces multi-instance contention). ----Returns (true, nil) on success or (false, err) on failure; callers wrap in ----pcall so a write failure never crashes startup. ----@param resolved table resolved managed config (nav_keys, resize_keys, unzoom_on_nav, nav_at_edge) ----@return boolean ok, string|nil err -function M.write(resolved) - local path = M.path() - local lines = { - MARKER, - '# herdr-splits plugin config — GENERATED by herdr-splits.nvim setup().', - '# Regenerated from defaults + setup() opts on every setup(); do not edit by hand.', - '# A headerless/legacy conf is adopted once on migration (see the startup', - '# notice), then overwritten thereafter — remove an opt in setup() to revert.', - 'nav_key_left=' .. resolved.nav_keys.left, - 'nav_key_down=' .. resolved.nav_keys.down, - 'nav_key_up=' .. resolved.nav_keys.up, - 'nav_key_right=' .. resolved.nav_keys.right, - 'resize_key_left=' .. resolved.resize_keys.left, - 'resize_key_down=' .. resolved.resize_keys.down, - 'resize_key_up=' .. resolved.resize_keys.up, - 'resize_key_right=' .. resolved.resize_keys.right, - 'unzoom_on_nav=' .. (resolved.unzoom_on_nav == false and 'false' or 'true'), - 'nav_at_edge=' .. (resolved.nav_at_edge == 'stop' and 'stop' or 'wrap'), - } - local content = table.concat(lines, '\n') .. '\n' - - -- Skip when unchanged: only when the existing file's bytes match exactly. - local existing = io.open(path, 'r') - if existing then - local prev = existing:read('*a') - existing:close() - if prev == content then return true end - end - - vim.fn.mkdir(vim.fn.fnamemodify(path, ':h'), 'p') - -- Unique same-dir temp so os.rename stays same-filesystem (atomic) and two - -- Neovim instances don't collide on a shared temp inode. - local tmp = path .. '.tmp.' .. vim.fn.getpid() .. '.' .. tostring(uv.hrtime()) - local f, err = io.open(tmp, 'w') - if not f then - pcall(os.remove, tmp) - vim.notify('herdr-splits: failed to open conf temp file: ' .. tostring(err), vim.log.levels.WARN) - return false, err - end - local wok, werr = f:write(content) - -- file:close() flushes buffered output and can itself fail with a delayed - -- write error (disk full, NFS, quota). Its result MUST be checked before - -- os.rename: otherwise an incomplete temp replaces the live config and the - -- atomic-write guarantee is lost. LuaJIT returns true on success or - -- (nil, err) on a flush failure — same form as file:write, checked here too. - local cok, cerr = f:close() - if (not wok) or (not cok) then - local why = (not wok) and werr or cerr - pcall(os.remove, tmp) - vim.notify('herdr-splits: failed to write conf temp file: ' .. tostring(why), vim.log.levels.WARN) - return false, why - end - local ok, rerr = os.rename(tmp, path) - if not ok then - pcall(os.remove, tmp) - vim.notify('herdr-splits: failed to write conf: ' .. tostring(rerr), vim.log.levels.WARN) - end - return ok, rerr -end - ----Runnable self-check for the notation translator. Asserts on the documented ----mapping table; returns true on success. Intended for headless validation: ----`nvim --headless -c "lua assert(require('herdr-splits.conf')._selfcheck())" -c "qa"`. ----@return boolean -function M._selfcheck() - local cases = { - { '', 'ctrl+h' }, { '', 'ctrl+j' }, { '', 'ctrl+k' }, { '', 'ctrl+l' }, - { '', 'alt+h' }, { '', 'alt+left' }, { '', 'shift+left' }, - { '', 'cmd+x' }, { '', 'ctrl+alt+h' }, { 'h', 'h' }, { '', 'esc' }, - } - for _, c in ipairs(cases) do - local got = M.to_herdr(c[1]) - assert(got == c[2], ('to_herdr(%q)=%q want %q'):format(c[1], tostring(got), c[2])) - end - return true -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/config.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/config.lua deleted file mode 100644 index 1763803..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/config.lua +++ /dev/null @@ -1,146 +0,0 @@ ----@class HerdrSplitsConfig ----@field default_amount number Resize amount as Herdr ratio (float, e.g. 0.03 = 3%) ----@field neovim_amount number Resize amount for native Neovim resizes (integer cells, default 3) ----@field at_edge 'wrap'|'stop'|'split'|function Neovim window-edge behavior (distinct from nav_at_edge below) ----@field ignored_buftypes string[] Buffer types ignored during resize ----@field ignored_filetypes string[] Filetypes ignored during resize ----@field move_cursor_same_row boolean Keep cursor on same screen row when moving left/right ----@field herdr_bin string|nil Path to herdr binary (auto-detected if nil) ----@field ignored_events string[] Autocmd events to ignore during resize operations ----@field auto_sync_herdr boolean|nil If true, auto-sync the Herdr-managed checkout to match this lazy commit (opt-in; default false) ----@field floating_zindex_max number Threshold below which a floating window's zindex classifies it as an embedded sidebar (default 50; Neovim's default float zindex) ----@field ignore_previewwindows boolean If true, vim.wo[winid].previewwindow windows (e.g. dadbod `.dbout`) are treated as sidebars (opt-in; default false) ---- Managed config (written to herdr-splits.conf by setup()). Pass Neovim ---- notation (e.g. ``, ``); stored/written in Herdr notation. ----@field nav_keys table Forward chords per direction: {left,down,up,right} (Neovim notation in opts; Herdr notation internally) ----@field resize_keys table Resize forward chords per direction: {left,down,up,right} (Neovim notation in opts; Herdr notation internally) ----@field unzoom_on_nav boolean If true, auto-unzoom when navigating away from a zoomed pane (default true) ----@field nav_at_edge 'wrap'|'stop' Herdr pane-boundary wrap behavior (distinct from at_edge, which is the Neovim window-edge behavior) - --- Managed config defaults (Herdr notation). The single source of truth for --- the key set written to herdr-splits.conf; deep-copied into M below and into --- the setup() merge base so the two cannot drift. -local managed_defaults = { - nav_keys = { left = 'ctrl+h', down = 'ctrl+j', up = 'ctrl+k', right = 'ctrl+l' }, - resize_keys = { left = 'alt+h', down = 'alt+j', up = 'alt+k', right = 'alt+l' }, - unzoom_on_nav = true, - nav_at_edge = 'wrap', -} - -local M = { - default_amount = 0.03, - neovim_amount = 3, - at_edge = 'wrap', - ignored_buftypes = { 'nofile', 'quickfix', 'prompt', 'help', 'terminal' }, - ignored_filetypes = { - 'NvimTree', - -- sidebars - 'neo-tree', - 'snacks_dashboard', - 'snacks_explorer', - 'snacks_picker', - -- DB / REPL / data sidebars - 'dadbod-ui', - 'dbout', - -- outlines / symbols - 'aerial', - 'Outline', - -- diagnostics / quick lists - 'Trouble', - 'quickfix', - }, - move_cursor_same_row = false, - herdr_bin = nil, - ignored_events = { 'BufEnter', 'WinEnter' }, - auto_sync_herdr = false, - floating_zindex_max = 50, - ignore_previewwindows = false, - -- Managed config: deep-copied from managed_defaults (single source). - -- Stored in Herdr chord notation; setup() translates user Neovim notation - -- and writes these to herdr-splits.conf for the scripts. - nav_keys = vim.deepcopy(managed_defaults.nav_keys), - resize_keys = vim.deepcopy(managed_defaults.resize_keys), - unzoom_on_nav = managed_defaults.unzoom_on_nav, - nav_at_edge = managed_defaults.nav_at_edge, -} - -local conf = require('herdr-splits.conf') - ----Apply user configuration on top of defaults and publish the managed keys ----to the shared `herdr-splits.conf` (so the Herdr-side scripts agree). ----Idempotent in outcome: managed keys (nav_keys/resize_keys/unzoom_on_nav/nav_at_edge) ----rebuild from defaults + opts each call; non-managed opts merge into existing config. ---- ----Managed keys (nav_keys/resize_keys/unzoom_on_nav/nav_at_edge) resolve with ----precedence: defaults -> existing conf value (adopt-once) -> explicit opt. ----User chords are given in Neovim notation and translated to Herdr notation ----before merging; the resolved set is written to the conf atomically (write ----failures never crash startup). ----@param opts table|nil -function M.setup(opts) - opts = opts or {} - - -- Apply herdr_bin from opts before the first conf.path() resolution so the - -- documented precedence (config.herdr_bin -> HERDR_BIN_PATH -> 'herdr') holds. - if opts.herdr_bin ~= nil then M.herdr_bin = opts.herdr_bin end - - -- Managed opts: translate user chords nvim -> herdr, capture only what was passed. - local user = {} - if opts.nav_keys then - user.nav_keys = {} - for dir, k in pairs(opts.nav_keys) do user.nav_keys[dir] = conf.to_herdr(k) end - end - if opts.resize_keys then - user.resize_keys = {} - for dir, k in pairs(opts.resize_keys) do user.resize_keys[dir] = conf.to_herdr(k) end - end - if opts.unzoom_on_nav ~= nil then user.unzoom_on_nav = opts.unzoom_on_nav end - if opts.nav_at_edge ~= nil then user.nav_at_edge = opts.nav_at_edge end - - -- Precedence: defaults -> legacy/headerless conf (adopt once) -> explicit - -- user opts. read_managed returns {} (no adoption) once the conf carries - -- our generated marker, so removing an opt reverts to the default next start. - local existing, migrated = conf.read_managed() - local resolved = vim.deepcopy(managed_defaults) - resolved = vim.tbl_deep_extend('force', resolved, existing) - resolved = vim.tbl_deep_extend('force', resolved, user) - - M.nav_keys, M.resize_keys = resolved.nav_keys, resolved.resize_keys - M.unzoom_on_nav, M.nav_at_edge = resolved.unzoom_on_nav, resolved.nav_at_edge - - -- One-time migration notice: a headerless/legacy conf was adopted. Fires - -- once — after this setup() the conf carries the marker, so later setups - -- don't adopt. Tell the user to move these into setup() to persist them. - if migrated then - local parts = {} - for _, kind in ipairs({ 'nav_keys', 'resize_keys' }) do - for dir, v in pairs(existing[kind] or {}) do - parts[#parts + 1] = ('%s.%s=%s'):format(kind, dir, v) - end - end - if existing.unzoom_on_nav ~= nil then - parts[#parts + 1] = 'unzoom_on_nav=' .. tostring(existing.unzoom_on_nav) - end - if existing.nav_at_edge ~= nil then - parts[#parts + 1] = 'nav_at_edge=' .. existing.nav_at_edge - end - vim.notify( - 'herdr-splits: adopted legacy conf values (' .. table.concat(parts, ', ') - .. '). Add them to setup() (Neovim notation) to keep them — the conf is ' - .. 'now regenerated on every setup().', - vim.log.levels.INFO - ) - end - - -- Non-managed opts (default_amount, at_edge, ignored_filetypes, …) merge as before. - local other = vim.deepcopy(opts) - other.nav_keys, other.resize_keys = nil, nil - other.unzoom_on_nav, other.nav_at_edge = nil, nil - local merged = vim.tbl_deep_extend('force', M, other) - for k, v in pairs(merged) do M[k] = v end - - -- Publish to the shared conf for the Herdr scripts (never fatal). - pcall(conf.write, resolved) -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/health.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/health.lua deleted file mode 100644 index 3751026..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/health.lua +++ /dev/null @@ -1,46 +0,0 @@ ----:checkhealth herdr-splits integration. ----Discovered automatically by Neovim's built-in `:checkhealth` via the ----runtimefile lookup in `lua//health.lua`. ----Requires Neovim ≥ 0.10 for `vim.health`. - -local M = {} - -function M.check() - local config = require('herdr-splits.config') - local herdr = require('herdr-splits.herdr') - local win = require('herdr-splits.win') - - vim.health.start('herdr-splits') - - if herdr.is_in_session() then - vim.health.ok( - string.format( - 'Running inside a Herdr session (HERDR_ENV=1, HERDR_PANE_ID=%s)', - tostring(vim.env.HERDR_PANE_ID) - ) - ) - else - vim.health.warn( - 'Not inside a Herdr session (HERDR_ENV=' - .. tostring(vim.env.HERDR_ENV) - .. ') — nav/resize will not cross pane boundaries.' - ) - end - - vim.health.info(string.format('ignored_buftypes: %s', vim.inspect(config.ignored_buftypes))) - vim.health.info(string.format('ignored_filetypes: %s', vim.inspect(config.ignored_filetypes))) - vim.health.info(string.format('floating_zindex_max: %s', tostring(config.floating_zindex_max))) - vim.health.info(string.format('ignore_previewwindows: %s', tostring(config.ignore_previewwindows))) - - if win.is_embedded_floating_window() then - vim.health.warn('Current window is an embedded floating window (zindex < 50) — treat as sidebar.') - end - if win.is_ignored_win() then - vim.health.info('Current window matches an ignored filetype/buftype.') - end - if win.is_floating() and not win.is_embedded_floating_window() then - vim.health.info('Current window is a true floating popup — nav/resize will forward to Herdr.') - end -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/herdr.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/herdr.lua deleted file mode 100644 index a5485ad..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/herdr.lua +++ /dev/null @@ -1,160 +0,0 @@ ----Herdr CLI wrapper. All Herdr subprocess calls go through this module. ----@class HerdrSplitsHerdr -local M = {} - -local config = require('herdr-splits.config') - ----Resolve the herdr binary path. ----@return string -function M.herdr_bin() - return config.herdr_bin or vim.env.HERDR_BIN_PATH or 'herdr' -end - ----Check if Neovim is running inside a Herdr session. ----@return boolean -function M.is_in_session() - return vim.env.HERDR_ENV == '1' and vim.env.HERDR_PANE_ID ~= nil and #vim.env.HERDR_PANE_ID > 0 -end - ----Get the current Herdr pane ID. ----@return string|nil -function M.current_pane_id() - if not M.is_in_session() then - return nil - end - return vim.env.HERDR_PANE_ID -end - ----Run a herdr CLI command and return stdout, stderr, and exit code. ----@param args string[] ----@return string stdout, string stderr, number exit_code -local function herdr_exec(args) - local cmd = vim.list_extend({ M.herdr_bin() }, args, 1, #args) - local obj = vim.system(cmd, { text = true }):wait() - return obj.stdout, obj.stderr, obj.code -end - ----Check if the current Herdr pane is at the layout boundary in the given direction. ----Calls `herdr pane edges --current` and parses the JSON response. ----@param direction '"left"'|'"right"'|'"up"'|'"down"' ----@return boolean|nil true if at edge, false if neighbor exists, nil on error -function M.current_pane_at_edge(direction) - if not M.is_in_session() then - return nil - end - - local edge_key = direction - local stdout, _, code = herdr_exec({ 'pane', 'edges', '--current' }) - - if code ~= 0 or not stdout or #stdout == 0 then - return nil - end - - local ok, data = pcall(vim.json.decode, stdout) - if - not ok - or type(data) ~= 'table' - or type(data.result) ~= 'table' - or type(data.result.edges) ~= 'table' - then - return nil - end - - local at_edge = data.result.edges[edge_key] - if type(at_edge) ~= 'boolean' then - return nil - end - return at_edge -end - ----Check if the current Herdr pane is zoomed. ----Calls `herdr pane layout --current` and parses JSON. ----@return boolean|nil true if zoomed, false if not, nil on error -function M.current_pane_is_zoomed() - if not M.is_in_session() then - return nil - end - - local stdout, _, code = herdr_exec({ 'pane', 'layout', '--current' }) - - if code ~= 0 or not stdout or #stdout == 0 then - return nil - end - - local ok, data = pcall(vim.json.decode, stdout) - if - not ok - or type(data) ~= 'table' - or type(data.result) ~= 'table' - or type(data.result.layout) ~= 'table' - then - return nil - end - - local zoomed = data.result.layout.zoomed - if type(zoomed) ~= 'boolean' then - return nil - end - return zoomed -end - ----Focus a Herdr pane in the given direction. ----Calls `herdr pane focus --direction --current`. ----@param direction '"left"'|'"right"'|'"up"'|'"down"' ----@return boolean true on success -function M.focus_pane(direction) - if not M.is_in_session() then - return false - end - - local _, _, code = herdr_exec({ 'pane', 'focus', '--direction', direction, '--current' }) - return code == 0 -end - ----Unzoom the current Herdr pane (turn off zoom). ----Calls `herdr pane zoom --off --current`. ----@return boolean true on success -function M.unzoom() - if not M.is_in_session() then - return false - end - - local _, _, code = herdr_exec({ 'pane', 'zoom', '--off', '--current' }) - return code == 0 -end - ----Check whether auto-unzoom is enabled. ----Reads `config.unzoom_on_nav` (resolved from setup(); default: enabled). ----@return boolean -function M.unzoom_enabled() - return config.unzoom_on_nav ~= false -end - ----Edge-wrap behavior across the Herdr pane boundary, read from the resolved ----in-memory config (the same value written to the shared conf that the ----Herdr-side scripts read). `stop` suppresses wrap-across-boundary on both ----the plain-pane side (handled by the Herdr script) and the Neovim ----edge-wrap side (handled here). Anything else defaults to `wrap`. ----@return '"wrap"'|'"stop"' -function M.nav_at_edge() - return config.nav_at_edge == 'stop' and 'stop' or 'wrap' -end - ----Resize the current Herdr pane in the given direction. ----Calls `herdr pane resize --direction --amount --current`. ----@param direction '"left"'|'"right"'|'"up"'|'"down"' ----@param amount number Float ratio (e.g., 0.03 = 3% of terminal dimension) ----@return boolean true on success -function M.resize_pane(direction, amount) - if not M.is_in_session() then - return false - end - - local amount_str = string.format('%.4f', amount) - local _, _, code = herdr_exec({ - 'pane', 'resize', '--direction', direction, '--amount', amount_str, '--current', - }) - return code == 0 -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/init.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/init.lua deleted file mode 100644 index 3782090..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/init.lua +++ /dev/null @@ -1,162 +0,0 @@ ----herdr-splits.nvim — Seamless navigation and resizing between Neovim splits ----and Herdr panes. Makes Herdr terminal splits behave like native Neovim windows. ---- ----Usage: ---- require('herdr-splits').setup({ ... }) ---- vim.keymap.set('n', '', require('herdr-splits').move_cursor_left) ---- vim.keymap.set('n', '', require('herdr-splits').resize_left) - -local config = require('herdr-splits.config') -local nav = require('herdr-splits.nav') -local resize_mod = require('herdr-splits.resize') -local win = require('herdr-splits.win') -local sync = require('herdr-splits.sync') - -local M = {} - ----Apply configuration. Idempotent — calling again merges into existing config. ----@param opts table|nil Configuration options (see config.lua for defaults) -function M.setup(opts) - config.setup(opts) - pcall(sync.sync) -end - ----Sync the Herdr-managed checkout to match this lazy commit. ----Intended as a lazy.nvim `build` hook entry point; respects `auto_sync_herdr`. ----Safe to call at any time; no-op unless opted in. -function M.sync_herdr() - pcall(sync.sync) -end - ----Resize the current split to the left. ----Amount defaults to config.default_amount. Multiplied by vim.v.count1. ----@param amount number|nil -function M.resize_left(amount) - local eventignore_orig = vim.o.eventignore - vim.o.eventignore = table.concat(config.ignored_events, ',') - resize_mod.is_resizing = true - local cur_win = vim.api.nvim_get_current_win() - local ok, err = pcall(resize_mod.resize, 'left', amount) - if not ok then - vim.notify('herdr-splits: resize_left failed: ' .. tostring(err), vim.log.levels.ERROR) - end - pcall(vim.api.nvim_set_current_win, cur_win) - resize_mod.is_resizing = false - vim.o.eventignore = eventignore_orig -end - ----Resize the current split downward. ----@param amount number|nil -function M.resize_down(amount) - local eventignore_orig = vim.o.eventignore - vim.o.eventignore = table.concat(config.ignored_events, ',') - resize_mod.is_resizing = true - local cur_win = vim.api.nvim_get_current_win() - local ok, err = pcall(resize_mod.resize, 'down', amount) - if not ok then - vim.notify('herdr-splits: resize_down failed: ' .. tostring(err), vim.log.levels.ERROR) - end - pcall(vim.api.nvim_set_current_win, cur_win) - resize_mod.is_resizing = false - vim.o.eventignore = eventignore_orig -end - ----Resize the current split upward. ----@param amount number|nil -function M.resize_up(amount) - local eventignore_orig = vim.o.eventignore - vim.o.eventignore = table.concat(config.ignored_events, ',') - resize_mod.is_resizing = true - local cur_win = vim.api.nvim_get_current_win() - local ok, err = pcall(resize_mod.resize, 'up', amount) - if not ok then - vim.notify('herdr-splits: resize_up failed: ' .. tostring(err), vim.log.levels.ERROR) - end - pcall(vim.api.nvim_set_current_win, cur_win) - resize_mod.is_resizing = false - vim.o.eventignore = eventignore_orig -end - ----Resize the current split to the right. ----@param amount number|nil -function M.resize_right(amount) - local eventignore_orig = vim.o.eventignore - vim.o.eventignore = table.concat(config.ignored_events, ',') - resize_mod.is_resizing = true - local cur_win = vim.api.nvim_get_current_win() - local ok, err = pcall(resize_mod.resize, 'right', amount) - if not ok then - vim.notify('herdr-splits: resize_right failed: ' .. tostring(err), vim.log.levels.ERROR) - end - pcall(vim.api.nvim_set_current_win, cur_win) - resize_mod.is_resizing = false - vim.o.eventignore = eventignore_orig -end - ----Move cursor to the left, crossing into Herdr pane if at Neovim edge. ----@param opts table|nil { same_row: boolean|nil, at_edge: string|function|nil } -function M.move_cursor_left(opts) - resize_mod.is_resizing = false - local ok, err = pcall(nav.move_cursor, 'left', opts) - if not ok then - vim.notify('herdr-splits: move_cursor_left failed: ' .. tostring(err), vim.log.levels.ERROR) - end -end - ----Move cursor downward, crossing into Herdr pane if at Neovim edge. ----@param opts table|nil -function M.move_cursor_down(opts) - resize_mod.is_resizing = false - local ok, err = pcall(nav.move_cursor, 'down', opts) - if not ok then - vim.notify('herdr-splits: move_cursor_down failed: ' .. tostring(err), vim.log.levels.ERROR) - end -end - ----Move cursor upward, crossing into Herdr pane if at Neovim edge. ----@param opts table|nil -function M.move_cursor_up(opts) - resize_mod.is_resizing = false - local ok, err = pcall(nav.move_cursor, 'up', opts) - if not ok then - vim.notify('herdr-splits: move_cursor_up failed: ' .. tostring(err), vim.log.levels.ERROR) - end -end - ----Move cursor to the right, crossing into Herdr pane if at Neovim edge. ----@param opts table|nil -function M.move_cursor_right(opts) - resize_mod.is_resizing = false - local ok, err = pcall(nav.move_cursor, 'right', opts) - if not ok then - vim.notify('herdr-splits: move_cursor_right failed: ' .. tostring(err), vim.log.levels.ERROR) - end -end - ----Append a filetype to ignored_filetypes at runtime (de-duped). ----@param name string Filetype name, e.g. 'fugitive' ----@return boolean true if added, false if already present -function M.add_ignored_filetype(name) - for _, v in ipairs(config.ignored_filetypes) do - if v == name then - return false - end - end - table.insert(config.ignored_filetypes, name) - return true -end - ----Append a buftype to ignored_buftypes at runtime (de-duped). ----@param name string Buffer type, e.g. 'help' ----@return boolean true if added, false if already present -function M.add_ignored_buftype(name) - for _, v in ipairs(config.ignored_buftypes) do - if v == name then - return false - end - end - table.insert(config.ignored_buftypes, name) - return true -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/nav.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/nav.lua deleted file mode 100644 index 56ecca3..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/nav.lua +++ /dev/null @@ -1,206 +0,0 @@ ----Navigation logic: seamless movement between Neovim splits and Herdr panes. ----@class HerdrSplitsNav -local M = {} - -local config = require('herdr-splits.config') -local herdr = require('herdr-splits.herdr') -local win = require('herdr-splits.win') - ----Treat the current window as a sidebar that should not be navigated through. ----Combines the configured ignore lists with the embedded-float heuristic. ----@return boolean -local function is_sidebar() - return win.is_ignored_or_preview() or win.is_embedded_floating_window() -end - ----Split a new Neovim window using the user's placement preferences. ----@param direction '"left"'|'"right"'|'"up"'|'"down"' -local function split_edge(direction) - if direction == 'left' or direction == 'right' then - vim.cmd('vsp') - else - vim.cmd('sp') - end -end - ----Move cursor between Neovim splits, falling through to Herdr at edges. ----This is the core navigation function. ----@param direction '"left"'|'"right"'|'"up"'|'"down"' ----@param opts table|nil { same_row: boolean|nil, at_edge: string|function|nil } -function M.move_cursor(direction, opts) - local same_row = config.move_cursor_same_row - local at_edge_behavior = config.at_edge - - if type(opts) == 'table' then - if opts.same_row ~= nil then - same_row = opts.same_row - end - if opts.at_edge ~= nil then - at_edge_behavior = opts.at_edge - end - end - - -- Handle floating windows: just forward to Herdr, - -- EXCEPT for embedded sidebars (snacks/neo-tree float/aerial float): - -- those should stay in Neovim so the user can keep interacting - -- with the picker. - if win.is_floating() and not win.is_embedded_floating_window() then - herdr.focus_pane(direction) - return - end - - local dir_key = win.dir_keys[direction] - local offset = vim.fn.winline() + vim.api.nvim_win_get_position(0)[1] - - -- Save current window to detect if wincmd changes it - local prev_win = vim.api.nvim_get_current_win() - - -- Try moving within Neovim first - local will_wrap = false - local count = vim.v.count1 - local target_winnr = vim.fn.winnr(count .. dir_key) - if count > 1 then - local prev_winnr = vim.fn.winnr((count - 1) .. dir_key) - will_wrap = target_winnr == prev_winnr - else - will_wrap = target_winnr == vim.fn.winnr() - end - - -- Command-line window (q:, q/, q?): Neovim forbids all window commands - -- (E11). Never wincmd; at a Neovim screen edge, delegate to Herdr - -- (subprocess-safe, does not close the cmdwin); otherwise silent no-op. - -- Mirrors smart-splits.nvim PR #464. - if win.is_command_line_window() then - if will_wrap and herdr.is_in_session() then - local at_herdr_edge = herdr.current_pane_at_edge(direction) - if at_herdr_edge == false then - herdr.focus_pane(direction) - elseif at_herdr_edge == true and herdr.nav_at_edge() ~= 'stop' then - herdr.focus_pane(win.reverse_direction[direction]) - end - end - return - end - - -- Execute the wincmd - if will_wrap and count == 1 then - vim.cmd('wincmd ' .. dir_key) - else - vim.cmd(count .. 'wincmd ' .. dir_key) - end - - if vim.api.nvim_get_current_win() ~= prev_win then - -- Moved within Neovim. Restore same-row if configured. - if (direction == 'left' or direction == 'right') and same_row then - local row = offset - vim.api.nvim_win_get_position(0)[1] - if row > 0 then - vim.cmd('normal! ' .. row .. 'H') - end - end - return - end - - -- We're at a Neovim edge. Try to cross into Herdr. - if not herdr.is_in_session() then - if will_wrap and count == 1 then - local sidebar = is_sidebar() - if type(at_edge_behavior) == 'function' then - at_edge_behavior({ - direction = direction, - split = function() split_edge(direction) end, - is_sidebar = sidebar, - wrap = function() - vim.cmd('wincmd ' .. win.dir_keys_reverse[direction]) - end, - }) - elseif at_edge_behavior == 'stop' then - return - elseif at_edge_behavior == 'split' then - if not sidebar then - split_edge(direction) - end - else -- 'wrap' (default) - -- Wrap is allowed even from filetype-based sidebars (dbui, neo-tree, - -- ...) so the user can leave them; only embedded floats stay gated. - if not win.is_embedded_floating_window() then - vim.cmd('wincmd ' .. win.dir_keys_reverse[direction]) - end - end - end - return - end - - -- Check zoom state: unzoom first, then retry Neovim navigation. - -- Must happen BEFORE the at_herdr_edge check — when zoomed, the pane fills - -- the screen so herdr reports it as being at every edge, making - -- at_herdr_edge useless until we unzoom. - if herdr.unzoom_enabled() and herdr.current_pane_is_zoomed() then - herdr.unzoom() - -- Retry wincmd — other Neovim splits may now be visible - vim.cmd('wincmd ' .. dir_key) - if vim.api.nvim_get_current_win() ~= prev_win then - if (direction == 'left' or direction == 'right') and same_row then - local row = offset - vim.api.nvim_win_get_position(0)[1] - if row > 0 then - vim.cmd('normal! ' .. row .. 'H') - end - end - return - end - -- Still at edge after unzoom; fall through to Herdr edge check. - end - - -- Check if we're at the Herdr edge too - local at_herdr_edge = herdr.current_pane_at_edge(direction) - if at_herdr_edge == nil then - if will_wrap and count == 1 and not win.is_embedded_floating_window() then - vim.cmd('wincmd ' .. win.dir_keys_reverse[direction]) - end - return - end - - if not at_herdr_edge then - -- There's a Herdr pane in this direction. Cross the boundary. - local moved = herdr.focus_pane(direction) - if not moved and will_wrap and count == 1 and not win.is_embedded_floating_window() then - vim.cmd('wincmd ' .. win.dir_keys_reverse[direction]) - end - return - end - - -- At both Neovim AND Herdr edges (no herdr pane to cross into). - -- Apply at_edge behavior. (Any needed unzoom already happened above.) - if type(at_edge_behavior) == 'function' then - at_edge_behavior({ - direction = direction, - split = function() split_edge(direction) end, - is_sidebar = is_sidebar(), - wrap = function() - vim.cmd('wincmd ' .. win.dir_keys_reverse[direction]) - end, - }) - elseif at_edge_behavior == 'stop' then - return - elseif at_edge_behavior == 'split' then - if not is_sidebar() then - split_edge(direction) - end - else -- 'wrap' (default) - -- Wrap is allowed from filetype-based sidebars (dbui, neo-tree, ...) so - -- you can leave them at an edge; only embedded floating overlays stay gated. - if will_wrap and count == 1 and not win.is_embedded_floating_window() then - -- Wrap to the opposite side. If a Herdr pane exists there AND nav_at_edge - -- allows wrap-across-boundary (the default), cross into it; otherwise - -- wrap within Neovim. nav_at_edge=stop keeps the wrap inside Neovim. - if herdr.nav_at_edge() ~= 'stop' - and herdr.current_pane_at_edge(win.reverse_direction[direction]) == false - then - herdr.focus_pane(win.reverse_direction[direction]) - else - vim.cmd('wincmd ' .. win.dir_keys_reverse[direction]) - end - end - end -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/resize.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/resize.lua deleted file mode 100644 index ff94999..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/resize.lua +++ /dev/null @@ -1,108 +0,0 @@ ----Resize logic: seamless resize between Neovim splits and Herdr panes. ---- ----Mental model (same as smart-splits.nvim): ---- The direction (up/down/left/right) is which way to move the split border. ---- The +/- operator depends on whether current window is above/below or ---- left/right of the neighbor being resized against. ---- ----When at a Neovim edge with no neighbor in that direction, and the window ----fills the terminal, the resize is forwarded to Herdr. ----@class HerdrSplitsResize -local M = {} - -local config = require('herdr-splits.config') -local herdr = require('herdr-splits.herdr') -local win = require('herdr-splits.win') - -M.is_resizing = false - ----Compute the +/- operator for a vertical resize. ----At start/middle: resize_up shrinks (-), resize_down grows (+). ----At last (bottom): inverted — resize_up grows (+), resize_down shrinks (-). ----@param direction '"up"'|'"down"' ----@return '"+""'|'"-""' -local function compute_vertical(direction) - local pos = win.win_position(direction) - if pos == 'start' or pos == 'middle' then - return direction == 'down' and '+' or '-' - end - return direction == 'down' and '-' or '+' -end - ----Compute the +/- operator for a horizontal resize. ----At start/middle: resize_left shrinks (-), resize_right grows (+). ----At last (right): inverted — resize_left grows (+), resize_right shrinks (-). ----@param direction '"left"'|'"right"' ----@return '"+""'|'"-""' -local function compute_horizontal(direction) - local pos = win.win_position(direction) - if pos == 'start' or pos == 'middle' then - return direction == 'right' and '+' or '-' - end - return direction == 'right' and '-' or '+' -end - ----Resize in a direction. ----@param direction '"left"'|'"right"'|'"up"'|'"down"' ----@param amount number|nil Override amount in Neovim cells. When nil, uses ---- vim.v.count1 * neovim_amount for native or count * default_amount for Herdr. -function M.resize(direction, amount) - local count = vim.v.count1 - local has_explicit = amount ~= nil - - -- Embedded floating sidebars (snacks float, neo-tree float, aerial float): - -- refuse to resize; the picker owns its own dimensions. - if win.is_embedded_floating_window() then - return - end - - -- Floating windows: forward to Herdr - if win.is_floating() then - local ratio = has_explicit and amount or (count * config.default_amount) - herdr.resize_pane(direction, ratio) - return - end - - -- Delegate to Herdr ONLY when at both Neovim edges in this dimension - -- AND the window fills the terminal (full_width or full_height). - local delegate = false - -- Never delegate from inside a sidebar; the ignore list applies to resize - -- too. The command-line window is exempted: it is `nofile` (so it trips this - -- rule) yet a full-width cmdwin should still resize the Herdr pane sideways. - local in_sidebar = win.is_ignored_or_preview() - if direction == 'left' or direction == 'right' then - delegate = win.is_full_width() and win.at_left_edge() and win.at_right_edge() and herdr.is_in_session() - else - delegate = win.is_full_height() and win.at_top_edge() and win.at_bottom_edge() and herdr.is_in_session() - end - if delegate and in_sidebar and not win.is_command_line_window() then - delegate = false - end - - if delegate and herdr.current_pane_is_zoomed() then - delegate = false - end - - if delegate then - local ratio = (has_explicit and amount < 1) and amount or (count * config.default_amount) - herdr.resize_pane(direction, ratio) - return - end - - -- Native Neovim resize - local cells = has_explicit and math.floor(amount) or (count * config.neovim_amount) - if cells <= 0 then - cells = 1 - end - - local is_horiz = direction == 'left' or direction == 'right' - local op = is_horiz and compute_horizontal(direction) or compute_vertical(direction) - - if is_horiz then - pcall(vim.cmd, 'vertical resize ' .. op .. cells) - else - pcall(vim.cmd, 'resize ' .. op .. cells) - end -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/sync.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/sync.lua deleted file mode 100644 index ddef394..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/sync.lua +++ /dev/null @@ -1,107 +0,0 @@ ----Auto-sync the Herdr-managed checkout to match the lazy.nvim checkout. ---- ----Herdr has no `plugin update` command in v1; the only sanctioned refresh is ----reinstall from GitHub. When lazy.nvim pulls a new commit, the bash scripts ----under the Herdr-managed checkout stay frozen at the old commit unless the ----user manually reinstalls. This module closes that gap: it reinstalls the ----Herdr-managed checkout pinned to the exact commit lazy fetched, so the bash ----scripts match the lua side byte-for-byte. ---- ----Entirely a no-op unless `auto_sync_herdr = true` is set in setup(). Also a ----no-op when: the herdr binary is unavailable, the plugin is installed as a ----local link (dev mode — reinstall would be refused anyway), the plugin is not ----installed, or the commits already match. -local M = {} - -local config = require('herdr-splits.config') - ----Plugin id and GitHub source as used by `herdr plugin install`. -local PLUGIN_ID = 'herdr-splits' -local PLUGIN_SOURCE = 'lmilojevicc/herdr-splits.nvim' - ----Run the sync. Safe to call at any time; never throws. -function M.sync() - if config.auto_sync_herdr ~= true then - return - end - - local ok, err = pcall(function() - local bin = config.herdr_bin or vim.env.HERDR_BIN_PATH or 'herdr' - if vim.fn.executable(bin) ~= 1 then - return - end - - -- Resolve this plugin's own checkout root (the lazy clone). - local source = debug.getinfo(1, 'S').source -- "@/lua/herdr-splits/sync.lua" - local this_file = source:sub(2) -- strip leading '@' - local plugin_root = vim.fn.fnamemodify(this_file, ':p:h:h:h') -- up 3: file<-herdr-splits<-lua<-root - if vim.fn.isdirectory(plugin_root .. '/.git') == 0 - and vim.fn.filereadable(plugin_root .. '/herdr-plugin.toml') == 0 then - return -- not a real checkout - end - - -- Get the lazy checkout HEAD. - local obj = vim.system({ 'git', '-C', plugin_root, 'rev-parse', 'HEAD' }, { text = true }):wait() - if obj.code ~= 0 then - return - end - local lazy_sha = vim.trim(obj.stdout or '') - if lazy_sha == '' then - return - end - - -- Get the managed install info. - local obj2 = vim.system({ bin, 'plugin', 'list', '--plugin', PLUGIN_ID, '--json' }, { text = true }):wait() - if obj2.code ~= 0 then - return - end - - local decoded, data = pcall(vim.json.decode, obj2.stdout or '') - if not decoded or type(data) ~= 'table' then - return - end - - -- Output may be a single object or an array; find our entry. - local entry = data - if data[1] ~= nil then - for _, e in ipairs(data) do - if e.plugin_id == PLUGIN_ID then - entry = e - break - end - end - end - - local src = entry and entry.source - if not src then - return - end - -- Dev mode (plugin link) or unknown kind: nothing to do. - if src.kind ~= 'github' then - return - end - - -- Already in sync? - local managed_sha = vim.trim(src.resolved_commit or '') - if managed_sha ~= '' and managed_sha:lower() == lazy_sha:lower() then - return - end - - -- Reinstall pinned to the lazy commit. - local obj3 = vim.system( - { bin, 'plugin', 'install', PLUGIN_SOURCE, '--ref', lazy_sha, '--yes' }, - { text = true } - ):wait() - if obj3.code == 0 then - vim.notify('herdr-splits: synced Herdr-side scripts to ' .. lazy_sha:sub(1, 7), vim.log.levels.INFO) - else - vim.notify('herdr-splits: Herdr-side sync skipped (install failed; local link or offline)', vim.log.levels.INFO) - end - end) - - if not ok then - vim.notify('herdr-splits: sync error: ' .. tostring(err), vim.log.levels.DEBUG) - end -end - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/win.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/win.lua deleted file mode 100644 index 47f6821..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/lua/herdr-splits/win.lua +++ /dev/null @@ -1,154 +0,0 @@ ----Window utility functions for Neovim split detection. ----@class HerdrSplitsWin -local M = {} - -local config = require('herdr-splits.config') - ----Check if the current window spans the full terminal width. ----@param winid number|nil window ID, defaults to current ----@return boolean -function M.is_full_width(winid) - return vim.api.nvim_win_get_width(winid or 0) == vim.o.columns -end - ----Check if the current window spans the full terminal height. ----Accounts for cmdheight, statusline, and tabline. ----@param winid number|nil window ID, defaults to current ----@return boolean -function M.is_full_height(winid) - local height = vim.o.lines - vim.o.cmdheight - local tabpages = #vim.api.nvim_list_tabpages() - local wins = #vim.api.nvim_tabpage_list_wins(0) - - if (vim.o.laststatus == 1 and wins > 1) or vim.o.laststatus > 1 then - height = height - 1 - end - if (vim.o.showtabline == 1 and tabpages > 1) or vim.o.showtabline == 2 then - height = height - 1 - end - - return vim.api.nvim_win_get_height(winid or 0) == height -end - ----@return boolean -function M.at_left_edge() - return vim.fn.winnr() == vim.fn.winnr('h') -end - ----@return boolean -function M.at_right_edge() - return vim.fn.winnr() == vim.fn.winnr('l') -end - ----@return boolean -function M.at_top_edge() - return vim.fn.winnr() == vim.fn.winnr('k') -end - ----@return boolean -function M.at_bottom_edge() - return vim.fn.winnr() == vim.fn.winnr('j') -end - ----Determine where the current window sits in the Neovim split layout ----for a given direction (horizontal or vertical). ----@param direction '"left"'|'"right"'|'"up"'|'"down"' ----@return '"start"'|'"middle"'|'"last"' -function M.win_position(direction) - if direction == 'left' or direction == 'right' then - if M.at_left_edge() then - return 'start' - end - if M.at_right_edge() then - return 'last' - end - return 'middle' - end - - if M.at_top_edge() then - return 'start' - end - if M.at_bottom_edge() then - return 'last' - end - return 'middle' -end - ----Check if a window should be ignored during resize operations. ----@param winid number|nil window ID, defaults to current ----@return boolean -function M.is_ignored_win(winid) - local bufnr = vim.api.nvim_win_get_buf(winid or 0) - return vim.tbl_contains(config.ignored_buftypes, vim.api.nvim_get_option_value('buftype', { buf = bufnr })) - or vim.tbl_contains(config.ignored_filetypes, vim.api.nvim_get_option_value('filetype', { buf = bufnr })) -end - ----Check if the current window is a floating window. ----@param winid number|nil ----@return boolean -function M.is_floating(winid) - return vim.api.nvim_win_get_config(winid or 0).relative ~= '' -end - ----Check if a window is an "embedded" floating window — one that is technically ----floating (relative ~= '') but visually behaves like a sidebar (e.g. snacks ----explorer). Neovim's default floating zindex is 50; anything explicitly set ----below that signals the window is meant to coexist with normal splits. ----@param winid number|nil window ID, defaults to current ----@return boolean -function M.is_embedded_floating_window(winid) - if not M.is_floating(winid) then - return false - end - local cfg = vim.api.nvim_win_get_config(winid or 0) - local threshold = config.floating_zindex_max or 50 - return cfg.zindex ~= nil and cfg.zindex < threshold -end - ----Same as M.is_ignored_win but also checks previewwindow when opt-in. ----@param winid number|nil window ID, defaults to current ----@return boolean -function M.is_ignored_or_preview(winid) - if M.is_ignored_win(winid) then - return true - end - if config.ignore_previewwindows then - local ok, pw = pcall(vim.api.nvim_win_get_option, winid or 0, 'previewwindow') - if ok and pw then - return true - end - end - return false -end - ----Returns true while Neovim's command-line window (q:, q/, q?) is open. ----Inside it all window commands raise E11, so callers must short-circuit. ----@return boolean -function M.is_command_line_window() - return vim.fn.getcmdwintype() ~= '' -end - ----Direction key shorthand for wincmd. -M.dir_keys = { - left = 'h', - right = 'l', - up = 'k', - down = 'j', -} - -M.dir_keys_reverse = { - left = 'l', - right = 'h', - up = 'j', - down = 'k', -} - ----Reverse of a direction name: left<->right, up<->down. -M.reverse_direction = { - left = 'right', - right = 'left', - up = 'down', - down = 'up', -} - -return M diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/plugin/herdr-splits.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/plugin/herdr-splits.lua deleted file mode 100644 index 4d32363..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/plugin/herdr-splits.lua +++ /dev/null @@ -1,11 +0,0 @@ --- herdr-splits.nvim plugin bootstrap. --- This file is loaded by Neovim when the plugin is found on the runtimepath. --- It defers all work to `require('herdr-splits')`. - -if vim.g.loaded_herdr_splits then - return -end -vim.g.loaded_herdr_splits = true - --- Defer loading until user calls setup() or invokes a function. --- The main module is available as require('herdr-splits'). diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/executable_herdr-nav.sh b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/executable_herdr-nav.sh deleted file mode 100644 index 9cdbbb7..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/executable_herdr-nav.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env bash -# Herdr navigation helper — used by herdr keybinds for seamless two-way nav. -# -# When a navigation key is pressed in Herdr: -# 1. Check if the focused pane is running Neovim in the foreground. -# - If yes: forward the key chord into that pane. The Neovim plugin owns -# in-split movement, edge crossing, and unzoom — do NOT unzoom here, or -# moving between Neovim splits would incorrectly unzoom the pane. -# 2. If no (a plain Herdr pane): unzoom if needed, then move Herdr pane focus. -# At a layout edge, focus wraps around to the opposite side (smart-splits -# style), so navigating past the last pane lands on the first — unless -# `nav_at_edge=stop`, in which case it halts at the edge. -# -# Auto-unzoom is configurable via `unzoom_on_nav=false` in -# `~/.config/herdr/plugins/config/herdr-splits/herdr-splits.conf` -# (same file the Neovim plugin reads). Default: enabled. -# -# Edge behaviour for plain Herdr panes is configurable via `nav_at_edge` in -# the same conf file: `wrap` (default; wraps to the opposite side at an edge) -# or `stop` (navigation halts at the edge instead of wrapping). -# -# Usage: herdr-nav.sh - -set -euo pipefail - -dir="${1:?usage: herdr-nav.sh }" -herdr="${HERDR_BIN_PATH:-herdr}" - -case "$dir" in - left) key="ctrl+h"; config_key="nav_key_left"; opp="right" ;; - down) key="ctrl+j"; config_key="nav_key_down"; opp="up" ;; - up) key="ctrl+k"; config_key="nav_key_up"; opp="down" ;; - right) key="ctrl+l"; config_key="nav_key_right"; opp="left" ;; - *) echo "herdr-nav.sh: unknown direction: $dir" >&2; exit 2 ;; -esac - -# Resolve `unzoom_on_nav` and `nav_at_edge` from the shared config file. -# Defaults: unzoom enabled, nav_at_edge=wrap (backward compatible). -unzoom=1 -nav_at_edge=wrap -config_path="${HERDR_SPLITS_CONFIG:-${HERDR_PLUGIN_CONFIG_DIR:-$HOME/.config/herdr/plugins/config/herdr-splits}/herdr-splits.conf}" -if [ -r "$config_path" ]; then - configured_key=$(sed -n -E "s/^[[:space:]]*${config_key}[[:space:]]*=[[:space:]]*([^[:space:]#]+).*$/\\1/p" "$config_path" | tail -n 1) - if [ -n "$configured_key" ]; then - key="$configured_key" - fi - if grep -Eq '^[[:space:]]*unzoom_on_nav[[:space:]]*=[[:space:]]*false' "$config_path"; then - unzoom=0 - fi - if grep -Eq '^[[:space:]]*nav_at_edge[[:space:]]*=[[:space:]]*stop' "$config_path"; then - nav_at_edge=stop - fi -fi - -# Get focused pane ID from server (best-effort; empty is fine — we fall -# through to the non-vim path below, which uses --current directly). -pane_id=$("$herdr" pane current --current 2>/dev/null | grep -o '"pane_id"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"$/\1/' || true) - -# Check if focused pane is running vim/nvim as foreground process. -is_vim=0 -if [ -n "$pane_id" ] && pane_info=$("$herdr" pane process-info --current 2>/dev/null); then - if echo "$pane_info" | grep -qiE '"name"[[:space:]]*:[[:space:]]*"(g?(view|l?n?vim?x?)(diff)?)"' 2>/dev/null; then - is_vim=1 - fi -fi - -# Vim pane: forward the chord; the Neovim plugin decides movement + unzoom. -if [ "$is_vim" -eq 1 ]; then - exec "$herdr" pane send-keys "$pane_id" "$key" -fi - -# --- Non-vim Herdr pane: unzoom if needed, then focus (wrapping at edges) --- - -# `pane edges` reports both edge flags and the zoomed state in one call. -edges_out=$("$herdr" pane edges --current 2>/dev/null || true) - -# A zoomed pane fills the tab and reports itself at every edge, so the edge -# flags are useless for the wrap decision. Unzoom (if enabled) so we can -# trust them. If unzoom is disabled we leave zoom untouched and must NOT use -# the (all-true) edge flags — wrap is skipped below in that case. -edges_trusted=1 -if printf '%s' "$edges_out" | grep -q '"zoomed"[[:space:]]*:[[:space:]]*true'; then - if [ "$unzoom" -eq 1 ]; then - "$herdr" pane zoom --off --current 2>/dev/null || true - # Layout changed; re-read edges so the wrap check is accurate. - edges_out=$("$herdr" pane edges --current 2>/dev/null || true) - else - edges_trusted=0 - fi -fi - -# Move to the neighbor in the requested direction. When already at the -# requested edge (no neighbor there): wrap to the opposite side, or — when -# nav_at_edge=stop — do nothing. Skip the edge check when the flags are -# unreliable (still zoomed, unzoom disabled); in that case we can't tell -# whether we're at an edge, so we just focus in the requested direction. -if [ "$edges_trusted" -eq 1 ] && printf '%s' "$edges_out" | grep -q "\"$dir\"[[:space:]]*:[[:space:]]*true"; then - if [ "$nav_at_edge" = stop ]; then - exit 0 - fi - exec "$herdr" pane focus --direction "$opp" --current -else - exec "$herdr" pane focus --direction "$dir" --current -fi diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/executable_herdr-resize.sh b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/executable_herdr-resize.sh deleted file mode 100644 index 16d0b0d..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/executable_herdr-resize.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash -# Herdr resize helper — used by herdr keybinds for seamless two-way resize. -# -# When a resize key (alt+h/j/k/l) is pressed in Herdr: -# 1. Check if the focused pane is running Neovim in the foreground -# 2. If yes: forward the key chord into that pane (Neovim's plugin handles it) -# 3. If no: resize Herdr pane directly -# -# Zoom state is left untouched (matches smart-splits.nvim's -# disable_multiplexer_nav_when_zoomed default). -# -# Usage: herdr-resize.sh [amount] - -set -euo pipefail - -dir="${1:?usage: herdr-resize.sh [amount]}" -amount="${2:-0.03}" -herdr="${HERDR_BIN_PATH:-herdr}" - -case "$dir" in - left) key="alt+h"; config_key="resize_key_left" ;; - down) key="alt+j"; config_key="resize_key_down" ;; - up) key="alt+k"; config_key="resize_key_up" ;; - right) key="alt+l"; config_key="resize_key_right" ;; - *) echo "herdr-resize.sh: unknown direction: $dir" >&2; exit 2 ;; -esac - -# Resolve the forward chord from the shared config file. -# Unset values keep the alt+hjkl default. -config_path="${HERDR_SPLITS_CONFIG:-${HERDR_PLUGIN_CONFIG_DIR:-$HOME/.config/herdr/plugins/config/herdr-splits}/herdr-splits.conf}" -if [ -r "$config_path" ]; then - configured_key=$(sed -n -E "s/^[[:space:]]*${config_key}[[:space:]]*=[[:space:]]*([^[:space:]#]+).*$/\\1/p" "$config_path" | tail -n 1) - if [ -n "$configured_key" ]; then - key="$configured_key" - fi -fi - -# Get focused pane ID from server -pane_id=$("$herdr" pane current --current 2>/dev/null | grep -o '"pane_id"\s*:\s*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"$/\1/') -if [ -z "$pane_id" ]; then - exec "$herdr" pane resize --direction "$dir" --amount "$amount" --current -fi - -# Check if focused pane is running vim/nvim as foreground process. -# When it is, the key is forwarded into Neovim so the plugin can decide -# whether to resize a Neovim split or hand off to Herdr. -is_vim=0 -if pane_info=$("$herdr" pane process-info --current 2>/dev/null); then - if echo "$pane_info" | grep -qiE '"name"\s*:\s*"(g?(view|l?n?vim?x?)(diff)?)"' 2>/dev/null; then - is_vim=1 - fi -fi - -if [ "$is_vim" -eq 1 ]; then - exec "$herdr" pane send-keys "$pane_id" "$key" -else - exec "$herdr" pane resize --direction "$dir" --amount "$amount" --current -fi diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/minimal_init.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/minimal_init.lua deleted file mode 100644 index 3fe8254..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/scripts/minimal_init.lua +++ /dev/null @@ -1,14 +0,0 @@ -local source = debug.getinfo(1, 'S').source -assert(source:sub(1, 1) == '@', 'could not locate minimal_init.lua') - -local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h') -vim.opt.runtimepath:prepend(root) -vim.opt.runtimepath:prepend(root .. '/deps/mini.test') - -require('mini.test').setup({ - collect = { - find_files = function() - return vim.fn.glob(root .. '/tests/test_*.lua', true, true) - end, - }, -}) diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_conf.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_conf.lua deleted file mode 100644 index 52f002f..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_conf.lua +++ /dev/null @@ -1,196 +0,0 @@ -local T -local expect = MiniTest.expect -local child = MiniTest.new_child_neovim() - -local source = debug.getinfo(1, 'S').source -local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h') - -local function write_config(lines) - child.lua_func(function(config_lines) - local path = vim.env.HERDR_SPLITS_CONFIG - vim.fn.mkdir(vim.fn.fnamemodify(path, ':h'), 'p') - vim.fn.writefile(config_lines, path) - end, lines) -end - -T = MiniTest.new_set({ - hooks = { - pre_case = function() - child.restart({ '--noplugin', '-u', 'NONE', '-i', 'NONE' }) - child.cmd('set runtimepath^=' .. vim.fn.fnameescape(root)) - child.lua([[ - local test_dir = vim.fn.tempname() - vim.fn.mkdir(test_dir, 'p') - vim.g.herdr_splits_test_dir = test_dir - vim.env.HOME = test_dir .. '/home' - vim.env.XDG_CONFIG_HOME = test_dir .. '/xdg' - vim.env.HERDR_SPLITS_CONFIG = test_dir .. '/nested/herdr-splits.conf' - vim.env.HERDR_BIN_PATH = test_dir .. '/missing-herdr' - vim.env.HERDR_PLUGIN_CONFIG_DIR = nil - ]]) - end, - post_case = function() - local test_dir = child.g.herdr_splits_test_dir - child.stop() - vim.fn.delete(test_dir, 'rf') - end, - }, -}) - -T['to_herdr translates key notation'] = function() - local translate = function(value) - return child.lua_func(function(key) - return require('herdr-splits.conf').to_herdr(key) - end, value) - end - - expect.equality(translate(''), 'ctrl+alt+left') - expect.equality(translate(''), 'alt+enter') - expect.equality(translate(''), 'shift+space') - expect.equality(translate('H'), 'h') - expect.equality(translate(''), 'esc') - expect.equality(translate(''), vim.NIL) - expect.equality(translate(false), vim.NIL) - expect.equality(translate(''), vim.NIL) -end - -T['read_managed handles a missing file'] = function() - local result = child.lua_func(function() - local values, adopted = require('herdr-splits.conf').read_managed() - return { adopted = adopted, count = vim.tbl_count(values) } - end) - - expect.equality(result, { adopted = false, count = 0 }) -end - -T['read_managed adopts managed legacy values with last value winning'] = function() - write_config({ - '# legacy config', - ' nav_key_left = ctrl+old', - 'nav_key_left=ctrl+new # last value wins', - 'resize_key_up = alt+up', - 'unzoom_on_nav=false', - 'nav_at_edge=stop', - 'unknown_key=ignored', - }) - - local result = child.lua_func(function() - local values, adopted = require('herdr-splits.conf').read_managed() - return { - adopted = adopted, - nav_left = values.nav_keys.left, - resize_up = values.resize_keys.up, - unzoom_on_nav = values.unzoom_on_nav, - nav_at_edge = values.nav_at_edge, - unknown = values.unknown_key, - } - end) - - expect.equality(result, { - adopted = true, - nav_left = 'ctrl+new', - resize_up = 'alt+up', - unzoom_on_nav = false, - nav_at_edge = 'stop', - }) -end - -T['write creates generated content without leftover temporary files'] = function() - local result = child.lua_func(function() - local conf = require('herdr-splits.conf') - local ok, err = conf.write({ - nav_keys = { left = 'ctrl+h', down = 'ctrl+j', up = 'ctrl+k', right = 'ctrl+l' }, - resize_keys = { left = 'alt+h', down = 'alt+j', up = 'alt+k', right = 'alt+l' }, - unzoom_on_nav = false, - nav_at_edge = 'stop', - }) - local values, adopted = conf.read_managed() - return { - ok = ok, - err = err, - adopted = adopted, - adopted_count = vim.tbl_count(values), - } - end) - - expect.equality(result, { ok = true, adopted = false, adopted_count = 0 }) - - local content = child.lua_func(function() - local file = assert(io.open(vim.env.HERDR_SPLITS_CONFIG, 'r')) - local bytes = file:read('*a') - file:close() - return bytes - end) - expect.equality(content, table.concat({ - '# herdr-splits-generated-v1', - '# herdr-splits plugin config — GENERATED by herdr-splits.nvim setup().', - '# Regenerated from defaults + setup() opts on every setup(); do not edit by hand.', - '# A headerless/legacy conf is adopted once on migration (see the startup', - '# notice), then overwritten thereafter — remove an opt in setup() to revert.', - 'nav_key_left=ctrl+h', - 'nav_key_down=ctrl+j', - 'nav_key_up=ctrl+k', - 'nav_key_right=ctrl+l', - 'resize_key_left=alt+h', - 'resize_key_down=alt+j', - 'resize_key_up=alt+k', - 'resize_key_right=alt+l', - 'unzoom_on_nav=false', - 'nav_at_edge=stop', - '', - }, '\n')) - expect.equality(child.lua_get([[vim.fn.glob(vim.env.HERDR_SPLITS_CONFIG .. '.tmp.*', false, true)]]), {}) -end - -T['config setup applies precedence and resets omitted managed options'] = function() - write_config({ - 'nav_key_left=ctrl+legacy', - 'resize_key_left=alt+legacy', - 'unzoom_on_nav=false', - 'nav_at_edge=stop', - }) - - local result = child.lua_func(function() - vim.notify = function() end - local config = require('herdr-splits.config') - - config.setup({ - nav_keys = { left = '' }, - unzoom_on_nav = true, - }) - local first = { - nav_left = config.nav_keys.left, - resize_left = config.resize_keys.left, - unzoom_on_nav = config.unzoom_on_nav, - nav_at_edge = config.nav_at_edge, - } - - config.setup({ nav_keys = { right = '' } }) - local second = { - nav_left = config.nav_keys.left, - nav_right = config.nav_keys.right, - resize_left = config.resize_keys.left, - unzoom_on_nav = config.unzoom_on_nav, - nav_at_edge = config.nav_at_edge, - } - return { first = first, second = second } - end) - - expect.equality(result, { - first = { - nav_left = 'ctrl+x', - resize_left = 'alt+legacy', - unzoom_on_nav = true, - nav_at_edge = 'stop', - }, - second = { - nav_left = 'ctrl+h', - nav_right = 'ctrl+r', - resize_left = 'alt+h', - unzoom_on_nav = true, - nav_at_edge = 'wrap', - }, - }) -end - -return T diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_herdr.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_herdr.lua deleted file mode 100644 index aecd3e0..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_herdr.lua +++ /dev/null @@ -1,267 +0,0 @@ -local T -local expect = MiniTest.expect -local child = MiniTest.new_child_neovim() - -local source = debug.getinfo(1, 'S').source -local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h') - -T = MiniTest.new_set({ - hooks = { - pre_case = function() - child.restart({ '--noplugin', '-u', 'NONE', '-i', 'NONE' }) - child.cmd('set runtimepath^=' .. vim.fn.fnameescape(root)) - end, - post_case = function() - child.stop() - end, - }, -}) - -T['resolves the binary and requires a complete session environment'] = function() - local result = child.lua_func(function() - local config = require('herdr-splits.config') - local herdr = require('herdr-splits.herdr') - - vim.env.HERDR_BIN_PATH = '/env/herdr' - config.herdr_bin = nil - local from_env = herdr.herdr_bin() - config.herdr_bin = '/config/herdr' - local from_config = herdr.herdr_bin() - config.herdr_bin = nil - vim.env.HERDR_BIN_PATH = nil - local fallback = herdr.herdr_bin() - - vim.env.HERDR_ENV = nil - vim.env.HERDR_PANE_ID = nil - local absent = { herdr.is_in_session(), herdr.current_pane_id() or '' } - vim.env.HERDR_ENV = '1' - vim.env.HERDR_PANE_ID = '' - local empty = { herdr.is_in_session(), herdr.current_pane_id() or '' } - vim.env.HERDR_PANE_ID = 'pane-7' - local present = { herdr.is_in_session(), herdr.current_pane_id() } - - return { - binaries = { from_env, from_config, fallback }, - absent = absent, - empty = empty, - present = present, - } - end) - - expect.equality(result, { - binaries = { '/env/herdr', '/config/herdr', 'herdr' }, - absent = { false, '' }, - empty = { false, '' }, - present = { true, 'pane-7' }, - }) -end - -T['parses edge responses and rejects invalid command output'] = function() - local result = child.lua_func(function() - vim.env.HERDR_ENV = '1' - vim.env.HERDR_PANE_ID = 'pane-7' - local config = require('herdr-splits.config') - config.herdr_bin = '/fake/herdr' - - local queue = { - { stdout = vim.json.encode({ result = { edges = { left = true } } }), stderr = '', code = 0 }, - { stdout = vim.json.encode({ result = { edges = { left = false } } }), stderr = '', code = 0 }, - { stdout = '{bad', stderr = '', code = 0 }, - { stdout = '', stderr = '', code = 0 }, - { stdout = vim.json.encode({ result = {} }), stderr = '', code = 0 }, - { stdout = '{}', stderr = 'failed', code = 2 }, - { stdout = vim.json.encode({ result = { edges = {} } }), stderr = '', code = 0 }, - { stdout = '{"result":{"edges":{"left":null}}}', stderr = '', code = 0 }, - { stdout = vim.json.encode({ result = { edges = { left = 'yes' } } }), stderr = '', code = 0 }, - } - local calls = {} - vim.system = function(argv, opts) - calls[#calls + 1] = { argv = vim.deepcopy(argv), opts = vim.deepcopy(opts) } - local item = table.remove(queue, 1) - return { wait = function() return item end } - end - - package.loaded['herdr-splits.herdr'] = nil - local herdr = require('herdr-splits.herdr') - local values = {} - for i = 1, 9 do - local value = herdr.current_pane_at_edge('left') - values[i] = value == nil and '' or value - end - return { values = values, calls = calls } - end) - - expect.equality(result.values, { - true, false, '', '', '', '', '', '', '', - }) - expect.equality(#result.calls, 9) - for _, call in ipairs(result.calls) do - expect.equality(call, { - argv = { '/fake/herdr', 'pane', 'edges', '--current' }, - opts = { text = true }, - }) - end -end - -T['parses zoom responses and rejects invalid command output'] = function() - local result = child.lua_func(function() - vim.env.HERDR_ENV = '1' - vim.env.HERDR_PANE_ID = 'pane-7' - local queue = { - { stdout = vim.json.encode({ result = { layout = { zoomed = true } } }), stderr = '', code = 0 }, - { stdout = vim.json.encode({ result = { layout = { zoomed = false } } }), stderr = '', code = 0 }, - { stdout = '{bad', stderr = '', code = 0 }, - { stdout = vim.json.encode({ result = {} }), stderr = '', code = 0 }, - { stdout = '{}', stderr = '', code = 1 }, - { stdout = vim.json.encode({ result = { layout = {} } }), stderr = '', code = 0 }, - { stdout = '{"result":{"layout":{"zoomed":null}}}', stderr = '', code = 0 }, - { stdout = vim.json.encode({ result = { layout = { zoomed = 1 } } }), stderr = '', code = 0 }, - } - local calls = {} - vim.system = function(argv, opts) - calls[#calls + 1] = { argv = vim.deepcopy(argv), opts = vim.deepcopy(opts) } - local item = table.remove(queue, 1) - return { wait = function() return item end } - end - - package.loaded['herdr-splits.herdr'] = nil - local herdr = require('herdr-splits.herdr') - local values = {} - for i = 1, 8 do - local value = herdr.current_pane_is_zoomed() - values[i] = value == nil and '' or value - end - return { values = values, calls = calls } - end) - - expect.equality(result.values, { - true, false, '', '', '', '', '', '', - }) - expect.equality(#result.calls, 8) - for _, call in ipairs(result.calls) do - expect.equality(call.argv, { 'herdr', 'pane', 'layout', '--current' }) - expect.equality(call.opts, { text = true }) - end -end - -T['rejects JSON null for pane queries'] = function() - local result = child.lua_func(function() - vim.env.HERDR_ENV = '1' - vim.env.HERDR_PANE_ID = 'pane-7' - local queue = { - 'null', - '{"result":null}', - '{"result":{"edges":null}}', - 'null', - '{"result":null}', - '{"result":{"layout":null}}', - } - vim.system = function() - local stdout = table.remove(queue, 1) - return { - wait = function() - return { stdout = stdout, stderr = '', code = 0 } - end, - } - end - - package.loaded['herdr-splits.herdr'] = nil - local herdr = require('herdr-splits.herdr') - local values = {} - for _ = 1, 3 do - local ok, value = pcall(herdr.current_pane_at_edge, 'left') - values[#values + 1] = { ok, value == nil and '' or value } - end - for _ = 1, 3 do - local ok, value = pcall(herdr.current_pane_is_zoomed) - values[#values + 1] = { ok, value == nil and '' or value } - end - return values - end) - - expect.equality(result, { - { true, '' }, - { true, '' }, - { true, '' }, - { true, '' }, - { true, '' }, - { true, '' }, - }) -end - -T['focus and unzoom use exact commands and report exit status'] = function() - local result = child.lua_func(function() - vim.env.HERDR_ENV = '1' - vim.env.HERDR_PANE_ID = 'pane-7' - local queue = { - { stdout = '', stderr = '', code = 0 }, - { stdout = '', stderr = 'no neighbor', code = 1 }, - { stdout = '', stderr = '', code = 0 }, - { stdout = '', stderr = 'failed', code = 1 }, - } - local calls = {} - vim.system = function(argv, opts) - calls[#calls + 1] = { argv = vim.deepcopy(argv), opts = vim.deepcopy(opts) } - local item = table.remove(queue, 1) - return { wait = function() return item end } - end - - package.loaded['herdr-splits.herdr'] = nil - local herdr = require('herdr-splits.herdr') - return { - values = { - herdr.focus_pane('right'), - herdr.focus_pane('left'), - herdr.unzoom(), - herdr.unzoom(), - }, - calls = calls, - } - end) - - expect.equality(result.values, { true, false, true, false }) - expect.equality(result.calls, { - { argv = { 'herdr', 'pane', 'focus', '--direction', 'right', '--current' }, opts = { text = true } }, - { argv = { 'herdr', 'pane', 'focus', '--direction', 'left', '--current' }, opts = { text = true } }, - { argv = { 'herdr', 'pane', 'zoom', '--off', '--current' }, opts = { text = true } }, - { argv = { 'herdr', 'pane', 'zoom', '--off', '--current' }, opts = { text = true } }, - }) -end - -T['resize formats ratios and reports exit status'] = function() - local result = child.lua_func(function() - vim.env.HERDR_ENV = '1' - vim.env.HERDR_PANE_ID = 'pane-7' - local queue = { - { stdout = '', stderr = '', code = 0 }, - { stdout = '', stderr = 'failed', code = 1 }, - } - local calls = {} - vim.system = function(argv, opts) - calls[#calls + 1] = { argv = vim.deepcopy(argv), opts = vim.deepcopy(opts) } - local item = table.remove(queue, 1) - return { wait = function() return item end } - end - - package.loaded['herdr-splits.herdr'] = nil - local herdr = require('herdr-splits.herdr') - return { - values = { herdr.resize_pane('down', 0.03), herdr.resize_pane('left', 1 / 3) }, - calls = calls, - } - end) - - expect.equality(result.values, { true, false }) - expect.equality(result.calls, { - { - argv = { 'herdr', 'pane', 'resize', '--direction', 'down', '--amount', '0.0300', '--current' }, - opts = { text = true }, - }, - { - argv = { 'herdr', 'pane', 'resize', '--direction', 'left', '--amount', '0.3333', '--current' }, - opts = { text = true }, - }, - }) -end - -return T diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_nav.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_nav.lua deleted file mode 100644 index f88a80d..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_nav.lua +++ /dev/null @@ -1,520 +0,0 @@ -local T -local expect = MiniTest.expect -local child = MiniTest.new_child_neovim() - -local source = debug.getinfo(1, 'S').source -local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h') - -T = MiniTest.new_set({ - hooks = { - pre_case = function() - child.restart({ '--noplugin', '-u', 'NONE', '-i', 'NONE' }) - child.cmd('set runtimepath^=' .. vim.fn.fnameescape(root)) - end, - post_case = function() - child.stop() - end, - }, -}) - -T['moves through native horizontal and vertical splits without delegation'] = function() - local result = child.lua_func(function() - local calls = {} - package.loaded['herdr-splits.herdr'] = { - focus_pane = function(direction) calls[#calls + 1] = direction end, - is_in_session = function() return false end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - vim.o.splitright = true - vim.cmd('vsplit') - local horizontal = vim.api.nvim_tabpage_list_wins(0) - table.sort(horizontal, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(horizontal[1]) - nav.move_cursor('right') - local moved_right = vim.api.nvim_get_current_win() == horizontal[2] - - vim.cmd('only') - vim.o.splitbelow = true - vim.cmd('split') - local vertical = vim.api.nvim_tabpage_list_wins(0) - table.sort(vertical, function(a, b) - return vim.api.nvim_win_get_position(a)[1] < vim.api.nvim_win_get_position(b)[1] - end) - vim.api.nvim_set_current_win(vertical[1]) - nav.move_cursor('down') - local moved_down = vim.api.nvim_get_current_win() == vertical[2] - - return { moved_right = moved_right, moved_down = moved_down, calls = calls } - end) - - expect.equality(result, { moved_right = true, moved_down = true, calls = {} }) -end - -T['applies typed navigation counts without wrapping or delegation'] = function() - child.lua_func(function() - _G.nav_delegations = {} - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return false end, - focus_pane = function(direction) - _G.nav_delegations[#_G.nav_delegations + 1] = direction - return true - end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - vim.o.splitright = true - for _ = 1, 3 do - vim.cmd('vsplit') - end - _G.nav_count_wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(_G.nav_count_wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(_G.nav_count_wins[1]) - vim.keymap.set('n', 'x', function() - nav.move_cursor('right', { at_edge = 'stop' }) - end) - end) - - child.type_keys('2x') - local after_two = child.lua_get('vim.api.nvim_get_current_win() == _G.nav_count_wins[3]') - child.type_keys('5x') - local exhausted_at_last = child.lua_get('vim.api.nvim_get_current_win() == _G.nav_count_wins[4]') - child.type_keys('5x') - local stayed_at_last = child.lua_get('vim.api.nvim_get_current_win() == _G.nav_count_wins[4]') - local delegations = child.lua_get('_G.nav_delegations') - - expect.equality({ - after_two = after_two, - exhausted_at_last = exhausted_at_last, - stayed_at_last = stayed_at_last, - delegations = delegations, - }, { - after_two = true, - exhausted_at_last = true, - stayed_at_last = true, - delegations = {}, - }) -end - -T['delegates normal floats but not embedded floats'] = function() - local result = child.lua_func(function() - local calls = {} - package.loaded['herdr-splits.herdr'] = { - focus_pane = function(direction) - calls[#calls + 1] = direction - return true - end, - is_in_session = function() return false end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - local normal = vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), true, { - relative = 'editor', row = 1, col = 1, width = 12, height = 3, zindex = 50, - }) - nav.move_cursor('right') - local normal_stayed = vim.api.nvim_get_current_win() == normal - - vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), true, { - relative = 'editor', row = 2, col = 2, width = 12, height = 3, zindex = 49, - }) - nav.move_cursor('left') - - return { calls = calls, normal_stayed = normal_stayed } - end) - - expect.equality(result, { - calls = { 'right' }, - normal_stayed = true, - }) -end - -T['applies no-session stop, wrap, and callback edge behavior'] = function() - local result = child.lua_func(function() - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return false end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - local function horizontal_pair() - vim.cmd('only') - vim.o.splitright = true - vim.cmd('vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(wins[1]) - return wins - end - - local stop_wins = horizontal_pair() - nav.move_cursor('left', { at_edge = 'stop' }) - local stopped = vim.api.nvim_get_current_win() == stop_wins[1] - - local wrap_wins = horizontal_pair() - nav.move_cursor('left', { at_edge = 'wrap' }) - local wrapped = vim.api.nvim_get_current_win() == wrap_wins[2] - - local callback_wins = horizontal_pair() - local callback = {} - nav.move_cursor('left', { - at_edge = function(ctx) - callback.direction = ctx.direction - callback.is_sidebar = ctx.is_sidebar - callback.has_split = type(ctx.split) == 'function' - callback.has_wrap = type(ctx.wrap) == 'function' - ctx.wrap() - end, - }) - callback.wrapped = vim.api.nvim_get_current_win() == callback_wins[2] - - return { - stopped = stopped, - wrapped = wrapped, - callback = callback, - } - end) - - expect.equality(result, { - stopped = true, - wrapped = true, - callback = { - direction = 'left', - is_sidebar = false, - has_split = true, - has_wrap = true, - wrapped = true, - }, - }) -end - -T['creates local edge splits and preserves split preferences'] = function() - local result = child.lua_func(function() - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return false end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - local cases = {} - - local function exercise(direction, preference) - vim.cmd('only') - vim.o.splitright = preference - vim.o.splitbelow = preference - local before = #vim.api.nvim_tabpage_list_wins(0) - local original = vim.api.nvim_get_current_win() - - nav.move_cursor(direction, { at_edge = 'split' }) - - local current = vim.api.nvim_get_current_win() - local original_position = vim.api.nvim_win_get_position(original) - local current_position = vim.api.nvim_win_get_position(current) - local placement_matches_preference - if direction == 'left' or direction == 'right' then - if preference then - placement_matches_preference = current_position[2] > original_position[2] - else - placement_matches_preference = current_position[2] < original_position[2] - end - elseif preference then - placement_matches_preference = current_position[1] > original_position[1] - else - placement_matches_preference = current_position[1] < original_position[1] - end - - cases[#cases + 1] = { - direction = direction, - preference = preference, - created_one = #vim.api.nvim_tabpage_list_wins(0) == before + 1, - focused_new = current ~= original, - placement_matches_preference = placement_matches_preference, - splitright_restored = vim.o.splitright == preference, - splitbelow_restored = vim.o.splitbelow == preference, - } - end - - for _, direction in ipairs({ 'left', 'right', 'up', 'down' }) do - exercise(direction, false) - exercise(direction, true) - end - return cases - end) - - local expected = {} - for _, direction in ipairs({ 'left', 'right', 'up', 'down' }) do - for _, preference in ipairs({ false, true }) do - expected[#expected + 1] = { - direction = direction, - preference = preference, - created_one = true, - focused_new = true, - placement_matches_preference = true, - splitright_restored = true, - splitbelow_restored = true, - } - end - end - expect.equality(result, expected) -end - -T['uses Herdr neighbors and falls back locally on focus or edge failures'] = function() - local result = child.lua_func(function() - local edge_queue = { false, false, '' } - local focus_queue = { true, false } - local calls = {} - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - unzoom_enabled = function() return false end, - current_pane_at_edge = function(direction) - calls[#calls + 1] = 'edge:' .. direction - local value = table.remove(edge_queue, 1) - if value == '' then return nil end - return value - end, - focus_pane = function(direction) - calls[#calls + 1] = 'focus:' .. direction - return table.remove(focus_queue, 1) - end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - local function at_left() - vim.cmd('only') - vim.o.splitright = true - vim.cmd('vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(wins[1]) - return wins - end - - local success_wins = at_left() - nav.move_cursor('left') - local focus_success_stays = vim.api.nvim_get_current_win() == success_wins[1] - - local failure_wins = at_left() - nav.move_cursor('left') - local focus_failure_wraps = vim.api.nvim_get_current_win() == failure_wins[2] - - local unknown_wins = at_left() - nav.move_cursor('left') - local unknown_wraps = vim.api.nvim_get_current_win() == unknown_wins[2] - - return { - focus_success_stays = focus_success_stays, - focus_failure_wraps = focus_failure_wraps, - unknown_wraps = unknown_wraps, - calls = calls, - } - end) - - expect.equality(result, { - focus_success_stays = true, - focus_failure_wraps = true, - unknown_wraps = true, - calls = { - 'edge:left', 'focus:left', - 'edge:left', 'focus:left', - 'edge:left', - }, - }) -end - -T['unzooms and retries native movement before querying Herdr edges'] = function() - local result = child.lua_func(function() - local calls = {} - local start_win = vim.api.nvim_get_current_win() - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - unzoom_enabled = function() return true end, - current_pane_is_zoomed = function() - calls[#calls + 1] = 'zoomed' - return true - end, - unzoom = function() - calls[#calls + 1] = 'unzoom' - local old_splitright = vim.o.splitright - vim.o.splitright = true - vim.cmd('vsplit') - vim.api.nvim_set_current_win(start_win) - vim.o.splitright = old_splitright - return true - end, - current_pane_at_edge = function() - calls[#calls + 1] = 'edge' - return false - end, - focus_pane = function() - calls[#calls + 1] = 'focus' - return true - end, - } - package.loaded['herdr-splits.nav'] = nil - require('herdr-splits.nav').move_cursor('right') - - return { - moved = vim.api.nvim_get_current_win() ~= start_win, - windows = #vim.api.nvim_tabpage_list_wins(0), - calls = calls, - } - end) - - expect.equality(result, { moved = true, windows = 2, calls = { 'zoomed', 'unzoom' } }) -end - -T['wraps through the reverse Herdr neighbor unless nav_at_edge stops it'] = function() - local result = child.lua_func(function() - local mode = 'wrap' - local calls = {} - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - unzoom_enabled = function() return false end, - current_pane_at_edge = function(direction) - calls[#calls + 1] = 'edge:' .. direction - return direction == 'left' - end, - nav_at_edge = function() return mode end, - focus_pane = function(direction) - calls[#calls + 1] = 'focus:' .. direction - return true - end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - local function at_left() - vim.cmd('only') - vim.o.splitright = true - vim.cmd('vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(wins[1]) - return wins - end - - local herdr_wrap_wins = at_left() - nav.move_cursor('left') - local herdr_wrap_stays = vim.api.nvim_get_current_win() == herdr_wrap_wins[1] - - mode = 'stop' - local local_wrap_wins = at_left() - nav.move_cursor('left') - local local_wraps = vim.api.nvim_get_current_win() == local_wrap_wins[2] - - return { herdr_wrap_stays = herdr_wrap_stays, local_wraps = local_wraps, calls = calls } - end) - - expect.equality(result, { - herdr_wrap_stays = true, - local_wraps = true, - calls = { 'edge:left', 'edge:right', 'focus:right', 'edge:left' }, - }) -end - -T['command-line window delegates to Herdr at the screen edge and never wincmds'] = function() - local result = child.lua_func(function() - local calls = {} - local edge = false - local nav_mode = 'wrap' - package.loaded['herdr-splits.win'] = { - is_command_line_window = function() return true end, - is_floating = function() return false end, - is_embedded_floating_window = function() return false end, - is_ignored_or_preview = function() return false end, - dir_keys = { left = 'h', right = 'l', up = 'k', down = 'j' }, - dir_keys_reverse = { left = 'l', right = 'h', up = 'j', down = 'k' }, - reverse_direction = { left = 'right', right = 'left', up = 'down', down = 'up' }, - } - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - current_pane_at_edge = function(direction) - calls[#calls + 1] = 'edge:' .. direction - return edge - end, - nav_at_edge = function() return nav_mode end, - focus_pane = function(direction) - calls[#calls + 1] = 'focus:' .. direction - return true - end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - -- single window: will_wrap is true in every direction, mirroring the - -- full-width/bottom command-line window geometry. - vim.cmd('only') - - edge = false - nav.move_cursor('left') - local c1 = vim.deepcopy(calls); calls = {} - - edge = true - nav_mode = 'wrap' - nav.move_cursor('right') - local c2 = vim.deepcopy(calls); calls = {} - - nav_mode = 'stop' - nav.move_cursor('right') - local c3 = vim.deepcopy(calls) - - return { neighbor = c1, wrap_reverse = c2, stop_noop = c3 } - end) - - expect.equality(result, { - neighbor = { 'edge:left', 'focus:left' }, - wrap_reverse = { 'edge:right', 'focus:left' }, - stop_noop = { 'edge:right' }, - }) -end - -T['command-line window no-ops silently when not at a screen edge'] = function() - local result = child.lua_func(function() - package.loaded['herdr-splits.win'] = { - is_command_line_window = function() return true end, - is_floating = function() return false end, - is_embedded_floating_window = function() return false end, - is_ignored_or_preview = function() return false end, - dir_keys = { left = 'h', right = 'l', up = 'k', down = 'j' }, - dir_keys_reverse = { left = 'l', right = 'h', up = 'j', down = 'k' }, - reverse_direction = { left = 'right', right = 'left', up = 'down', down = 'up' }, - } - local focused = {} - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - current_pane_at_edge = function() return false end, - nav_at_edge = function() return 'wrap' end, - focus_pane = function(d) focused[#focused + 1] = d; return true end, - } - package.loaded['herdr-splits.nav'] = nil - local nav = require('herdr-splits.nav') - - vim.o.splitright = true - vim.cmd('vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - -- left window: 'right' has a Neovim neighbor -> will_wrap == false - vim.api.nvim_set_current_win(wins[1]) - nav.move_cursor('right') - return { stayed = vim.api.nvim_get_current_win() == wins[1], focused = focused } - end) - - -- Without the guard, wincmd l would move to wins[2]; with it, silent no-op. - expect.equality(result, { stayed = true, focused = {} }) -end - -return T diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_plugin.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_plugin.lua deleted file mode 100644 index 0afc929..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_plugin.lua +++ /dev/null @@ -1,60 +0,0 @@ -local T -local expect = MiniTest.expect -local child = MiniTest.new_child_neovim() - -local source = debug.getinfo(1, 'S').source -local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h') - -T = MiniTest.new_set({ - hooks = { - pre_case = function() - child.restart({ '--noplugin', '-u', 'NONE', '-i', 'NONE' }) - child.cmd('set runtimepath^=' .. vim.fn.fnameescape(root)) - end, - post_case = function() - child.stop() - end, - }, -}) - -T['public module loads its expected API'] = function() - local result = child.lua_func(function() - local plugin = require('herdr-splits') - local names = { - 'setup', - 'sync_herdr', - 'resize_left', - 'resize_down', - 'resize_up', - 'resize_right', - 'move_cursor_left', - 'move_cursor_down', - 'move_cursor_up', - 'move_cursor_right', - 'add_ignored_filetype', - 'add_ignored_buftype', - } - local types = {} - for _, name in ipairs(names) do - types[name] = type(plugin[name]) - end - return types - end) - - expect.equality(result, { - setup = 'function', - sync_herdr = 'function', - resize_left = 'function', - resize_down = 'function', - resize_up = 'function', - resize_right = 'function', - move_cursor_left = 'function', - move_cursor_down = 'function', - move_cursor_up = 'function', - move_cursor_right = 'function', - add_ignored_filetype = 'function', - add_ignored_buftype = 'function', - }) -end - -return T diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_resize.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_resize.lua deleted file mode 100644 index 0053377..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_resize.lua +++ /dev/null @@ -1,302 +0,0 @@ -local T -local expect = MiniTest.expect -local child = MiniTest.new_child_neovim() - -local source = debug.getinfo(1, 'S').source -local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h') - -T = MiniTest.new_set({ - hooks = { - pre_case = function() - child.restart({ '--noplugin', '-u', 'NONE', '-i', 'NONE' }) - child.cmd('set runtimepath^=' .. vim.fn.fnameescape(root)) - end, - post_case = function() - child.stop() - end, - }, -}) - -T['uses the correct horizontal resize sign at both sides'] = function() - local deltas = child.lua_func(function() - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return false end, - } - package.loaded['herdr-splits.resize'] = nil - local resize = require('herdr-splits.resize') - vim.o.equalalways = false - vim.o.winminwidth = 1 - - local function delta(side, direction) - vim.cmd('only') - vim.o.splitright = true - vim.cmd('vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(wins[side == 'left' and 1 or 2]) - local before = vim.api.nvim_win_get_width(0) - resize.resize(direction, 2) - return vim.api.nvim_win_get_width(0) - before - end - - return { - left_left = delta('left', 'left'), - left_right = delta('left', 'right'), - right_left = delta('right', 'left'), - right_right = delta('right', 'right'), - } - end) - - expect.equality(deltas, { left_left = -2, left_right = 2, right_left = 2, right_right = -2 }) -end - -T['uses the correct vertical resize sign at top and bottom'] = function() - local deltas = child.lua_func(function() - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return false end, - } - package.loaded['herdr-splits.resize'] = nil - local resize = require('herdr-splits.resize') - vim.o.equalalways = false - vim.o.winminheight = 1 - - local function delta(side, direction) - vim.cmd('only') - vim.o.splitbelow = true - vim.cmd('split') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[1] < vim.api.nvim_win_get_position(b)[1] - end) - vim.api.nvim_set_current_win(wins[side == 'top' and 1 or 2]) - local before = vim.api.nvim_win_get_height(0) - resize.resize(direction, 2) - return vim.api.nvim_win_get_height(0) - before - end - - return { - top_up = delta('top', 'up'), - top_down = delta('top', 'down'), - bottom_up = delta('bottom', 'up'), - bottom_down = delta('bottom', 'down'), - } - end) - - expect.equality(deltas, { top_up = -2, top_down = 2, bottom_up = 2, bottom_down = -2 }) -end - -T['floors explicit cell amounts and clamps nonpositive values'] = function() - local deltas = child.lua_func(function() - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return false end, - } - package.loaded['herdr-splits.resize'] = nil - local resize = require('herdr-splits.resize') - vim.o.equalalways = false - vim.o.winminwidth = 1 - - local function delta(amount) - vim.cmd('only') - vim.o.splitright = true - vim.cmd('vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(wins[1]) - local before = vim.api.nvim_win_get_width(0) - resize.resize('right', amount) - return vim.api.nvim_win_get_width(0) - before - end - - return { floored = delta(2.9), zero = delta(0), negative = delta(-4) } - end) - - expect.equality(deltas, { floored = 2, zero = 1, negative = 1 }) -end - -T['multiplies native resize cells by the typed count'] = function() - local before = child.lua_func(function() - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return false end, - } - package.loaded['herdr-splits.resize'] = nil - local config = require('herdr-splits.config') - config.neovim_amount = 2 - vim.o.equalalways = false - vim.o.winminwidth = 1 - vim.o.splitright = true - vim.cmd('vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - vim.api.nvim_set_current_win(wins[1]) - vim.keymap.set('n', 'x', function() - require('herdr-splits.resize').resize('right') - end) - return vim.api.nvim_win_get_width(0) - end) - - child.type_keys('3x') - local after = child.lua_get('vim.api.nvim_win_get_width(0)') - expect.equality(after - before, 6) -end - -T['delegates full-terminal ratios for defaults, counts, and explicit amounts'] = function() - child.lua_func(function() - _G.resize_calls = {} - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - current_pane_is_zoomed = function() return false end, - resize_pane = function(direction, amount) - _G.resize_calls[#_G.resize_calls + 1] = { direction, amount } - return true - end, - } - package.loaded['herdr-splits.resize'] = nil - local config = require('herdr-splits.config') - config.default_amount = 0.03 - local resize = require('herdr-splits.resize') - resize.resize('left') - resize.resize('right', 0.2) - resize.resize('left', 2) - vim.keymap.set('n', 'x', function() resize.resize('right') end) - end) - - child.type_keys('3x') - local calls = child.lua_get('_G.resize_calls') - expect.equality(calls, { - { 'left', 0.03 }, - { 'right', 0.2 }, - { 'left', 0.03 }, - { 'right', 0.09 }, - }) -end - -T['delegates vertical full-terminal ratios using real geometry'] = function() - local result = child.lua_func(function() - local calls = {} - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - current_pane_is_zoomed = function() return false end, - resize_pane = function(direction, amount) - calls[#calls + 1] = { direction, amount } - return true - end, - } - package.loaded['herdr-splits.resize'] = nil - local config = require('herdr-splits.config') - config.default_amount = 0.03 - local win = require('herdr-splits.win') - local resize = require('herdr-splits.resize') - - local geometry = { - full_height = win.is_full_height(), - at_top = win.at_top_edge(), - at_bottom = win.at_bottom_edge(), - } - resize.resize('up') - resize.resize('down', 0.2) - return { geometry = geometry, calls = calls } - end) - - expect.equality(result, { - geometry = { full_height = true, at_top = true, at_bottom = true }, - calls = { { 'up', 0.03 }, { 'down', 0.2 } }, - }) -end - -T['delegates normal floats but suppresses embedded, sidebar, and zoomed windows'] = function() - local result = child.lua_func(function() - local calls = {} - local zoomed = false - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - current_pane_is_zoomed = function() return zoomed end, - resize_pane = function(direction, amount) - calls[#calls + 1] = { direction, amount } - return true - end, - } - package.loaded['herdr-splits.resize'] = nil - local resize = require('herdr-splits.resize') - local base = vim.api.nvim_get_current_win() - - local normal = vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), true, { - relative = 'editor', row = 1, col = 1, width = 12, height = 3, zindex = 50, - }) - resize.resize('right', 0.15) - - local embedded = vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), true, { - relative = 'editor', row = 2, col = 2, width = 12, height = 3, zindex = 49, - }) - resize.resize('left') - - vim.api.nvim_set_current_win(base) - vim.api.nvim_win_close(embedded, true) - vim.api.nvim_win_close(normal, true) - local bufnr = vim.api.nvim_get_current_buf() - vim.api.nvim_set_option_value('buftype', 'nofile', { buf = bufnr }) - resize.resize('left') - - vim.api.nvim_set_option_value('buftype', '', { buf = bufnr }) - zoomed = true - resize.resize('right') - - return { calls = calls, current = vim.api.nvim_get_current_win() == base } - end) - - expect.equality(result, { calls = { { 'right', 0.15 } }, current = true }) -end - -T['command-line window horizontal resize delegates past the nofile sidebar rule'] = function() - local result = child.lua_func(function() - local calls = {} - local cmdwin = true - package.loaded['herdr-splits.win'] = { - is_command_line_window = function() return cmdwin end, - is_embedded_floating_window = function() return false end, - is_floating = function() return false end, - is_ignored_or_preview = function() return true end, - is_full_width = function() return true end, - is_full_height = function() return false end, - at_left_edge = function() return true end, - at_right_edge = function() return true end, - at_top_edge = function() return true end, - at_bottom_edge = function() return true end, - win_position = function() return 'start' end, - } - package.loaded['herdr-splits.herdr'] = { - is_in_session = function() return true end, - current_pane_is_zoomed = function() return false end, - resize_pane = function(direction, amount) - calls[#calls + 1] = { direction, amount } - return true - end, - } - package.loaded['herdr-splits.resize'] = nil - local config = require('herdr-splits.config') - config.default_amount = 0.03 - local resize = require('herdr-splits.resize') - - -- cmdwin + full-width + nofile: horizontal resize delegates to Herdr - cmdwin = true - resize.resize('left') - resize.resize('right', 0.2) - - -- ordinary nofile buffer (not cmdwin): sidebar rule still blocks delegation - cmdwin = false - resize.resize('left') - - return { calls = calls } - end) - - expect.equality(result, { - calls = { { 'left', 0.03 }, { 'right', 0.2 } }, - }) -end - -return T diff --git a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_win.lua b/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_win.lua deleted file mode 100644 index c8312fd..0000000 --- a/dot_config/herdr/plugins/github/herdr-splits-d880c4924f2b/tests/test_win.lua +++ /dev/null @@ -1,138 +0,0 @@ -local T -local expect = MiniTest.expect -local child = MiniTest.new_child_neovim() - -local source = debug.getinfo(1, 'S').source -local root = vim.fn.fnamemodify(source:sub(2), ':p:h:h') - -T = MiniTest.new_set({ - hooks = { - pre_case = function() - child.restart({ '--noplugin', '-u', 'NONE', '-i', 'NONE' }) - child.cmd('set runtimepath^=' .. vim.fn.fnameescape(root)) - end, - post_case = function() - child.stop() - end, - }, -}) - -T['win_position identifies horizontal split positions'] = function() - local positions = child.lua_func(function() - vim.cmd('vsplit | vsplit') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[2] < vim.api.nvim_win_get_position(b)[2] - end) - - local out = {} - for _, win in ipairs(wins) do - vim.api.nvim_set_current_win(win) - out[#out + 1] = require('herdr-splits.win').win_position('left') - end - return out - end) - - expect.equality(positions, { 'start', 'middle', 'last' }) -end - -T['win_position identifies vertical split positions'] = function() - local positions = child.lua_func(function() - vim.cmd('split | split') - local wins = vim.api.nvim_tabpage_list_wins(0) - table.sort(wins, function(a, b) - return vim.api.nvim_win_get_position(a)[1] < vim.api.nvim_win_get_position(b)[1] - end) - - local out = {} - for _, win in ipairs(wins) do - vim.api.nvim_set_current_win(win) - out[#out + 1] = require('herdr-splits.win').win_position('up') - end - return out - end) - - expect.equality(positions, { 'start', 'middle', 'last' }) -end - -T['floating classification distinguishes embedded floats'] = function() - local result = child.lua_func(function() - local win = require('herdr-splits.win') - local normal = vim.api.nvim_get_current_win() - local low = vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), false, { - relative = 'editor', row = 1, col = 1, width = 10, height = 3, zindex = 49, - }) - local default = vim.api.nvim_open_win(vim.api.nvim_create_buf(false, true), false, { - relative = 'editor', row = 2, col = 2, width = 10, height = 3, zindex = 50, - }) - - return { - normal_floating = win.is_floating(normal), - normal_embedded = win.is_embedded_floating_window(normal), - low_floating = win.is_floating(low), - low_embedded = win.is_embedded_floating_window(low), - default_floating = win.is_floating(default), - default_embedded = win.is_embedded_floating_window(default), - } - end) - - expect.equality(result, { - normal_floating = false, - normal_embedded = false, - low_floating = true, - low_embedded = true, - default_floating = true, - default_embedded = false, - }) -end - -T['ignored window classification uses buffer type and filetype'] = function() - local result = child.lua_func(function() - local win = require('herdr-splits.win') - local bufnr = vim.api.nvim_get_current_buf() - local regular = win.is_ignored_win() - - vim.api.nvim_set_option_value('buftype', 'nofile', { buf = bufnr }) - local ignored_buftype = win.is_ignored_win() - vim.api.nvim_set_option_value('buftype', '', { buf = bufnr }) - - vim.api.nvim_set_option_value('filetype', 'neo-tree', { buf = bufnr }) - local ignored_filetype = win.is_ignored_win() - return { - regular = regular, - ignored_buftype = ignored_buftype, - ignored_filetype = ignored_filetype, - } - end) - - expect.equality(result, { - regular = false, - ignored_buftype = true, - ignored_filetype = true, - }) -end - -T['preview windows are ignored only when configured'] = function() - local result = child.lua_func(function() - local win = require('herdr-splits.win') - local config = require('herdr-splits.config') - vim.wo.previewwindow = true - - config.ignore_previewwindows = false - local disabled = win.is_ignored_or_preview() - config.ignore_previewwindows = true - local enabled = win.is_ignored_or_preview() - return { disabled = disabled, enabled = enabled } - end) - - expect.equality(result, { disabled = false, enabled = true }) -end - -T['command-line window is not active in a normal buffer'] = function() - local result = child.lua_func(function() - return require('herdr-splits.win').is_command_line_window() - end) - expect.equality(result, false) -end - -return T diff --git a/dot_config/herdr/session.json b/dot_config/herdr/session.json deleted file mode 100644 index fa51fc2..0000000 --- a/dot_config/herdr/session.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "version": 3, - "workspaces": [ - { - "id": "w5", - "custom_name": null, - "identity_cwd": "/Users/zamp", - "public_pane_numbers": { - "17": 1 - }, - "next_public_pane_number": 2, - "public_tab_numbers": [ - 1 - ], - "next_public_tab_number": 2, - "tabs": [ - { - "custom_name": null, - "layout": { - "Pane": 17 - }, - "panes": { - "17": { - "cwd": "/Users/zamp" - } - }, - "zoomed": false, - "focused": 17, - "root_pane": 17 - } - ], - "active_tab": 0 - } - ], - "active": 0, - "selected": 0, - "sidebar_width": 28, - "sidebar_section_split": 0.5081967, - "collapsed_space_keys": [] -} \ No newline at end of file