...
This commit is contained in:
@@ -4,7 +4,11 @@
|
||||
import freeflowuniverse.herolib.osal.tmux
|
||||
|
||||
mut t := tmux.new()!
|
||||
t.session_delete('main')!
|
||||
println(t)
|
||||
if !t.is_running()! {
|
||||
t.start()!
|
||||
}
|
||||
if t.session_exist('main') {
|
||||
t.session_delete('main')!
|
||||
}
|
||||
t.window_new(name: 'test', cmd: 'mc', reset: true)!
|
||||
println(t)
|
||||
|
||||
@@ -13,19 +13,76 @@ pub mut:
|
||||
sessionid string // unique link to job
|
||||
}
|
||||
|
||||
@[heap]
|
||||
struct Pane {
|
||||
pub mut:
|
||||
window &Window @[str: skip]
|
||||
id int // pane id (e.g., %1, %2)
|
||||
pid int // process id
|
||||
active bool // is this the active pane
|
||||
cmd string // command running in pane
|
||||
env map[string]string
|
||||
created_at time.Time
|
||||
last_output_offset int // for tracking new logs
|
||||
|
||||
// get session (session has windows) .
|
||||
// returns none if not found
|
||||
pub fn (mut t Tmux) session_get(name_ string) !&Session {
|
||||
name := texttools.name_fix(name_)
|
||||
for s in t.sessions {
|
||||
if s.name == name {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return error('Can not find session with name: \'${name_}\', out of loaded sessions.')
|
||||
}
|
||||
|
||||
pub fn (mut t Tmux) session_exist(name_ string) bool {
|
||||
name := texttools.name_fix(name_)
|
||||
t.session_get(name) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (mut t Tmux) session_delete(name_ string) ! {
|
||||
if !(t.session_exist(name_)) {
|
||||
return
|
||||
}
|
||||
name := texttools.name_fix(name_)
|
||||
mut i := 0
|
||||
for mut s in t.sessions {
|
||||
if s.name == name {
|
||||
s.stop()!
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
t.sessions.delete(i)
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct SessionCreateArgs {
|
||||
pub mut:
|
||||
name string @[required]
|
||||
reset bool
|
||||
}
|
||||
|
||||
|
||||
|
||||
// create session, if reset will re-create
|
||||
pub fn (mut t Tmux) session_create(args SessionCreateArgs) !&Session {
|
||||
name := texttools.name_fix(args.name)
|
||||
if !(t.session_exist(name)) {
|
||||
$if debug {
|
||||
console.print_header(' tmux - create session: ${args}')
|
||||
}
|
||||
mut s2 := Session{
|
||||
tmux: t // reference back
|
||||
name: name
|
||||
}
|
||||
s2.create()!
|
||||
t.sessions << &s2
|
||||
}
|
||||
mut s := t.session_get(name)!
|
||||
if args.reset {
|
||||
$if debug {
|
||||
console.print_header(' tmux - session ${name} will be restarted.')
|
||||
}
|
||||
s.restart()!
|
||||
}
|
||||
t.scan()!
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
@[params]
|
||||
pub struct TmuxNewArgs {
|
||||
sessionid string
|
||||
@@ -41,49 +98,6 @@ pub fn new(args TmuxNewArgs) !Tmux {
|
||||
return t
|
||||
}
|
||||
|
||||
// // loads tmux session, populate the object
|
||||
// pub fn (mut tmux Tmux) load() ! {
|
||||
// // isrunning := tmux.is_running()!
|
||||
// // if !isrunning {
|
||||
// // tmux.start()!
|
||||
// // }
|
||||
// // console.print_debug("SCAN")
|
||||
// tmux.scan()!
|
||||
// }
|
||||
|
||||
pub struct ProcessStats {
|
||||
pub mut:
|
||||
cpu_percent f64
|
||||
memory_bytes u64
|
||||
memory_percent f64
|
||||
}
|
||||
|
||||
pub fn (mut p Pane) get_stats() !ProcessStats {
|
||||
if p.pid == 0 {
|
||||
return ProcessStats{}
|
||||
}
|
||||
|
||||
// Use ps command to get CPU and memory stats
|
||||
cmd := 'ps -p ${p.pid} -o %cpu,%mem,rss --no-headers'
|
||||
result := osal.execute_silent(cmd) or {
|
||||
return error('Cannot get stats for PID ${p.pid}: ${err}')
|
||||
}
|
||||
|
||||
if result.trim() == '' {
|
||||
return error('Process ${p.pid} not found')
|
||||
}
|
||||
|
||||
parts := result.trim().split_any(' \t').filter(it != '')
|
||||
if parts.len < 3 {
|
||||
return error('Invalid ps output: ${result}')
|
||||
}
|
||||
|
||||
return ProcessStats{
|
||||
cpu_percent: parts[0].f64()
|
||||
memory_percent: parts[1].f64()
|
||||
memory_bytes: parts[2].u64() * 1024 // ps returns KB, convert to bytes
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut t Tmux) stop() ! {
|
||||
$if debug {
|
||||
@@ -128,73 +142,6 @@ pub mut:
|
||||
offset int
|
||||
}
|
||||
|
||||
pub fn (mut p Pane) get_new_logs() ![]LogEntry {
|
||||
// Capture pane content with line numbers
|
||||
cmd := 'tmux capture-pane -t ${p.window.session.name}:@${p.window.id}.%${p.id} -S ${p.last_output_offset} -p'
|
||||
result := osal.execute_silent(cmd) or {
|
||||
return error('Cannot capture pane output: ${err}')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn (mut p Pane) check_process_status() !ProcessStatus {
|
||||
|
||||
}
|
||||
|
||||
if result.trim() == '' {
|
||||
// Process not found, check exit status from shell history or tmux
|
||||
return p.check_exit_status() or { .finished_error }
|
||||
}
|
||||
|
||||
return .running
|
||||
}
|
||||
|
||||
fn (mut p Pane) check_exit_status() !ProcessStatus {
|
||||
// Get the last few lines to see if there's an exit status
|
||||
logs := p.get_all_logs()!
|
||||
lines := logs.split_into_lines()
|
||||
|
||||
// Look for shell prompt indicating command finished
|
||||
for line in lines.reverse() {
|
||||
line_clean := line.trim()
|
||||
if line_clean.contains('$') || line_clean.contains('#') || line_clean.contains('>') {
|
||||
// Found shell prompt, command likely finished
|
||||
// Could also check for specific exit codes in history
|
||||
return .finished_ok
|
||||
}
|
||||
}
|
||||
|
||||
return .finished_error
|
||||
}
|
||||
|
||||
lines := result.split_into_lines()
|
||||
mut entries := []LogEntry{}
|
||||
|
||||
for i, line in lines {
|
||||
if line.trim() != '' {
|
||||
entries << LogEntry{
|
||||
content: line
|
||||
timestamp: time.now()
|
||||
offset: p.last_output_offset + i + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update offset to avoid duplicates next time
|
||||
if entries.len > 0 {
|
||||
p.last_output_offset = entries.last().offset
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
pub fn (mut p Pane) get_all_logs() !string {
|
||||
cmd := 'tmux capture-pane -t ${p.window.session.name}:@${p.window.id}.%${p.id} -S -1000 -p'
|
||||
return osal.execute_silent(cmd) or {
|
||||
error('Cannot capture pane output: ${err}')
|
||||
}
|
||||
}
|
||||
|
||||
// print list of tmux sessions
|
||||
pub fn (mut t Tmux) list_print() {
|
||||
// os.log('TMUX - Start listing ....')
|
||||
|
||||
137
lib/osal/tmux/tmux_pane.v
Normal file
137
lib/osal/tmux/tmux_pane.v
Normal file
@@ -0,0 +1,137 @@
|
||||
module tmux
|
||||
|
||||
import freeflowuniverse.herolib.osal.core as osal
|
||||
// import freeflowuniverse.herolib.session
|
||||
import os
|
||||
import time
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
@[heap]
|
||||
struct Pane {
|
||||
pub mut:
|
||||
window &Window @[str: skip]
|
||||
id int // pane id (e.g., %1, %2)
|
||||
pid int // process id
|
||||
active bool // is this the active pane
|
||||
cmd string // command running in pane
|
||||
env map[string]string
|
||||
created_at time.Time
|
||||
last_output_offset int // for tracking new logs
|
||||
}
|
||||
|
||||
|
||||
pub fn (mut p Pane) stats() !ProcessStats {
|
||||
if p.pid == 0 {
|
||||
return ProcessStats{}
|
||||
}
|
||||
|
||||
// Use ps command to get CPU and memory stats
|
||||
cmd := 'ps -p ${p.pid} -o %cpu,%mem,rss --no-headers'
|
||||
result := osal.execute_silent(cmd) or {
|
||||
return error('Cannot get stats for PID ${p.pid}: ${err}')
|
||||
}
|
||||
|
||||
if result.trim_space() == '' {
|
||||
return error('Process ${p.pid} not found')
|
||||
}
|
||||
|
||||
parts := result.trim_space().split_any(' \t').filter(it != '')
|
||||
if parts.len < 3 {
|
||||
return error('Invalid ps output: ${result}')
|
||||
}
|
||||
|
||||
return ProcessStats{
|
||||
cpu_percent: parts[0].f64()
|
||||
memory_percent: parts[1].f64()
|
||||
memory_bytes: parts[2].u64() * 1024 // ps returns KB, convert to bytes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct LogEntry {
|
||||
pub mut:
|
||||
content string
|
||||
timestamp time.Time
|
||||
offset int
|
||||
}
|
||||
|
||||
pub fn (mut p Pane) logs_get_new(reset bool) ![]LogEntry {
|
||||
|
||||
if reset{
|
||||
p.last_output_offset = 0
|
||||
}
|
||||
// Capture pane content with line numbers
|
||||
cmd := 'tmux capture-pane -t ${p.window.session.name}:@${p.window.id}.%${p.id} -S ${p.last_output_offset} -p'
|
||||
result := osal.execute_silent(cmd) or {
|
||||
return error('Cannot capture pane output: ${err}')
|
||||
}
|
||||
|
||||
lines := result.split_into_lines()
|
||||
mut entries := []LogEntry{}
|
||||
|
||||
mut i:= 0
|
||||
for line in lines {
|
||||
if line.trim_space() != '' {
|
||||
entries << LogEntry{
|
||||
content: line
|
||||
timestamp: time.now()
|
||||
offset: p.last_output_offset + i + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update offset to avoid duplicates next time
|
||||
if entries.len > 0 {
|
||||
p.last_output_offset = entries.last().offset
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
pub fn (mut p Pane) exit_status() !ProcessStatus {
|
||||
// Get the last few lines to see if there's an exit status
|
||||
logs := p.logs_all()!
|
||||
lines := logs.split_into_lines()
|
||||
|
||||
// Look for shell prompt indicating command finished
|
||||
for line in lines.reverse() {
|
||||
line_clean := line.trim_space()
|
||||
if line_clean.contains('$') || line_clean.contains('#') || line_clean.contains('>') {
|
||||
// Found shell prompt, command likely finished
|
||||
// Could also check for specific exit codes in history
|
||||
return .finished_ok
|
||||
}
|
||||
}
|
||||
return .finished_error
|
||||
}
|
||||
|
||||
pub fn (mut p Pane) logs_get_all() !string {
|
||||
cmd := 'tmux capture-pane -t ${p.window.session.name}:@${p.window.id}.%${p.id} -S -2000 -p'
|
||||
return osal.execute_silent(cmd) or {
|
||||
error('Cannot capture pane output: ${err}')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn (mut w Pane) output_wait(c_ string, timeoutsec int) ! {
|
||||
mut t := ourtime.now()
|
||||
start := t.unix()
|
||||
c := c_.replace('\n', '')
|
||||
for i in 0 .. 2000 {
|
||||
os := w.logs_get_new()!.map(it.content)
|
||||
// console.print_debug(o)
|
||||
// $if debug {
|
||||
// console.print_debug(" - tmux ${w.name}: wait for: '${c}'")
|
||||
// }
|
||||
// need to replace \n because can be wrapped because of size of pane
|
||||
for o in os{
|
||||
if o.replace('\n', '').contains(c) {
|
||||
return
|
||||
}
|
||||
}
|
||||
mut t2 := ourtime.now()
|
||||
if t2.unix() > start + timeoutsec {
|
||||
return error('timeout on output wait for tmux.\n${w} .\nwaiting for:\n${c}')
|
||||
}
|
||||
time.sleep(100 * time.millisecond)
|
||||
}
|
||||
}
|
||||
21
lib/osal/tmux/tmux_process.v
Normal file
21
lib/osal/tmux/tmux_process.v
Normal file
@@ -0,0 +1,21 @@
|
||||
module tmux
|
||||
|
||||
|
||||
|
||||
pub struct ProcessStats {
|
||||
pub mut:
|
||||
cpu_percent f64
|
||||
memory_bytes u64
|
||||
memory_percent f64
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum ProcessStatus {
|
||||
running
|
||||
finished_ok
|
||||
finished_error
|
||||
not_found
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ fn (mut t Tmux) scan_add(line string) !&Pane {
|
||||
}
|
||||
|
||||
// scan the system to detect sessions .
|
||||
//TODO needs to be done differently, here only find the sessions, then per session call the scan() which will find the windows, call scan() there as well ...
|
||||
pub fn (mut t Tmux) scan() ! {
|
||||
// os.log('TMUX - Scanning ....')
|
||||
|
||||
|
||||
@@ -13,72 +13,58 @@ pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
// get session (session has windows) .
|
||||
// returns none if not found
|
||||
pub fn (mut t Tmux) session_get(name_ string) !&Session {
|
||||
name := texttools.name_fix(name_)
|
||||
for s in t.sessions {
|
||||
if s.name == name {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return error('Can not find session with name: \'${name_}\', out of loaded sessions.')
|
||||
}
|
||||
|
||||
pub fn (mut t Tmux) session_exist(name_ string) bool {
|
||||
name := texttools.name_fix(name_)
|
||||
t.session_get(name) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (mut t Tmux) session_delete(name_ string) ! {
|
||||
if !(t.session_exist(name_)) {
|
||||
return
|
||||
}
|
||||
name := texttools.name_fix(name_)
|
||||
mut i := 0
|
||||
for mut s in t.sessions {
|
||||
if s.name == name {
|
||||
s.stop()!
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
t.sessions.delete(i)
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct SessionCreateArgs {
|
||||
pub struct WindowArgs {
|
||||
pub mut:
|
||||
name string @[required]
|
||||
name string
|
||||
reset bool
|
||||
}
|
||||
|
||||
// create session, if reset will re-create
|
||||
pub fn (mut t Tmux) session_create(args SessionCreateArgs) !&Session {
|
||||
name := texttools.name_fix(args.name)
|
||||
if !(t.session_exist(name)) {
|
||||
$if debug {
|
||||
console.print_header(' tmux - create session: ${args}')
|
||||
}
|
||||
mut s2 := Session{
|
||||
tmux: t // reference back
|
||||
name: name
|
||||
}
|
||||
s2.create()!
|
||||
t.sessions << &s2
|
||||
}
|
||||
mut s := t.session_get(name)!
|
||||
if args.reset {
|
||||
$if debug {
|
||||
console.print_header(' tmux - session ${name} will be restarted.')
|
||||
}
|
||||
s.restart()!
|
||||
}
|
||||
t.scan()!
|
||||
return s
|
||||
|
||||
pub fn (mut w Session) scan() ! {
|
||||
//TODO: here needs to be the code to check reality and update the windows
|
||||
}
|
||||
|
||||
|
||||
// window_name is the name of the window in session main (will always be called session main)
|
||||
// cmd to execute e.g. bash file
|
||||
// environment arguments to use
|
||||
// reset, if reset it will create window even if it does already exist, will destroy it
|
||||
// ```
|
||||
// struct WindowArgs {
|
||||
// pub mut:
|
||||
// name string
|
||||
// cmd string
|
||||
// env map[string]string
|
||||
// reset bool
|
||||
// }
|
||||
// ```
|
||||
pub fn (mut s Session) window_new(args WindowArgs) !Window {
|
||||
$if debug {
|
||||
console.print_header(' start window: \n${args}')
|
||||
}
|
||||
namel := texttools.name_fix(args.name)
|
||||
if s.window_exist(name: namel) {
|
||||
if args.reset {
|
||||
s.window_delete(name: namel)!
|
||||
} else {
|
||||
return error('cannot create new window it already exists, window ${namel} in session:${s.name}')
|
||||
}
|
||||
}
|
||||
mut w := Window{
|
||||
session: &s
|
||||
name: namel
|
||||
panes: []&Pane{}
|
||||
env: args.env
|
||||
}
|
||||
s.windows << &w
|
||||
w.create(args.cmd)!
|
||||
// After creation, scan to populate panes
|
||||
s.tmux.scan()!
|
||||
return w
|
||||
}
|
||||
|
||||
|
||||
pub fn (mut s Session) create() ! {
|
||||
res_opt := "-P -F '#\{window_id\}'"
|
||||
cmd := "tmux new-session ${res_opt} -d -s ${s.name} 'sh'"
|
||||
@@ -96,16 +82,6 @@ pub fn (mut s Session) create() ! {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut s Session) restart() ! {
|
||||
s.stop()!
|
||||
s.create()!
|
||||
}
|
||||
|
||||
pub fn (mut s Session) stop() ! {
|
||||
osal.execute_silent('tmux kill-session -t ${s.name}') or {
|
||||
return error("Can't delete session ${s.name} - This may happen when session is not found: ${err}")
|
||||
}
|
||||
}
|
||||
|
||||
// get all windows as found in a session
|
||||
pub fn (mut s Session) windows_get() []&Window {
|
||||
@@ -118,11 +94,11 @@ pub fn (mut s Session) windows_get() []&Window {
|
||||
}
|
||||
|
||||
// List windows in a session
|
||||
pub fn (mut s Session) list_windows() []&Window {
|
||||
pub fn (mut s Session) window_list() []&Window {
|
||||
return s.windows
|
||||
}
|
||||
|
||||
pub fn (mut s Session) windownames_get() []string {
|
||||
pub fn (mut s Session) window_names() []string {
|
||||
mut res := []string{}
|
||||
for _, window in s.windows {
|
||||
res << window.name
|
||||
@@ -138,10 +114,10 @@ pub fn (mut s Session) str() string {
|
||||
return out
|
||||
}
|
||||
|
||||
pub fn (mut s Session) get_total_stats() !ProcessStats {
|
||||
pub fn (mut s Session) stats() !ProcessStats {
|
||||
mut total := ProcessStats{}
|
||||
for mut window in s.windows {
|
||||
stats := window.get_total_stats() or { continue }
|
||||
stats := window.stats() or { continue }
|
||||
total.cpu_percent += stats.cpu_percent
|
||||
total.memory_bytes += stats.memory_bytes
|
||||
total.memory_percent += stats.memory_percent
|
||||
@@ -167,3 +143,56 @@ pub fn (mut s Session) get_total_stats() !ProcessStats {
|
||||
// os.log('SESSION - Session: $s.name already activate ')
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
fn (mut s Session) window_exist(args_ WindowGetArgs) bool {
|
||||
mut args := args_
|
||||
s.window_get(args) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (mut s Session) window_get(args_ WindowGetArgs) !&Window {
|
||||
mut args := args_
|
||||
args.name = texttools.name_fix(args.name)
|
||||
for w in s.windows {
|
||||
if w.name == args.name {
|
||||
if (args.id > 0 && w.id == args.id) || args.id == 0 {
|
||||
return w
|
||||
}
|
||||
}
|
||||
}
|
||||
return error('Cannot find window ${args.name} in session:${s.name}')
|
||||
}
|
||||
|
||||
pub fn (mut s Session) window_delete(args_ WindowGetArgs) ! {
|
||||
// $if debug { console.print_debug(" - window delete: $args_")}
|
||||
mut args := args_
|
||||
args.name = texttools.name_fix(args.name)
|
||||
if !(s.window_exist(args)) {
|
||||
return
|
||||
}
|
||||
mut i := 0
|
||||
for mut w in s.windows {
|
||||
if w.name == args.name {
|
||||
if (args.id > 0 && w.id == args.id) || args.id == 0 {
|
||||
w.stop()!
|
||||
break
|
||||
}
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
s.windows.delete(i) // i is now the one in the list which needs to be removed
|
||||
}
|
||||
|
||||
|
||||
pub fn (mut s Session) restart() ! {
|
||||
s.stop()!
|
||||
s.create()!
|
||||
}
|
||||
|
||||
pub fn (mut s Session) stop() ! {
|
||||
osal.execute_silent('tmux kill-session -t ${s.name}') or {
|
||||
return error("Can't delete session ${s.name} - This may happen when session is not found: ${err}")
|
||||
}
|
||||
}
|
||||
@@ -18,127 +18,28 @@ pub mut:
|
||||
env map[string]string
|
||||
}
|
||||
|
||||
pub struct WindowArgs {
|
||||
@[params]
|
||||
pub struct PaneNewArgs {
|
||||
pub mut:
|
||||
name string
|
||||
reset bool //means we reset the pane if it already exists
|
||||
cmd string
|
||||
env map[string]string
|
||||
reset bool
|
||||
env map[string]string
|
||||
}
|
||||
|
||||
// window_name is the name of the window in session main (will always be called session main)
|
||||
// cmd to execute e.g. bash file
|
||||
// environment arguments to use
|
||||
// reset, if reset it will create window even if it does already exist, will destroy it
|
||||
// ```
|
||||
// struct WindowArgs {
|
||||
// pub mut:
|
||||
// name string
|
||||
// cmd string
|
||||
// env map[string]string
|
||||
// reset bool
|
||||
// }
|
||||
// ```
|
||||
pub fn (mut t Tmux) window_new(args WindowArgs) !Window {
|
||||
mut s := t.session_create(name: 'main', reset: false)!
|
||||
mut w := s.window_new(args)!
|
||||
return w
|
||||
|
||||
pub fn (mut w Window) scan() ! {
|
||||
//TODO: here needs to be the code to check reality and update panes
|
||||
}
|
||||
|
||||
// is always in the main tmux
|
||||
pub fn (mut t Tmux) window_delete(args WindowGetArgs) ! {
|
||||
mut s := t.session_create(name: 'main', reset: false)!
|
||||
s.window_delete(name: args.name)!
|
||||
}
|
||||
|
||||
// window_name is the name of the window in session main (will always be called session main)
|
||||
// cmd to execute e.g. bash file
|
||||
// environment arguments to use
|
||||
// reset, if reset it will create window even if it does already exist, will destroy it
|
||||
// ```
|
||||
// struct WindowArgs {
|
||||
// pub mut:
|
||||
// name string
|
||||
// cmd string
|
||||
// env map[string]string
|
||||
// reset bool
|
||||
// }
|
||||
// ```
|
||||
pub fn (mut s Session) window_new(args WindowArgs) !Window {
|
||||
$if debug {
|
||||
console.print_header(' start window: \n${args}')
|
||||
}
|
||||
namel := texttools.name_fix(args.name)
|
||||
if s.window_exist(name: namel) {
|
||||
if args.reset {
|
||||
s.window_delete(name: namel)!
|
||||
} else {
|
||||
return error('cannot create new window it already exists, window ${namel} in session:${s.name}')
|
||||
}
|
||||
}
|
||||
mut w := Window{
|
||||
session: &s
|
||||
name: namel
|
||||
panes: []&Pane{}
|
||||
env: args.env
|
||||
}
|
||||
s.windows << &w
|
||||
w.create(args.cmd)!
|
||||
// After creation, scan to populate panes
|
||||
s.tmux.scan()!
|
||||
return w
|
||||
}
|
||||
|
||||
pub struct WindowGetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
cmd string
|
||||
id int
|
||||
}
|
||||
|
||||
fn (mut s Session) window_exist(args_ WindowGetArgs) bool {
|
||||
mut args := args_
|
||||
s.window_get(args) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (mut s Session) window_get(args_ WindowGetArgs) !&Window {
|
||||
mut args := args_
|
||||
args.name = texttools.name_fix(args.name)
|
||||
for w in s.windows {
|
||||
if w.name == args.name {
|
||||
if (args.id > 0 && w.id == args.id) || args.id == 0 {
|
||||
return w
|
||||
}
|
||||
}
|
||||
}
|
||||
return error('Cannot find window ${args.name} in session:${s.name}')
|
||||
}
|
||||
|
||||
pub fn (mut s Session) window_delete(args_ WindowGetArgs) ! {
|
||||
// $if debug { console.print_debug(" - window delete: $args_")}
|
||||
mut args := args_
|
||||
args.name = texttools.name_fix(args.name)
|
||||
if !(s.window_exist(args)) {
|
||||
return
|
||||
}
|
||||
mut i := 0
|
||||
for mut w in s.windows {
|
||||
if w.name == args.name {
|
||||
if (args.id > 0 && w.id == args.id) || args.id == 0 {
|
||||
w.stop()!
|
||||
break
|
||||
}
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
s.windows.delete(i) // i is now the one in the list which needs to be removed
|
||||
}
|
||||
|
||||
pub fn (mut w Window) create(cmd_ string) ! {
|
||||
//helper function
|
||||
//TODO env variables are not inserted in pane
|
||||
fn (mut w Window) pane_create(args_ PaneNewArgs) ! {
|
||||
// tmux new-window -P -c /tmp -e good=1 -e bad=0 -n koekoe -t main bash
|
||||
mut final_cmd := cmd_
|
||||
if cmd_.contains('\n') {
|
||||
mut args := args_
|
||||
mut final_cmd := args.cmd
|
||||
if args.cmd.contains('\n') {
|
||||
// means is multiline need to write it
|
||||
// scriptpath string // is the path where the script will be put which is executed
|
||||
// scriptkeep bool // means we don't remove the script
|
||||
@@ -151,8 +52,13 @@ pub fn (mut w Window) create(cmd_ string) ! {
|
||||
final_cmd = cmd_new
|
||||
}
|
||||
|
||||
mut newcmd:='/bin/bash -c ${final_cmd}'
|
||||
if cmd_==""{
|
||||
newcmd = '/bin/bash'
|
||||
}
|
||||
|
||||
res_opt := "-P -F '#{session_name}|#{window_name}|#{window_id}|#{pane_active}|#{pane_id}|#{pane_pid}|#{pane_start_command}'"
|
||||
cmd := 'tmux new-window ${res_opt} -t ${w.session.name} -n ${w.name} \'/bin/bash -c ${final_cmd}\''
|
||||
cmd := 'tmux new-window ${res_opt} -t ${w.session.name} -n ${w.name} \'${newcmd}\''
|
||||
console.print_debug(cmd)
|
||||
res := osal.exec(cmd: cmd, stdout: false, name: 'tmux_window_create') or {
|
||||
return error("Can't create new window ${w.name} \n${cmd}\n${err}")
|
||||
@@ -166,20 +72,8 @@ pub fn (mut w Window) create(cmd_ string) ! {
|
||||
}
|
||||
}
|
||||
|
||||
// do some good checks if the window is still active
|
||||
// not implemented yet
|
||||
pub fn (mut w Window) check() ! {
|
||||
panic('not implemented yet')
|
||||
}
|
||||
|
||||
// restart the window
|
||||
pub fn (mut w Window) restart() ! {
|
||||
w.stop()!
|
||||
w.create()!
|
||||
}
|
||||
|
||||
// stop the window
|
||||
pub fn (mut w Window) stop() ! {
|
||||
pub fn (mut w Window) kill() ! {
|
||||
osal.exec(
|
||||
cmd: 'tmux kill-window -t @${w.id}'
|
||||
stdout: false
|
||||
@@ -197,10 +91,10 @@ pub fn (window Window) str() string {
|
||||
return out
|
||||
}
|
||||
|
||||
pub fn (mut w Window) get_total_stats() !ProcessStats {
|
||||
pub fn (mut w Window) stats() !ProcessStats {
|
||||
mut total := ProcessStats{}
|
||||
for mut pane in w.panes {
|
||||
stats := pane.get_stats() or { continue }
|
||||
stats := pane.stats() or { continue }
|
||||
total.cpu_percent += stats.cpu_percent
|
||||
total.memory_bytes += stats.memory_bytes
|
||||
total.memory_percent += stats.memory_percent
|
||||
@@ -218,12 +112,12 @@ fn (mut w Window) activate() ! {
|
||||
}
|
||||
|
||||
// List panes in a window
|
||||
pub fn (mut w Window) list_panes() []&Pane {
|
||||
return w.panes
|
||||
pub fn (mut w Window) pane_list() []&Pane {
|
||||
return w.panes
|
||||
}
|
||||
|
||||
// Get active pane in window
|
||||
pub fn (mut w Window) get_active_pane() ?&Pane {
|
||||
pub fn (mut w Window) pane_active() ?&Pane {
|
||||
for pane in w.panes {
|
||||
if pane.active {
|
||||
return pane
|
||||
@@ -231,50 +125,3 @@ pub fn (mut w Window) get_active_pane() ?&Pane {
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
// show the environment
|
||||
pub fn (mut w Window) environment_print() ! {
|
||||
// This function needs to be updated to target a specific pane, not the window directly.
|
||||
// For now, I'll leave it as is, but it's a point for future refinement.
|
||||
// It should probably take a pane ID or operate on the active pane.
|
||||
return error('Window.environment_print() needs to be updated to target a specific pane.')
|
||||
}
|
||||
|
||||
// capture the output
|
||||
pub fn (mut w Window) output_print() ! {
|
||||
o := w.output()!
|
||||
console.print_debug(o)
|
||||
}
|
||||
|
||||
// capture the output
|
||||
pub fn (mut w Window) output() !string {
|
||||
//-S is start, minus means go in history, otherwise its only the active output
|
||||
// tmux capture-pane -t your-session-name:your-window-number -S -1000
|
||||
cmd := 'tmux capture-pane -t ${w.session.name}:@${w.id} -S -1000 && tmux show-buffer'
|
||||
res := osal.execute_silent(cmd) or {
|
||||
return error('Couldnt show enviroment cmd: ${w.cmd} \n${err}')
|
||||
}
|
||||
return texttools.remove_empty_lines(res)
|
||||
}
|
||||
|
||||
pub fn (mut w Window) output_wait(c_ string, timeoutsec int) ! {
|
||||
mut t := ourtime.now()
|
||||
start := t.unix()
|
||||
c := c_.replace('\n', '')
|
||||
for i in 0 .. 2000 {
|
||||
o := w.output()!
|
||||
// console.print_debug(o)
|
||||
$if debug {
|
||||
console.print_debug(" - tmux ${w.name}: wait for: '${c}'")
|
||||
}
|
||||
// need to replace \n because can be wrapped because of size of pane
|
||||
if o.replace('\n', '').contains(c) {
|
||||
return
|
||||
}
|
||||
mut t2 := ourtime.now()
|
||||
if t2.unix() > start + timeoutsec {
|
||||
return error('timeout on output wait for tmux.\n${w} .\nwaiting for:\n${c}')
|
||||
}
|
||||
time.sleep(100 * time.millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user