Files
herolib/lib/osal/screen/factory.v
2024-12-25 08:40:56 +01:00

178 lines
3.9 KiB
V

module screen
// import freeflowuniverse.herolib.osal
import freeflowuniverse.herolib.core.texttools
// import freeflowuniverse.herolib.screen
import os
import time
import freeflowuniverse.herolib.ui.console
@[heap]
pub struct ScreensFactory {
pub mut:
screens []Screen
}
@[params]
pub struct ScreensNewArgs {
pub:
reset bool
}
// return screen instance
pub fn new(args ScreensNewArgs) !ScreensFactory {
mut t := ScreensFactory{}
t.scan()!
if args.reset {
t.reset()!
}
return t
}
pub fn init_screen_object(item_ map[string]string) Screen {
mut item := Screen{}
state_item := item_['state'] or { panic('bug') }
item.state = match state_item.trim('() ').to_lower() {
'detached' { .detached }
else { .unknown }
}
pre := item_['pre'] or { panic('bug') }
item.pid = pre.all_before('.').trim_space().int()
item.name = pre.all_after('.').trim_space()
return item
}
// loads screen screen, populate the object
pub fn (mut self ScreensFactory) scan() ! {
self.screens = []Screen{}
os.execute('screen -wipe > /dev/null 2>&1') // make sure its all clean
res := os.execute('screen -ls')
if res.exit_code > 1 {
return error('could not find screen or other error, make sure screen is installed.\n${res.output}')
}
if res.output.contains('No Sockets found') {
return
}
// there is stuff to parses
res1 := texttools.remove_empty_lines(res.output)
.split_into_lines()
.filter(it.starts_with(' ') || it.starts_with('\t'))
.join_lines()
mut res2 := texttools.to_list_map('pre,state', res1, '').map(init_screen_object(it))
for mut item in res2 {
if self.exists(item.name) {
return error('duplicate screen with name: ${item.name}')
}
self.screens << item
}
// console.print_debug(self.str())
}
pub struct ScreenAddArgs {
pub mut:
name string @[requred]
cmd string
reset bool
start bool = true
attach bool
}
// print list of screen screens
pub fn (mut self ScreensFactory) add(args_ ScreenAddArgs) !Screen {
mut args := args_
if args.cmd == '' {
args.cmd = '/bin/bash'
}
if args.name.len < 3 {
return error('name needs to be at least 3 chars.')
}
if self.exists(args.name) {
if args.reset {
self.kill(args.name)!
} else {
return self.get(args.name)!
}
}
self.screens << Screen{
name: args.name
cmd: args.cmd
}
if args.start {
self.start(args.name)!
}
mut myscreen := self.get(args.name) or {
return error('couldnt start screen with name ${args.name}, was not found afterwards.\ncmd:${args.cmd}\nScreens found.\n${self.str()}')
}
if args.attach {
myscreen.attach()!
}
return myscreen
}
// print list of screen screens
pub fn (mut self ScreensFactory) exists(name string) bool {
for mut screen in self.screens {
if screen.name == name {
return true
}
}
return false
}
pub fn (mut self ScreensFactory) get(name string) !Screen {
for mut screen in self.screens {
if screen.name == name {
return screen
}
}
// print_backtrace()
return error('couldnt find screen with name ${name}\nScreens found.\n${self.str()}')
}
pub fn (mut self ScreensFactory) start(name string) ! {
mut s := self.get(name) or {
return error("can't start screen with name:${name}, couldn't find.\nScreens found.\n${self.str()}")
}
s.start_()!
for {
self.scan()!
mut s2 := self.get(name) or {
return error('couldnt start screen with name ${name}, was not found in screen scan.\ncmd:\n${s.cmd}\nScreens found.\n${self.str()}')
}
if s2.pid > 0 {
return
}
console.print_debug(s2.str())
time.sleep(100000)
}
}
pub fn (mut self ScreensFactory) kill(name string) ! {
if self.exists(name) {
mut s := self.get(name) or { return }
s.kill_()!
}
self.scan()!
}
// print list of screen screens
pub fn (mut self ScreensFactory) reset() ! {
for mut screen in self.screens {
screen.kill_()!
}
self.scan()!
}
pub fn (mut self ScreensFactory) str() string {
if self.screens.len == 0 {
return 'No screens found.'
}
mut out := '# Screens\n'
for s in self.screens {
out += '${s}\n'
}
return out
}