From 7d28129f06af49228ccfce6cbebc1a0b57db9600 Mon Sep 17 00:00:00 2001 From: Mahmoud-Emad Date: Sun, 31 Aug 2025 17:56:03 +0300 Subject: [PATCH] feat: implement dynamic pane resizing - Add `resize_panes_equal()` to `Window`. - Dynamically apply `tmux` layouts based on pane count. - Implement `get_width()` and `get_height()` for `Pane`. - Update test to create 4 panes and use equal resizing. --- .../tmux/heroscripts/debug_test.heroscript | 18 ------- .../simple_declarative_test.heroscript | 14 +++++- lib/osal/tmux/play.v | 3 ++ lib/osal/tmux/tmux_pane.v | 18 +++++++ lib/osal/tmux/tmux_window.v | 48 +++++++++++++++++++ 5 files changed, 81 insertions(+), 20 deletions(-) delete mode 100644 examples/osal/tmux/heroscripts/debug_test.heroscript diff --git a/examples/osal/tmux/heroscripts/debug_test.heroscript b/examples/osal/tmux/heroscripts/debug_test.heroscript deleted file mode 100644 index 85ad2ea4..00000000 --- a/examples/osal/tmux/heroscripts/debug_test.heroscript +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env hero - -// Debug test - no ttyd, just basic declarative functionality - -// Ensure a test session exists -!!tmux.session_ensure - name:"debug_test" - -// Ensure a simple 2-pane window exists -!!tmux.window_ensure - name:"debug_test|demo" - cat:"2pane" - -// Try to configure just one pane -!!tmux.pane_ensure - name:"debug_test|demo|1" - label:"test" - cmd:"echo Hello from pane 1" \ No newline at end of file diff --git a/examples/osal/tmux/heroscripts/simple_declarative_test.heroscript b/examples/osal/tmux/heroscripts/simple_declarative_test.heroscript index ab2aeeea..8b1ff813 100644 --- a/examples/osal/tmux/heroscripts/simple_declarative_test.heroscript +++ b/examples/osal/tmux/heroscripts/simple_declarative_test.heroscript @@ -9,7 +9,7 @@ // Ensure a simple 2-pane window exists !!tmux.window_ensure name:"test|demo" - cat:"2pane" + cat:"4pane" // Configure the panes !!tmux.pane_ensure @@ -20,4 +20,14 @@ !!tmux.pane_ensure name:"test|demo|2" label:"second" - cmd:"echo Second pane ready" \ No newline at end of file + cmd:"echo Second pane ready" + +!!tmux.pane_ensure + name:"test|demo|3" + label:"third" + cmd:"echo Third pane ready" + +!!tmux.pane_ensure + name:"test|demo|4" + label:"fourth" + cmd:"echo Fourth pane ready" \ No newline at end of file diff --git a/lib/osal/tmux/play.v b/lib/osal/tmux/play.v index 631591e7..50d7189c 100644 --- a/lib/osal/tmux/play.v +++ b/lib/osal/tmux/play.v @@ -655,6 +655,9 @@ fn play_window_ensure(mut plbook PlayBook, mut tmux_instance Tmux) ! { env: env )! } + + // After creating all panes, resize them to equal dimensions dynamically + window.resize_panes_equal()! } action.done = true diff --git a/lib/osal/tmux/tmux_pane.v b/lib/osal/tmux/tmux_pane.v index b94cf2d0..cd57c6ea 100644 --- a/lib/osal/tmux/tmux_pane.v +++ b/lib/osal/tmux/tmux_pane.v @@ -201,3 +201,21 @@ pub fn (mut p Pane) resize_left(cells int) ! { pub fn (mut p Pane) resize_right(cells int) ! { p.resize(direction: 'right', cells: cells)! } + +// Get current pane width +pub fn (p Pane) get_width() !int { + cmd := 'tmux display-message -t ${p.window.session.name}:@${p.window.id}.%${p.id} -p "#{pane_width}"' + res := osal.exec(cmd: cmd, stdout: false, name: 'tmux_get_pane_width') or { + return error("Can't get pane width: ${err}") + } + return res.output.trim_space().int() +} + +// Get current pane height +pub fn (p Pane) get_height() !int { + cmd := 'tmux display-message -t ${p.window.session.name}:@${p.window.id}.%${p.id} -p "#{pane_height}"' + res := osal.exec(cmd: cmd, stdout: false, name: 'tmux_get_pane_height') or { + return error("Can't get pane height: ${err}") + } + return res.output.trim_space().int() +} diff --git a/lib/osal/tmux/tmux_window.v b/lib/osal/tmux/tmux_window.v index 385d960f..745c1b74 100644 --- a/lib/osal/tmux/tmux_window.v +++ b/lib/osal/tmux/tmux_window.v @@ -274,6 +274,54 @@ pub fn (mut w Window) pane_split_vertical(cmd string) !&Pane { return w.pane_split(cmd: cmd, horizontal: false) } +// Resize panes to equal dimensions dynamically based on pane count +pub fn (mut w Window) resize_panes_equal() ! { + w.scan()! // Refresh pane information + + pane_count := w.panes.len + if pane_count <= 1 { + return + } + + // Dynamic layout based on actual pane count + match pane_count { + 1 { + // Single pane, no resizing needed + console.print_debug('Single pane, no resizing needed') + } + 2 { + // Two panes: use even-horizontal layout (side by side) + cmd := 'tmux select-layout -t ${w.session.name}:@${w.id} even-horizontal' + osal.execute_silent(cmd) or { + console.print_debug('Could not apply even-horizontal layout: ${err}') + } + } + 3 { + // Three panes: use main-horizontal layout (one large top, two smaller bottom) + cmd := 'tmux select-layout -t ${w.session.name}:@${w.id} main-horizontal' + osal.execute_silent(cmd) or { + console.print_debug('Could not apply main-horizontal layout: ${err}') + } + } + 4 { + // Four panes: use tiled layout (2x2 grid) + cmd := 'tmux select-layout -t ${w.session.name}:@${w.id} tiled' + osal.execute_silent(cmd) or { + console.print_debug('Could not apply tiled layout: ${err}') + } + } + else { + // For 5+ panes: use tiled layout which works well for any number + if pane_count >= 5 { + cmd := 'tmux select-layout -t ${w.session.name}:@${w.id} tiled' + osal.execute_silent(cmd) or { + console.print_debug('Could not apply tiled layout for ${pane_count} panes: ${err}') + } + } + } + } +} + @[params] pub struct TtydArgs { pub mut: