Merge branch 'development_tmux' of github.com:freeflowuniverse/herolib into development_tmux
This commit is contained in:
@@ -15,11 +15,12 @@ const ttyd_port = 7890
|
|||||||
fn show_help() {
|
fn show_help() {
|
||||||
println('=== Tmux Server Dashboard ===')
|
println('=== Tmux Server Dashboard ===')
|
||||||
println('Usage:')
|
println('Usage:')
|
||||||
println(' ${os.args[0]} # Start the dashboard')
|
println(' ${os.args[0]} # Start the dashboard')
|
||||||
println(' ${os.args[0]} -down # Stop dashboard and cleanup')
|
println(' ${os.args[0]} -editable # Start dashboard with editable ttyd')
|
||||||
println(' ${os.args[0]} -status # Show dashboard status')
|
println(' ${os.args[0]} -down # Stop dashboard and cleanup')
|
||||||
println(' ${os.args[0]} -restart # Restart the dashboard')
|
println(' ${os.args[0]} -status # Show dashboard status')
|
||||||
println(' ${os.args[0]} -help # Show this help')
|
println(' ${os.args[0]} -restart # Restart the dashboard')
|
||||||
|
println(' ${os.args[0]} -help # Show this help')
|
||||||
println('')
|
println('')
|
||||||
println('Dashboard includes:')
|
println('Dashboard includes:')
|
||||||
println(' • Python HTTP Server (port ${python_port})')
|
println(' • Python HTTP Server (port ${python_port})')
|
||||||
@@ -27,6 +28,10 @@ fn show_help() {
|
|||||||
println(' • Hero Web (compile and run hero web server)')
|
println(' • Hero Web (compile and run hero web server)')
|
||||||
println(' • CPU Monitor (htop)')
|
println(' • CPU Monitor (htop)')
|
||||||
println(' • Web access via ttyd (port ${ttyd_port})')
|
println(' • Web access via ttyd (port ${ttyd_port})')
|
||||||
|
println('')
|
||||||
|
println('ttyd modes:')
|
||||||
|
println(' • Default: read-only access to terminal')
|
||||||
|
println(' • -editable: allows writing/editing in the terminal')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop_dashboard() ! {
|
fn stop_dashboard() ! {
|
||||||
@@ -87,25 +92,25 @@ fn show_status() ! {
|
|||||||
}
|
}
|
||||||
println('✓ Window "${window_name}" exists with ${window.panes.len} panes')
|
println('✓ Window "${window_name}" exists with ${window.panes.len} panes')
|
||||||
|
|
||||||
// Show pane details
|
// Show pane details
|
||||||
for i, pane in window.panes {
|
for i, pane in window.panes {
|
||||||
service_name := match i {
|
service_name := match i {
|
||||||
0 { 'Python HTTP Server' }
|
0 { 'Python HTTP Server' }
|
||||||
1 { 'Counter Service' }
|
1 { 'Counter Service' }
|
||||||
2 { 'Hero Web Service' }
|
2 { 'Hero Web Service' }
|
||||||
3 { 'CPU Monitor' }
|
3 { 'CPU Monitor' }
|
||||||
else { 'Service ${i+1}' }
|
else { 'Service ${i + 1}' }
|
||||||
}
|
|
||||||
|
|
||||||
mut pane_mut := pane
|
|
||||||
stats := pane_mut.stats() or {
|
|
||||||
println(' Pane ${i + 1} (${service_name}): ID=%${pane.id}, PID=${pane.pid} (stats unavailable)')
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
memory_mb := f64(stats.memory_bytes) / (1024.0 * 1024.0)
|
|
||||||
println(' Pane ${i + 1} (${service_name}): ID=%${pane.id}, CPU=${stats.cpu_percent:.1f}%, Memory=${memory_mb:.1f}MB')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mut pane_mut := pane
|
||||||
|
stats := pane_mut.stats() or {
|
||||||
|
println(' Pane ${i + 1} (${service_name}): ID=%${pane.id}, PID=${pane.pid} (stats unavailable)')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_mb := f64(stats.memory_bytes) / (1024.0 * 1024.0)
|
||||||
|
println(' Pane ${i + 1} (${service_name}): ID=%${pane.id}, CPU=${stats.cpu_percent:.1f}%, Memory=${memory_mb:.1f}MB')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
println('✗ Tmux session "${session_name}" not running')
|
println('✗ Tmux session "${session_name}" not running')
|
||||||
}
|
}
|
||||||
@@ -139,7 +144,7 @@ fn restart_dashboard() ! {
|
|||||||
start_dashboard()!
|
start_dashboard()!
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_dashboard() ! {
|
fn start_dashboard_with_mode(ttyd_editable bool) ! {
|
||||||
println('=== Server Dashboard with 4 Panes ===')
|
println('=== Server Dashboard with 4 Panes ===')
|
||||||
println('Setting up tmux session with:')
|
println('Setting up tmux session with:')
|
||||||
println(' 1. Python HTTP Server (port ${python_port})')
|
println(' 1. Python HTTP Server (port ${python_port})')
|
||||||
@@ -148,172 +153,172 @@ fn start_dashboard() ! {
|
|||||||
println(' 4. CPU Monitor (htop)')
|
println(' 4. CPU Monitor (htop)')
|
||||||
println('')
|
println('')
|
||||||
|
|
||||||
// Initialize tmux
|
// Initialize tmux
|
||||||
mut t := tmux.new()!
|
mut t := tmux.new()!
|
||||||
|
|
||||||
if !t.is_running()! {
|
if !t.is_running()! {
|
||||||
println('Starting tmux server...')
|
println('Starting tmux server...')
|
||||||
t.start()!
|
t.start()!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up existing session if it exists
|
// Clean up existing session if it exists
|
||||||
if t.session_exist(session_name) {
|
if t.session_exist(session_name) {
|
||||||
println('Cleaning up existing ${session_name} session...')
|
println('Cleaning up existing ${session_name} session...')
|
||||||
t.session_delete(session_name)!
|
t.session_delete(session_name)!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new session
|
// Create new session
|
||||||
println('Creating ${session_name} session...')
|
println('Creating ${session_name} session...')
|
||||||
mut session := t.session_create(name: session_name)!
|
mut session := t.session_create(name: session_name)!
|
||||||
|
|
||||||
// Create main window with initial bash shell
|
// Create main window with initial bash shell
|
||||||
println('Creating dashboard window...')
|
println('Creating dashboard window...')
|
||||||
mut window := session.window_new(name: window_name, cmd: 'bash', reset: true)!
|
mut window := session.window_new(name: window_name, cmd: 'bash', reset: true)!
|
||||||
|
|
||||||
// Wait for initial setup
|
// Wait for initial setup
|
||||||
time.sleep(500 * time.millisecond)
|
time.sleep(500 * time.millisecond)
|
||||||
t.scan()!
|
t.scan()!
|
||||||
|
|
||||||
println('\n=== Setting up 4-pane layout ===')
|
println('\n=== Setting up 4-pane layout ===')
|
||||||
|
|
||||||
// Get the main window
|
// Get the main window
|
||||||
window = session.window_get(name: window_name)!
|
window = session.window_get(name: window_name)!
|
||||||
|
|
||||||
// Split horizontally first (left and right halves)
|
// Split horizontally first (left and right halves)
|
||||||
println('1. Splitting horizontally for left/right layout...')
|
println('1. Splitting horizontally for left/right layout...')
|
||||||
mut right_pane := window.pane_split_horizontal('bash')!
|
mut right_pane := window.pane_split_horizontal('bash')!
|
||||||
time.sleep(300 * time.millisecond)
|
|
||||||
window.scan()!
|
|
||||||
|
|
||||||
// Split left pane vertically (top-left and bottom-left)
|
|
||||||
println('2. Splitting left pane vertically...')
|
|
||||||
window.scan()!
|
|
||||||
if window.panes.len >= 2 {
|
|
||||||
mut left_pane := window.panes[0] // First pane should be the left one
|
|
||||||
left_pane.select()!
|
|
||||||
time.sleep(200 * time.millisecond)
|
|
||||||
mut bottom_left_pane := window.pane_split_vertical('bash')!
|
|
||||||
time.sleep(300 * time.millisecond)
|
time.sleep(300 * time.millisecond)
|
||||||
window.scan()!
|
window.scan()!
|
||||||
}
|
|
||||||
|
|
||||||
// Split right pane vertically (top-right and bottom-right)
|
// Split left pane vertically (top-left and bottom-left)
|
||||||
println('3. Splitting right pane vertically...')
|
println('2. Splitting left pane vertically...')
|
||||||
window.scan()!
|
|
||||||
if window.panes.len >= 3 {
|
|
||||||
// Find the rightmost pane (should be the last one after horizontal split)
|
|
||||||
mut right_pane_current := window.panes[window.panes.len - 1]
|
|
||||||
right_pane_current.select()!
|
|
||||||
time.sleep(200 * time.millisecond)
|
|
||||||
mut bottom_right_pane := window.pane_split_vertical('bash')!
|
|
||||||
time.sleep(300 * time.millisecond)
|
|
||||||
window.scan()!
|
window.scan()!
|
||||||
}
|
if window.panes.len >= 2 {
|
||||||
|
mut left_pane := window.panes[0] // First pane should be the left one
|
||||||
// Set a proper 2x2 tiled layout using tmux command
|
left_pane.select()!
|
||||||
println('4. Setting 2x2 tiled layout...')
|
time.sleep(200 * time.millisecond)
|
||||||
os.execute('tmux select-layout -t ${session_name}:${window_name} tiled')
|
mut bottom_left_pane := window.pane_split_vertical('bash')!
|
||||||
time.sleep(500 * time.millisecond)
|
time.sleep(300 * time.millisecond)
|
||||||
window.scan()!
|
window.scan()!
|
||||||
|
|
||||||
println('5. Layout complete! We now have 4 panes in 2x2 grid.')
|
|
||||||
|
|
||||||
// Refresh to get all panes
|
|
||||||
window.scan()!
|
|
||||||
println('\nCurrent panes: ${window.panes.len}')
|
|
||||||
for i, pane in window.panes {
|
|
||||||
println(' Pane ${i}: ID=%${pane.id}, PID=${pane.pid}')
|
|
||||||
}
|
|
||||||
|
|
||||||
if window.panes.len < 4 {
|
|
||||||
eprintln('Expected 4 panes, but got ${window.panes.len}')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
println('\n=== Starting services in each pane ===')
|
|
||||||
|
|
||||||
// Pane 1 (top-left): Python HTTP Server
|
|
||||||
println('Starting Python HTTP Server in pane 1...')
|
|
||||||
mut pane1 := window.panes[0]
|
|
||||||
pane1.select()!
|
|
||||||
pane1.send_command('echo "=== Python HTTP Server Port 8000 ==="')!
|
|
||||||
pane1.send_command('cd /tmp && python3 -m http.server ${python_port}')!
|
|
||||||
|
|
||||||
time.sleep(500 * time.millisecond)
|
|
||||||
|
|
||||||
// Pane 2 (bottom-left): Counter Service
|
|
||||||
println('Starting Counter Service in pane 2...')
|
|
||||||
mut pane2 := window.panes[1]
|
|
||||||
pane2.select()!
|
|
||||||
pane2.send_command('echo "=== Counter Service - Updates every 5 seconds ==="')!
|
|
||||||
pane2.send_command('while true; do echo "Count: $(date)"; sleep 5; done')!
|
|
||||||
|
|
||||||
time.sleep(500 * time.millisecond)
|
|
||||||
|
|
||||||
// Pane 3 (top-right): Hero Web
|
|
||||||
println('Starting Hero Web in pane 3...')
|
|
||||||
mut pane3 := window.panes[2]
|
|
||||||
pane3.select()!
|
|
||||||
pane3.send_command('echo "=== Hero Web Server ==="')!
|
|
||||||
pane3.send_command('./cli/compile.vsh && /Users/mahmoud/hero/bin/hero web')!
|
|
||||||
|
|
||||||
time.sleep(500 * time.millisecond)
|
|
||||||
|
|
||||||
// Pane 4 (bottom-right): CPU Monitor
|
|
||||||
println('Starting CPU Monitor in pane 4...')
|
|
||||||
mut pane4 := window.panes[3]
|
|
||||||
pane4.select()!
|
|
||||||
pane4.send_command('echo "=== CPU Monitor ==="')!
|
|
||||||
pane4.send_command('htop')!
|
|
||||||
|
|
||||||
println('\n=== All services started! ===')
|
|
||||||
|
|
||||||
// Wait a moment for services to initialize
|
|
||||||
time.sleep(2000 * time.millisecond)
|
|
||||||
|
|
||||||
// Refresh and show current state
|
|
||||||
t.scan()!
|
|
||||||
window = session.window_get(name: window_name)!
|
|
||||||
|
|
||||||
println('\n=== Current Dashboard State ===')
|
|
||||||
for i, mut pane in window.panes {
|
|
||||||
stats := pane.stats() or {
|
|
||||||
println(' Pane ${i + 1}: ID=%${pane.id}, PID=${pane.pid} (stats unavailable)')
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
memory_mb := f64(stats.memory_bytes) / (1024.0 * 1024.0)
|
|
||||||
service_name := match i {
|
|
||||||
0 { 'Python Server' }
|
|
||||||
1 { 'Counter Service' }
|
|
||||||
2 { 'Hero Web' }
|
|
||||||
3 { 'CPU Monitor' }
|
|
||||||
else { 'Unknown' }
|
|
||||||
}
|
|
||||||
println(' Pane ${i + 1} (${service_name}): ID=%${pane.id}, CPU=${stats.cpu_percent:.1f}%, Memory=${memory_mb:.1f}MB')
|
|
||||||
}
|
|
||||||
|
|
||||||
println('\n=== Access Information ===')
|
// Split right pane vertically (top-right and bottom-right)
|
||||||
println('• Python HTTP Server: http://localhost:${python_port}')
|
println('3. Splitting right pane vertically...')
|
||||||
println('• Tmux Session: tmux attach-session -t ${session_name}')
|
window.scan()!
|
||||||
println('')
|
if window.panes.len >= 3 {
|
||||||
println('=== Pane Resize Commands ===')
|
// Find the rightmost pane (should be the last one after horizontal split)
|
||||||
println('To resize panes, attach to the session and use:')
|
mut right_pane_current := window.panes[window.panes.len - 1]
|
||||||
println(' Ctrl+B then Arrow Keys (hold Ctrl+B and press arrow keys)')
|
right_pane_current.select()!
|
||||||
println(' Or programmatically:')
|
time.sleep(200 * time.millisecond)
|
||||||
for i, pane in window.panes {
|
mut bottom_right_pane := window.pane_split_vertical('bash')!
|
||||||
service_name := match i {
|
time.sleep(300 * time.millisecond)
|
||||||
0 { 'Python Server' }
|
window.scan()!
|
||||||
1 { 'Counter Service' }
|
}
|
||||||
2 { 'Hero Web' }
|
|
||||||
3 { 'CPU Monitor' }
|
// Set a proper 2x2 tiled layout using tmux command
|
||||||
else { 'Unknown' }
|
println('4. Setting 2x2 tiled layout...')
|
||||||
|
os.execute('tmux select-layout -t ${session_name}:${window_name} tiled')
|
||||||
|
time.sleep(500 * time.millisecond)
|
||||||
|
window.scan()!
|
||||||
|
|
||||||
|
println('5. Layout complete! We now have 4 panes in 2x2 grid.')
|
||||||
|
|
||||||
|
// Refresh to get all panes
|
||||||
|
window.scan()!
|
||||||
|
println('\nCurrent panes: ${window.panes.len}')
|
||||||
|
for i, pane in window.panes {
|
||||||
|
println(' Pane ${i}: ID=%${pane.id}, PID=${pane.pid}')
|
||||||
|
}
|
||||||
|
|
||||||
|
if window.panes.len < 4 {
|
||||||
|
eprintln('Expected 4 panes, but got ${window.panes.len}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
println('\n=== Starting services in each pane ===')
|
||||||
|
|
||||||
|
// Pane 1 (top-left): Python HTTP Server
|
||||||
|
println('Starting Python HTTP Server in pane 1...')
|
||||||
|
mut pane1 := window.panes[0]
|
||||||
|
pane1.select()!
|
||||||
|
pane1.send_command('echo "=== Python HTTP Server Port 8000 ==="')!
|
||||||
|
pane1.send_command('cd /tmp && python3 -m http.server ${python_port}')!
|
||||||
|
|
||||||
|
time.sleep(500 * time.millisecond)
|
||||||
|
|
||||||
|
// Pane 2 (bottom-left): Counter Service
|
||||||
|
println('Starting Counter Service in pane 2...')
|
||||||
|
mut pane2 := window.panes[1]
|
||||||
|
pane2.select()!
|
||||||
|
pane2.send_command('echo "=== Counter Service - Updates every 5 seconds ==="')!
|
||||||
|
pane2.send_command('while true; do echo "Count: $(date)"; sleep 5; done')!
|
||||||
|
|
||||||
|
time.sleep(500 * time.millisecond)
|
||||||
|
|
||||||
|
// Pane 3 (top-right): Hero Web
|
||||||
|
println('Starting Hero Web in pane 3...')
|
||||||
|
mut pane3 := window.panes[2]
|
||||||
|
pane3.select()!
|
||||||
|
pane3.send_command('echo "=== Hero Web Server ==="')!
|
||||||
|
pane3.send_command('hero web')!
|
||||||
|
|
||||||
|
time.sleep(500 * time.millisecond)
|
||||||
|
|
||||||
|
// Pane 4 (bottom-right): CPU Monitor
|
||||||
|
println('Starting CPU Monitor in pane 4...')
|
||||||
|
mut pane4 := window.panes[3]
|
||||||
|
pane4.select()!
|
||||||
|
pane4.send_command('echo "=== CPU Monitor ==="')!
|
||||||
|
pane4.send_command('htop')!
|
||||||
|
|
||||||
|
println('\n=== All services started! ===')
|
||||||
|
|
||||||
|
// Wait a moment for services to initialize
|
||||||
|
time.sleep(2000 * time.millisecond)
|
||||||
|
|
||||||
|
// Refresh and show current state
|
||||||
|
t.scan()!
|
||||||
|
window = session.window_get(name: window_name)!
|
||||||
|
|
||||||
|
println('\n=== Current Dashboard State ===')
|
||||||
|
for i, mut pane in window.panes {
|
||||||
|
stats := pane.stats() or {
|
||||||
|
println(' Pane ${i + 1}: ID=%${pane.id}, PID=${pane.pid} (stats unavailable)')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
memory_mb := f64(stats.memory_bytes) / (1024.0 * 1024.0)
|
||||||
|
service_name := match i {
|
||||||
|
0 { 'Python Server' }
|
||||||
|
1 { 'Counter Service' }
|
||||||
|
2 { 'Hero Web' }
|
||||||
|
3 { 'CPU Monitor' }
|
||||||
|
else { 'Unknown' }
|
||||||
|
}
|
||||||
|
println(' Pane ${i + 1} (${service_name}): ID=%${pane.id}, CPU=${stats.cpu_percent:.1f}%, Memory=${memory_mb:.1f}MB')
|
||||||
|
}
|
||||||
|
|
||||||
|
println('\n=== Access Information ===')
|
||||||
|
println('• Python HTTP Server: http://localhost:${python_port}')
|
||||||
|
println('• Tmux Session: tmux attach-session -t ${session_name}')
|
||||||
|
println('')
|
||||||
|
println('=== Pane Resize Commands ===')
|
||||||
|
println('To resize panes, attach to the session and use:')
|
||||||
|
println(' Ctrl+B then Arrow Keys (hold Ctrl+B and press arrow keys)')
|
||||||
|
println(' Or programmatically:')
|
||||||
|
for i, pane in window.panes {
|
||||||
|
service_name := match i {
|
||||||
|
0 { 'Python Server' }
|
||||||
|
1 { 'Counter Service' }
|
||||||
|
2 { 'Hero Web' }
|
||||||
|
3 { 'CPU Monitor' }
|
||||||
|
else { 'Unknown' }
|
||||||
|
}
|
||||||
|
println(' # Resize ${service_name} pane:')
|
||||||
|
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -U 5 # Up')
|
||||||
|
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -D 5 # Down')
|
||||||
|
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -L 5 # Left')
|
||||||
|
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -R 5 # Right')
|
||||||
}
|
}
|
||||||
println(' # Resize ${service_name} pane:')
|
|
||||||
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -U 5 # Up')
|
|
||||||
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -D 5 # Down')
|
|
||||||
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -L 5 # Left')
|
|
||||||
println(' tmux resize-pane -t ${session_name}:${window_name}.%${pane.id} -R 5 # Right')
|
|
||||||
}
|
|
||||||
|
|
||||||
println('\n=== Dashboard is running! ===')
|
println('\n=== Dashboard is running! ===')
|
||||||
println('Attach to view: tmux attach-session -t ${session_name}')
|
println('Attach to view: tmux attach-session -t ${session_name}')
|
||||||
@@ -321,44 +326,64 @@ for i, pane in window.panes {
|
|||||||
println('To stop all services: tmux kill-session -t ${session_name}')
|
println('To stop all services: tmux kill-session -t ${session_name}')
|
||||||
println('Running the browser-based dashboard: TTYD')
|
println('Running the browser-based dashboard: TTYD')
|
||||||
|
|
||||||
window.run_ttyd(ttyd_port) or { println('Failed to start ttyd: ${err}') }
|
mode_str := if ttyd_editable { 'editable' } else { 'read-only' }
|
||||||
|
println('Starting ttyd in ${mode_str} mode...')
|
||||||
|
|
||||||
|
window.run_ttyd(port: ttyd_port, editable: ttyd_editable) or {
|
||||||
|
println('Failed to start ttyd: ${err}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main execution with argument handling
|
fn start_dashboard() ! {
|
||||||
if os.args.len > 1 {
|
start_dashboard_with_mode(false)!
|
||||||
command := os.args[1]
|
}
|
||||||
match command {
|
|
||||||
'-down' {
|
fn main() {
|
||||||
stop_dashboard() or {
|
mut ttyd_editable := false // Local flag for ttyd editable mode
|
||||||
eprintln('Error stopping dashboard: ${err}')
|
|
||||||
|
// Main execution with argument handling
|
||||||
|
if os.args.len > 1 {
|
||||||
|
command := os.args[1]
|
||||||
|
match command {
|
||||||
|
'-editable' {
|
||||||
|
ttyd_editable = true
|
||||||
|
start_dashboard_with_mode(ttyd_editable) or {
|
||||||
|
eprintln('Error starting dashboard: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'-down' {
|
||||||
|
stop_dashboard() or {
|
||||||
|
eprintln('Error stopping dashboard: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'-status' {
|
||||||
|
show_status() or {
|
||||||
|
eprintln('Error getting status: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'-restart' {
|
||||||
|
restart_dashboard() or {
|
||||||
|
eprintln('Error restarting dashboard: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'-help', '--help', '-h' {
|
||||||
|
show_help()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eprintln('Unknown command: ${command}')
|
||||||
|
show_help()
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'-status' {
|
} else {
|
||||||
show_status() or {
|
// No arguments - start the dashboard
|
||||||
eprintln('Error getting status: ${err}')
|
start_dashboard_with_mode(ttyd_editable) or {
|
||||||
exit(1)
|
eprintln('Error starting dashboard: ${err}')
|
||||||
}
|
|
||||||
}
|
|
||||||
'-restart' {
|
|
||||||
restart_dashboard() or {
|
|
||||||
eprintln('Error restarting dashboard: ${err}')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'-help', '--help', '-h' {
|
|
||||||
show_help()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
eprintln('Unknown command: ${command}')
|
|
||||||
show_help()
|
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// No arguments - start the dashboard
|
|
||||||
start_dashboard() or {
|
|
||||||
eprintln('Error starting dashboard: ${err}')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,14 +260,27 @@ pub fn (mut s Session) stop() ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run ttyd for this session so it can be accessed in the browser
|
// Run ttyd for this session so it can be accessed in the browser
|
||||||
pub fn (mut s Session) run_ttyd(port int) ! {
|
pub fn (mut s Session) run_ttyd(args TtydArgs) ! {
|
||||||
target := '${s.name}'
|
target := '${s.name}'
|
||||||
cmd := 'nohup ttyd -p ${port} tmux attach -t ${target} >/dev/null 2>&1 &'
|
|
||||||
|
// Add -W flag for write access if editable mode is enabled
|
||||||
|
mut ttyd_flags := '-p ${args.port}'
|
||||||
|
if args.editable {
|
||||||
|
ttyd_flags += ' -W'
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := 'nohup ttyd ${ttyd_flags} tmux attach -t ${target} >/dev/null 2>&1 &'
|
||||||
|
|
||||||
code := os.system(cmd)
|
code := os.system(cmd)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return error('Failed to start ttyd on port ${port} for session ${s.name}')
|
return error('Failed to start ttyd on port ${args.port} for session ${s.name}')
|
||||||
}
|
}
|
||||||
|
|
||||||
println('ttyd started for session ${s.name} at http://localhost:${port}')
|
mode_str := if args.editable { 'editable' } else { 'read-only' }
|
||||||
|
println('ttyd started for session ${s.name} at http://localhost:${args.port} (${mode_str} mode)')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backward compatibility method - runs ttyd in read-only mode
|
||||||
|
pub fn (mut s Session) run_ttyd_readonly(port int) ! {
|
||||||
|
s.run_ttyd(port: port, editable: false)!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,15 +257,35 @@ pub fn (mut w Window) pane_split_vertical(cmd string) !&Pane {
|
|||||||
return w.pane_split(cmd: cmd, horizontal: false)
|
return w.pane_split(cmd: cmd, horizontal: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct TtydArgs {
|
||||||
|
pub mut:
|
||||||
|
port int
|
||||||
|
editable bool // if true, allows write access to the terminal
|
||||||
|
}
|
||||||
|
|
||||||
// Run ttyd for this window so it can be accessed in the browser
|
// Run ttyd for this window so it can be accessed in the browser
|
||||||
pub fn (mut w Window) run_ttyd(port int) ! {
|
pub fn (mut w Window) run_ttyd(args TtydArgs) ! {
|
||||||
target := '${w.session.name}:@${w.id}'
|
target := '${w.session.name}:@${w.id}'
|
||||||
cmd := 'nohup ttyd -p ${port} tmux attach -t ${target} >/dev/null 2>&1 &'
|
|
||||||
|
// Add -W flag for write access if editable mode is enabled
|
||||||
|
mut ttyd_flags := '-p ${args.port}'
|
||||||
|
if args.editable {
|
||||||
|
ttyd_flags += ' -W'
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := 'nohup ttyd ${ttyd_flags} tmux attach -t ${target} >/dev/null 2>&1 &'
|
||||||
|
|
||||||
code := os.system(cmd)
|
code := os.system(cmd)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return error('Failed to start ttyd on port ${port} for window ${w.name}')
|
return error('Failed to start ttyd on port ${args.port} for window ${w.name}')
|
||||||
}
|
}
|
||||||
|
|
||||||
println('ttyd started for window ${w.name} at http://localhost:${port}')
|
mode_str := if args.editable { 'editable' } else { 'read-only' }
|
||||||
|
println('ttyd started for window ${w.name} at http://localhost:${args.port} (${mode_str} mode)')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backward compatibility method - runs ttyd in read-only mode
|
||||||
|
pub fn (mut w Window) run_ttyd_readonly(port int) ! {
|
||||||
|
w.run_ttyd(port: port, editable: false)!
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user