You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

161 lines
5.7 KiB

#punkapps app manager
# deck cli
namespace eval punk::mod::cli {
namespace export help list run
namespace ensemble create
# namespace ensemble configure [namespace current] -unknown punk::mod::cli::_unknown
if 0 {
proc _unknown {ns args} {
puts stderr "punk::mod::cli::_unknown '$ns' '$args'"
puts stderr "punk::mod::cli::help $args"
puts stderr "arglen:[llength $args]"
punk::mod::cli::help {*}$args
}
}
#cli must have _init method - usually used to load commandsets lazily
#
variable initialised 0
proc _init {args} {
variable initialised
if {$initialised} {
return
}
#...
set initialised 1
}
proc help {args} {
set basehelp [punk::mix::base help {*}$args]
#namespace export
return $basehelp
}
proc getraw {appname} {
set app_folders [punk::config::configure running apps]
#todo search each app folder
set bases [::list]
set versions [::list]
set mains [::list]
set appinfo [::list bases {} mains {} versions {}]
foreach containerfolder $app_folders {
lappend bases $containerfolder
if {[file exists $containerfolder]} {
if {[file exists $containerfolder/$appname/main.tcl]} {
#exact match - only return info for the exact one specified
set namematches $appname
set parts [split $appname -]
} else {
set namematches [glob -nocomplain -dir $containerfolder -type d -tail ${appname}-*]
set namematches [lsort $namematches] ;#todo - -ascii? -dictionary? natsort?
}
foreach nm $namematches {
set mainfile $containerfolder/$nm/main.tcl
set parts [split $nm -]
if {[llength $parts] == 1} {
set ver ""
} else {
set ver [lindex $parts end]
}
if {$ver ni $versions} {
lappend versions $ver
lappend mains $ver $mainfile
} else {
puts stderr "punk::apps::app version '$ver' of app '$appname' already encountered at $mainfile. (will use earliest encountered in running-config apps and ignore others of same version)"
}
}
} else {
puts stderr "punk::apps::app missing apps_folder:'$containerfolder' Ensure apps_folder is set in punk::config"
}
}
dict set appinfo versions $versions
#todo - natsort!
set sorted_versions [lsort $versions]
set latest [lindex $sorted_versions 0]
if {$latest eq "" && [llength $sorted_versions] > 1} {
set latest [lindex $sorted_versions 1]
}
dict set appinfo latest $latest
dict set appinfo bases $bases
dict set appinfo mains $mains
return $appinfo
}
proc list {{glob *}} {
set apps_folder [punk::config::configure running apps]
if {[file exists $apps_folder]} {
if {[file exists $apps_folder/$glob]} {
#tailcall source $apps_folder/$glob/main.tcl
return $glob
}
set apps [glob -nocomplain -dir $apps_folder -type d -tail $glob]
if {[llength $apps] == 0} {
if {[string first * $glob] <0 && [string first ? $glob] <0} {
#no glob chars supplied - only launch if exact match for name part
set namematches [glob -nocomplain -dir $apps_folder -type d -tail ${glob}-*]
set namematches [lsort $namematches] ;#todo - -ascii? -dictionary? natsort?
if {[llength $namematches] > 0} {
set latest [lindex $namematches end]
lassign $latest nm ver
#tailcall source $apps_folder/$latest/main.tcl
}
}
}
return $apps
}
}
#todo - way to launch as separate process
# solo-opts only before appname - args following appname are passed to the app
proc run {args} {
set nameposn [lsearch -not $args -*]
if {$nameposn < 0} {
error "punkapp::run unable to determine application name"
}
set appname [lindex $args $nameposn]
set controlargs [lrange $args 0 $nameposn-1]
set appargs [lrange $args $nameposn+1 end]
set appinfo [punk::mod::cli::getraw $appname]
if {[llength [dict get $appinfo versions]]} {
set ver [dict get $appinfo latest]
puts stdout "info: $appinfo"
set ::argc [llength $appargs]
set ::argv $appargs
source [dict get $appinfo mains $ver]
if {"-hideconsole" in $controlargs} {
puts stderr "attempting console hide"
#todo - something better - a callback when window mapped?
after 500 {::punkapp::hide_console}
}
return $appinfo
} else {
error "punk::mod::cli unable to run '$appname'. main.tcl not found in [dict get $appinfo bases]"
}
}
}
namespace eval punk::mod::cli {
proc _cli {args} {
#don't use tailcall - base uses info level to determine caller
::punk::mix::base::_cli {*}$args
}
variable default_command help
package require punk::mix::base
package require punk::overlay
punk::overlay::custom_from_base [namespace current] ::punk::mix::base
}
package provide punk::mod [namespace eval punk::mod {
variable version
set version 0.1
}]