21 proc setDebugMode {mode} {
26 proc getDebugMode {} {
31 proc printDebugMode {} {
34 Msg Info "DEBUG_MODE is set to $DEBUG_MODE"
36 Msg Info "DEBUG_MODE is not set or is 0"
44 proc dictSafeGet {d args} {
45 if {[dict exists $d {*}$args]} {
46 return [dict get $d {*}$args]
57 proc Msg {level fmsg {title ""}} {
60 set level [
string tolower $level]
61 if {$title == ""} {
set title [
lindex [
info level [
expr {[info level] - 1}]] 0]}
62 if {$level == 0 || $level == "status" || $level == "extra_info"} {
65 }
elseif {$level == 1 || $level == "info"} {
68 }
elseif {$level == 2 || $level == "warning"} {
71 }
elseif {$level == 3 || [
string first "critical" $level] != -1} {
72 set vlevel {CRITICAL WARNING}
73 set qlevel critical_warning
74 }
elseif {$level == 4 || $level == "error"} {
77 }
elseif {$level == 5 || $level == "debug"} {
78 if {([
info exists ::DEBUG_MODE] && $::DEBUG_MODE == 1) || (
79 [
info exists ::env(HOG_DEBUG_MODE)] && $::env(HOG_DEBUG_MODE) == 1
83 set msg "DEBUG: \[Hog:$title\] $msg"
88 puts "Hog Error: level $level not defined"
93 if {[
string match "-*" $msg]} {
96 set status [
catch {send_msg_id Hog:$title-0 $vlevel "$msg"}]
102 post_message -type $qlevel "Hog:$title $msg"
103 if {$qlevel == "error"} {
108 if {$vlevel != "STATUS"} {
109 puts "$vlevel: \[Hog:$title\] $msg"
114 ([
dictSafeGet $HogEnvDict terminal colored] > 0) ||
115 ([
info exists ::env(HOG_COLOR)] &&
116 ([
string match "ENABLED" $::env(HOG_COLOR)] ||
117 ([
string is integer -strict $::env(HOG_COLOR)] && $::env(HOG_COLOR) > 0)
121 ([
info exists ::env(HOG_LOGGER)] && ([
string match "ENABLED" $::env(HOG_LOGGER)]))
128 if {$qlevel == "error"} {
141 proc MsgAndLog {msg {severity "CriticalWarning"} {outFile ""}} {
143 if {$outFile != ""} {
144 set directory [
file dir $outFile]
145 if {![
file exists $directory]} {
146 Msg Info "Creating $directory..."
147 file mkdir $directory
150 set oF [open "$outFile" a+]
160 proc Logo {{repo_path .}} {
162 if {![
info exists ::env(HOG_LOGO_PRINTED)] || $::env(HOG_LOGO_PRINTED) eq "0"} {
164 [
info exists ::env(HOG_COLOR)] && ([
string match "ENABLED" $::env(HOG_COLOR)] || [
string is integer -strict $::env(HOG_COLOR)] && $::env(HOG_COLOR) > 0)
166 set logo_file "$repo_path/Hog/images/hog_logo_color.txt"
168 set logo_file "$repo_path/Hog/images/hog_logo.txt"
172 set ver [
Git {describe --always}]
176 if {[
file exists $logo_file]} {
177 set f [open $logo_file "r"]
180 set lines [
split $data "\n"]
182 if {[regexp {(Version:)[ ]+} $l -> prefix]} {
183 set string_len [
string length $l]
185 set version_string "* Version: $ver"
186 set version_len [
string length $version_string]
187 append version_string [
string repeat " " [
expr {$string_len - $version_len - 1}]] "*"
188 set l $version_string
193 Msg CriticalWarning "Logo file: $logo_file not found"
207 proc PrintFileContent {filename} {
209 set file [open $filename r]
212 set content [read $file]
228 proc PrintFileTree {{data} {repo_path} {indentation ""}} {
233 if {![regexp {^[\t\s]*$} $line] & ![regexp {^[\t\s]*\#} $line]} {
234 lappend print_list "$line"
239 foreach p $print_list {
241 if {$i == [
llength $print_list]} {
246 set file_name [
lindex [
split $p] 0]
247 if {[
file exists [
file normalize [
lindex [glob -nocomplain $repo_path/$file_name] 0]]]} {
250 set exists " !!!!! NOT FOUND !!!!!"
253 Msg Status "$indentation$pad$p$exists"
254 set last_printed $file_name
263 namespace eval Hog::LoggerLib {
265 variable toml_dict {}
274 proc GetUserFilePath {filename} {
275 set homeDir [
file normalize ~]
276 set fullPath [
file join $homeDir $filename]
277 if {[
file exists $fullPath]} {
291 proc ParseTOML {toml_file} {
298 if {![
file exists $toml_file]} {
299 Msg Warning "TOML file $toml_file does not exist"
302 if {[
catch {open $toml_file r} file_handle]} {
303 Msg Error "Cannot open TOML file $toml_file: $file_handle"
307 set current_section ""
309 set in_multiline_string 0
310 set multiline_buffer ""
312 while {[
gets $file_handle line] >= 0} {
315 if {$in_multiline_string} {
316 if {[
string match "*\"\"\"*" $line]} {
318 set end_pos [
string first "\"\"\"" $line]
319 append multiline_buffer [
string range $line 0 [
expr $end_pos - 1]]
320 if {$current_section eq ""} {
321 dict set toml_dict $multiline_key $multiline_buffer
323 dict set toml_dict $current_section $multiline_key $multiline_buffer
325 set in_multiline_string 0
326 set multiline_buffer ""
329 append multiline_buffer $line "\n"
337 for {
set i 0} {$i < [
string length $line]} {
incr i} {
338 set char [
string index $line $i]
339 if {!$in_quotes && ($char eq "\"" || $char eq "'")} {
342 append clean_line $char
343 }
elseif {$in_quotes && $char eq $quote_char} {
346 append clean_line $char
347 }
elseif {!$in_quotes && $char eq "#"} {
350 append clean_line $char
353 set line [
string trim $clean_line]
359 if {[regexp {^\[([^\]]+)\]$} $line match section_name]} {
360 set current_section $section_name
362 if {![dict exists $toml_dict $current_section]} {
363 dict set toml_dict $current_section [dict create]
368 if {[regexp {^([^=]+)=(.*)$} $line match raw_key raw_value]} {
369 set key [
string trim $raw_key]
370 set value [
string trim $raw_value]
372 if {[
string match "*\"\"\"*" $value] && ![
string match "*\"\"\"*\"\"\"*" $value]} {
373 set start_pos [
string first "\"\"\"" $value]
374 set multiline_key $key
375 set multiline_buffer [
string range $value [
expr $start_pos + 3] end]
376 append multiline_buffer "\n"
377 set in_multiline_string 1
383 if {[
string match "*.*" $key]} {
384 set key_parts [
split $key "."]
385 set dict_ref toml_dict
386 if {$current_section ne ""} {
387 lappend dict_ref $current_section
389 for {
set i 0} {$i < [
expr [
llength $key_parts] - 1]} {
incr i} {
390 set part [
lindex $key_parts $i]
391 lappend dict_ref $part
392 if {![dict exists {*}$dict_ref]} {
393 dict set {*}$dict_ref [dict create]
396 set final_key [
lindex $key_parts end]
397 lappend dict_ref $final_key
398 dict set {*}$dict_ref $parsed_value
401 if {$current_section eq ""} {
402 dict set toml_dict $key $parsed_value
404 dict set toml_dict $current_section $key $parsed_value
419 proc ParseTOMLValue {value} {
420 set value [
string trim $value]
422 if {$value eq "true"} {
424 }
elseif {$value eq "false"} {
428 if {[regexp {^"(.*)"$} $value match string_content]} {
430 set string_content [
string map {\\" \" \\\\ \\ \\n \n \\t \t \\r \r} $string_content]
431 return $string_content
432 }
elseif {[regexp {^'(.*)'$} $value match string_content]} {
434 return $string_content
437 if {[
string match {\[*\]} $value]} {
438 set array_content [
string range $value 1 end-1]
439 set array_content [
string trim $array_content]
440 if {$array_content eq ""} {
444 set current_element ""
448 for {
set i 0} {$i < [
string length $array_content]} {
incr i} {
449 set char [
string index $array_content $i]
450 if {!$in_quotes && ($char eq "\"" || $char eq "'")} {
453 append current_element $char
454 }
elseif {$in_quotes && $char eq $quote_char} {
457 append current_element $char
458 }
elseif {!$in_quotes && $char eq "\["} {
460 append current_element $char
461 }
elseif {!$in_quotes && $char eq "\]"} {
462 incr bracket_depth -1
463 append current_element $char
464 }
elseif {!$in_quotes && $char eq "," && $bracket_depth == 0} {
466 set current_element ""
468 append current_element $char
471 if {$current_element ne ""} {
477 if {[
string is integer $value]} {
478 return [
expr {int($value)}]
479 }
elseif {[
string is double $value]} {
480 return [
expr {double($value)}]
483 if {[regexp {^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}} $value]} {
497 proc GetTOMLValue {toml_dict key_path} {
498 set key_parts [
split $key_path "."]
499 set current_dict $toml_dict
500 foreach part $key_parts {
501 if {[dict exists $current_dict $part]} {
502 set current_dict [dict get $current_dict $part]
515 proc PrintTOMLDict {toml_dict {indent 0}} {
516 set indent_str [
string repeat " " $indent]
517 dict for {key value} $toml_dict {
518 if {[string is list $value] && [llength $value] > 1 && [string is list [lindex $value 0]]} {
519 # This is likely a nested dictionary
520 Msg Debug "${indent_str}${key}:"
521 if {[catch {dict for {subkey subvalue} $value {}} result]} {
522 # Not a dictionary, print as value
523 Msg Debug "${indent_str} $value"
525 PrintTOMLDict $value [expr {$indent + 1}]
527 } elseif {[string is list $value] && [llength $value] > 0} {
529 Msg Debug "${indent_str}${key}: \[list of [llength $value] items\]"
530 foreach item $value {
531 Msg Debug "${indent_str} - $item"
534 Msg Debug "${indent_str}${key}: $value"
542 proc GetTOMLDict {} {
544 if {[
info exists toml_dict]} {