Browse Source

initial textblock::frame_cache, a? ansi colourset displays

master
Julian Noble 6 months ago
parent
commit
aaaacfb293
  1. 1
      src/modules/punk-0.1.tm
  2. 595
      src/modules/punk/ansi-999999.0a1.0.tm
  3. 20
      src/modules/punk/char-999999.0a1.0.tm
  4. 141
      src/modules/punk/lib-999999.0a1.0.tm
  5. 2
      src/modules/punk/ns-999999.0a1.0.tm
  6. 219
      src/modules/textblock-999999.0a1.0.tm

1
src/modules/punk-0.1.tm

@ -6932,6 +6932,7 @@ namespace eval punk {
set cmdinfo [list]
lappend cmdinfo [list help "This help. To see available subitems type: help topics"]
lappend cmdinfo [list deck "(ensemble command to make new projects/modules and to generate docs)"]
lappend cmdinfo [list a? "view ANSI colours"]
lappend cmdinfo [list ./ "view/change directory"]
lappend cmdinfo [list ../ "go up one directory"]
lappend cmdinfo [list ./new "make new directory and switch to it"]

595
src/modules/punk/ansi-999999.0a1.0.tm

@ -761,19 +761,21 @@ namespace eval punk::ansi {
#CSI <n> m = SGR (Select Graphic Rendition)
#leave map unindented - used both as a dict and for direct display
variable SGR_setting_map {
reset 0 bold 1 dim 2 italic 3 noitalic 23
underline 4 doubleunderline 21 nounderline 24 blink 5 fastblink 6 noblink 25
reverse 7 noreverse 27 hide 8 nohide 28 strike 9 nostrike 29
normal 22 defaultfg 39 defaultbg 49 overline 53 nooverline 55
frame 51 framecircle 52 noframe 54 underlinedefault 59
reset 0 bold 1 dim 2 italic 3 noitalic 23
underline 4 doubleunderline 21 nounderline 24 blink 5 fastblink 6 noblink 25
reverse 7 noreverse 27 hide 8 nohide 28 strike 9 nostrike 29
normal 22 defaultfg 39 defaultbg 49 overline 53 nooverline 55
frame 51 framecircle 52 noframe 54 underlinedefault 59
}
#unprefixed colours are (close to) the ansi-specified colour names (lower-cased and whitespace collapsed, with capitalisation of 1st letter given fg/bg meaning here)
#leave map unindented - used both as a dict and for direct display
variable SGR_colour_map {
black 30 red 31 green 32 yellow 33 blue 34 purple 35 cyan 36 white 37
Black 40 Red 41 Green 42 Yellow 43 Blue 44 Purple 45 Cyan 46 White 47
brightblack 90 brightred 91 brightgreen 92 brightyellow 93 brightblue 94 brightpurple 95 brightcyan 96 brightwhite 97
Brightblack 100 Brightred 101 Brightgreen 102 Brightyellow 103 Brightblue 104 Brightpurple 105 Brightcyan 106 Brightwhite 107
black 30 red 31 green 32 yellow 33 blue 34 purple 35 cyan 36 white 37
Black 40 Red 41 Green 42 Yellow 43 Blue 44 Purple 45 Cyan 46 White 47
brightblack 90 brightred 91 brightgreen 92 brightyellow 93 brightblue 94 brightpurple 95 brightcyan 96 brightwhite 97
Brightblack 100 Brightred 101 Brightgreen 102 Brightyellow 103 Brightblue 104 Brightpurple 105 Brightcyan 106 Brightwhite 107
}
variable SGR_map ;#public - part of interface - review
set SGR_map [dict merge $SGR_colour_map $SGR_setting_map]
@ -792,185 +794,211 @@ namespace eval punk::ansi {
# -- --- ---
#css 1-2.0 HTML 3.2-4 Basic colours eg web-silver for fg Web-silver for bg
#
dict set WEB_colour_map white 255-255-255 ;# #FFFFFF
dict set WEB_colour_map silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map gray 128-128-128 ;# #808080
dict set WEB_colour_map black 0-0-0 ;# #000000
dict set WEB_colour_map red 255-0-0 ;# #FF0000
dict set WEB_colour_map maroon 128-0-0 ;# #800000
dict set WEB_colour_map yellow 255-255-0 ;# #FFFF00
dict set WEB_colour_map olive 128-128-0 ;# #808000
dict set WEB_colour_map lime 0-255-0 ;# #00FF00
dict set WEB_colour_map green 0-128-0 ;# #008000
dict set WEB_colour_map aqua 0-255-255 ;# #00FFFF
dict set WEB_colour_map teal 0-128-128 ;# #008080
dict set WEB_colour_map blue 0-0-255 ;# #0000FF
dict set WEB_colour_map navy 0-0-128 ;# #000080
dict set WEB_colour_map fuchsia 255-0-255 ;# #FF00FF
dict set WEB_colour_map purple 128-0-128 ;# #800080
variable WEB_colour_map_basic
dict set WEB_colour_map_basic white 255-255-255 ;# #FFFFFF
dict set WEB_colour_map_basic silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map_basic gray 128-128-128 ;# #808080
dict set WEB_colour_map_basic black 0-0-0 ;# #000000
dict set WEB_colour_map_basic red 255-0-0 ;# #FF0000
dict set WEB_colour_map_basic maroon 128-0-0 ;# #800000
dict set WEB_colour_map_basic yellow 255-255-0 ;# #FFFF00
dict set WEB_colour_map_basic olive 128-128-0 ;# #808000
dict set WEB_colour_map_basic lime 0-255-0 ;# #00FF00
dict set WEB_colour_map_basic green 0-128-0 ;# #008000
dict set WEB_colour_map_basic aqua 0-255-255 ;# #00FFFF
dict set WEB_colour_map_basic teal 0-128-128 ;# #008080
dict set WEB_colour_map_basic blue 0-0-255 ;# #0000FF
dict set WEB_colour_map_basic navy 0-0-128 ;# #000080
dict set WEB_colour_map_basic fuchsia 255-0-255 ;# #FF00FF
dict set WEB_colour_map_basic purple 128-0-128 ;# #800080
# -- --- ---
#Pink colours
dict set WEB_colour_map mediumvioletred 199-21-133 ;# #C71585
dict set WEB_colour_map deeppink 255-20-147 ;# #FF1493
dict set WEB_colour_map palevioletred 219-112-147 ;# #DB7093
dict set WEB_colour_map hotpink 255-105-180 ;# #FF69B4
dict set WEB_colour_map lightpink 255-182-193 ;# #FFB6C1
dict set WEB_colour_map pink 255-192-203 ;# #FFCOCB
variable WEB_colour_map_pink
dict set WEB_colour_map_pink mediumvioletred 199-21-133 ;# #C71585
dict set WEB_colour_map_pink deeppink 255-20-147 ;# #FF1493
dict set WEB_colour_map_pink palevioletred 219-112-147 ;# #DB7093
dict set WEB_colour_map_pink hotpink 255-105-180 ;# #FF69B4
dict set WEB_colour_map_pink lightpink 255-182-193 ;# #FFB6C1
dict set WEB_colour_map_pink pink 255-192-203 ;# #FFCOCB
# -- --- ---
#Red colours
dict set WEB_colour_map darkred 139-0-0 ;# #8B0000
#red - as above
dict set WEB_colour_map firebrick 178-34-34 ;# #B22222
dict set WEB_colour_map crimson 220-20-60 ;# #DC143C
dict set WEB_colour_map indianred 205-92-92 ;# #CD5C5C
dict set WEB_colour_map lightcoral 240-128-128 ;# #F08080
dict set WEB_colour_map salmon 250-128-114 ;# #FA8072
dict set WEB_colour_map darksalmon 233-150-122 ;# #E9967A
dict set WEB_colour_map lightsalmon 255-160-122 ;# #FFA07A
variable WEB_colour_map_red
dict set WEB_colour_map_red darkred 139-0-0 ;# #8B0000
dict set WEB_colour_map_red red 255-0-0 ;# #FF0000
dict set WEB_colour_map_red firebrick 178-34-34 ;# #B22222
dict set WEB_colour_map_red crimson 220-20-60 ;# #DC143C
dict set WEB_colour_map_red indianred 205-92-92 ;# #CD5C5C
dict set WEB_colour_map_red lightcoral 240-128-128 ;# #F08080
dict set WEB_colour_map_red salmon 250-128-114 ;# #FA8072
dict set WEB_colour_map_red darksalmon 233-150-122 ;# #E9967A
dict set WEB_colour_map_red lightsalmon 255-160-122 ;# #FFA07A
# -- --- ---
#Orange colours
dict set WEB_colour_map orangered 255-69-0 ;# #FF4500
dict set WEB_colour_map tomato 255-99-71 ;# #FF6347
dict set WEB_colour_map darkorange 255-140-0 ;# #FF8C00
dict set WEB_colour_map coral 255-127-80 ;# #FF7F50
dict set WEB_colour_map orange 255-165-0 ;# #FFA500
variable WEB_colour_map_orange
dict set WEB_colour_map_orange orangered 255-69-0 ;# #FF4500
dict set WEB_colour_map_orange tomato 255-99-71 ;# #FF6347
dict set WEB_colour_map_orange darkorange 255-140-0 ;# #FF8C00
dict set WEB_colour_map_orange coral 255-127-80 ;# #FF7F50
dict set WEB_colour_map_orange orange 255-165-0 ;# #FFA500
# -- --- ---
#Yellow colours
dict set WEB_colour_map darkkhaki 189-183-107 ;# #BDB76B
dict set WEB_colour_map gold 255-215-0 ;# #FFD700
dict set WEB_colour_map khaki 240-230-140 ;# #F0E68C
dict set WEB_colour_map peachpuff 255-218-185 ;# #FFDAB9
#yellow - as above
dict set WEB_colour_map palegoldenrod 238-232-170 ;# #EEE8AA
dict set WEB_colour_map moccasin 255-228-181 ;# #FFE4B5
dict set WEB_colour_map papayawhip 255-239-213 ;# #FFEFD5
dict set WEB_colour_map lightgoldenrodyeallow 250-250-210 ;# #FAFAD2
dict set WEB_colour_map lemonchiffon 255-250-205 ;# #FFFACD
dict set WEB_colour_map lightyellow 255-255-224 ;# #FFFFE0
variable WEB_colour_map_yellow
dict set WEB_colour_map_yellow darkkhaki 189-183-107 ;# #BDB76B
dict set WEB_colour_map_yellow gold 255-215-0 ;# #FFD700
dict set WEB_colour_map_yellow khaki 240-230-140 ;# #F0E68C
dict set WEB_colour_map_yellow peachpuff 255-218-185 ;# #FFDAB9
dict set WEB_colour_map_yellow yellow 255-255-0 ;# #FFFF00
dict set WEB_colour_map_yellow palegoldenrod 238-232-170 ;# #EEE8AA
dict set WEB_colour_map_yellow moccasin 255-228-181 ;# #FFE4B5
dict set WEB_colour_map_yellow papayawhip 255-239-213 ;# #FFEFD5
dict set WEB_colour_map_yellow lightgoldenrodyeallow 250-250-210 ;# #FAFAD2
dict set WEB_colour_map_yellow lemonchiffon 255-250-205 ;# #FFFACD
dict set WEB_colour_map_yellow lightyellow 255-255-224 ;# #FFFFE0
# -- --- ---
#Brown colours
#maroon as above
dict set WEB_colour_map brown 165-42-42 ;# #A52A2A
dict set WEB_colour_map saddlebrown 139-69-19 ;# #8B4513
dict set WEB_colour_map sienna 160-82-45 ;# #A0522D
dict set WEB_colour_map chocolate 210-105-30 ;# #D2691E
dict set WEB_colour_map darkgoldenrod 184-134-11 ;# #B8860B
dict set WEB_colour_map peru 205-133-63 ;# #CD853F
dict set WEB_colour_map rosybrown 188-143-143 ;# #BC8F8F
dict set WEB_colour_map goldenrod 218-165-32 ;# #DAA520
dict set WEB_colour_map sandybrown 244-164-96 ;# #F4A460
dict set WEB_colour_map tan 210-180-140 ;# #D2B48C
dict set WEB_colour_map burlywood 222-184-135 ;# #DEB887
dict set WEB_colour_map wheat 245-222-179 ;# #F5DEB3
dict set WEB_colour_map navajowhite 255-222-173 ;# #FFDEAD
dict set WEB_colour_map bisque 255-228-196 ;# #FFEfC4
dict set WEB_colour_map blanchedalmond 255-228-196 ;# #FFEfC4
dict set WEB_colour_map cornsilk 255-248-220 ;# #FFF8DC
variable WEB_colour_map_brown
dict set WEB_colour_map_brown brown 165-42-42 ;# #A52A2A
dict set WEB_colour_map_brown saddlebrown 139-69-19 ;# #8B4513
dict set WEB_colour_map_brown sienna 160-82-45 ;# #A0522D
dict set WEB_colour_map_brown chocolate 210-105-30 ;# #D2691E
dict set WEB_colour_map_brown darkgoldenrod 184-134-11 ;# #B8860B
dict set WEB_colour_map_brown peru 205-133-63 ;# #CD853F
dict set WEB_colour_map_brown rosybrown 188-143-143 ;# #BC8F8F
dict set WEB_colour_map_brown goldenrod 218-165-32 ;# #DAA520
dict set WEB_colour_map_brown sandybrown 244-164-96 ;# #F4A460
dict set WEB_colour_map_brown tan 210-180-140 ;# #D2B48C
dict set WEB_colour_map_brown burlywood 222-184-135 ;# #DEB887
dict set WEB_colour_map_brown wheat 245-222-179 ;# #F5DEB3
dict set WEB_colour_map_brown navajowhite 255-222-173 ;# #FFDEAD
dict set WEB_colour_map_brown bisque 255-228-196 ;# #FFEfC4
dict set WEB_colour_map_brown blanchedalmond 255-228-196 ;# #FFEfC4
dict set WEB_colour_map_brown cornsilk 255-248-220 ;# #FFF8DC
# -- --- ---
#Purple, violet, and magenta colours
dict set WEB_colour_map indigo 75-0-130 ;# #4B0082
#purple as above
dict set WEB_colour_map darkmagenta 139-0-139 ;# #8B008B
dict set WEB_colour_map darkviolet 148-0-211 ;# #9400D3
dict set WEB_colour_map darkslateblue 72-61-139 ;# #9400D3
dict set WEB_colour_map blueviolet 138-43-226 ;# #8A2BE2
dict set WEB_colour_map darkorchid 153-50-204 ;# #9932CC
#fuchsia as above
dict set WEB_colour_map magenta 255-0-255 ;# #FF00FF - same as fuchsia
dict set WEB_colour_map slateblue 106-90-205 ;# #6A5ACD
dict set WEB_colour_map mediumslateblue 123-104-238 ;# #7B68EE
dict set WEB_colour_map mediumorchid 186-85-211 ;# #BA5503
dict set WEB_colour_map mediumpurple 147-112-219 ;# #9370DB
dict set WEB_colour_map orchid 218-112-214 ;# #DA70D6
dict set WEB_colour_map violet 238-130-238 ;# #EE82EE
dict set WEB_colour_map plum 221-160-221 ;# #DDA0DD
dict set WEB_colour_map thistle 216-191-216 ;# #D88FD8
dict set WEB_colour_map lavender 230-230-150 ;# #E6E6FA
variable WEB_colour_map_purple
dict set WEB_colour_map_purple indigo 75-0-130 ;# #4B0082
dict set WEB_colour_map_purple purple 128-0-128 ;# #800080
dict set WEB_colour_map_purple darkmagenta 139-0-139 ;# #8B008B
dict set WEB_colour_map_purple darkviolet 148-0-211 ;# #9400D3
dict set WEB_colour_map_purple darkslateblue 72-61-139 ;# #9400D3
dict set WEB_colour_map_purple blueviolet 138-43-226 ;# #8A2BE2
dict set WEB_colour_map_purple darkorchid 153-50-204 ;# #9932CC
dict set WEB_colour_map_purple fuchsia 255-0-255 ;# #FF00FF
dict set WEB_colour_map_purple magenta 255-0-255 ;# #FF00FF - same as fuchsia
dict set WEB_colour_map_purple slateblue 106-90-205 ;# #6A5ACD
dict set WEB_colour_map_purple mediumslateblue 123-104-238 ;# #7B68EE
dict set WEB_colour_map_purple mediumorchid 186-85-211 ;# #BA5503
dict set WEB_colour_map_purple mediumpurple 147-112-219 ;# #9370DB
dict set WEB_colour_map_purple orchid 218-112-214 ;# #DA70D6
dict set WEB_colour_map_purple violet 238-130-238 ;# #EE82EE
dict set WEB_colour_map_purple plum 221-160-221 ;# #DDA0DD
dict set WEB_colour_map_purple thistle 216-191-216 ;# #D88FD8
dict set WEB_colour_map_purple lavender 230-230-150 ;# #E6E6FA
# -- --- ---
#Blue colours
dict set WEB_colour_map midnightblue 25-25-112 ;# #191970
#navy as above
dict set WEB_colour_map darkblue 0-0-139 ;# #00008B
dict set WEB_colour_map mediumblue 0-0-205 ;# #0000CD
#blue as above
dict set WEB_colour_map royalblue 65-105-225 ;# #4169E1
dict set WEB_colour_map steelblue 70-130-180 ;# #4682B4
dict set WEB_colour_map dodgerblue 30-144-255 ;# #1E90FF
dict set WEB_colour_map deepskyblue 0-191-255 ;# #00BFFF
dict set WEB_colour_map cornflowerblue 100-149-237 ;# #6495ED
dict set WEB_colour_map skyblue 135-206-235 ;# #87CEEB
dict set WEB_colour_map lightskyblue 135-206-250 ;# #87CEFA
dict set WEB_colour_map lightsteelblue 176-196-222 ;# #B0C4DE
dict set WEB_colour_map lightblue 173-216-230 ;# #ADD8E6
dict set WEB_colour_map powderblue 176-224-230 ;# #B0E0E6
variable WEB_colour_map_blue
dict set WEB_colour_map_blue midnightblue 25-25-112 ;# #191970
dict set WEB_colour_map_blue navy 0-0-128 ;# #000080
dict set WEB_colour_map_blue darkblue 0-0-139 ;# #00008B
dict set WEB_colour_map_blue mediumblue 0-0-205 ;# #0000CD
dict set WEB_colour_map_blue blue 0-0-255 ;# #0000FF
dict set WEB_colour_map_blue royalblue 65-105-225 ;# #4169E1
dict set WEB_colour_map_blue steelblue 70-130-180 ;# #4682B4
dict set WEB_colour_map_blue dodgerblue 30-144-255 ;# #1E90FF
dict set WEB_colour_map_blue deepskyblue 0-191-255 ;# #00BFFF
dict set WEB_colour_map_blue cornflowerblue 100-149-237 ;# #6495ED
dict set WEB_colour_map_blue skyblue 135-206-235 ;# #87CEEB
dict set WEB_colour_map_blue lightskyblue 135-206-250 ;# #87CEFA
dict set WEB_colour_map_blue lightsteelblue 176-196-222 ;# #B0C4DE
dict set WEB_colour_map_blue lightblue 173-216-230 ;# #ADD8E6
dict set WEB_colour_map_blue powderblue 176-224-230 ;# #B0E0E6
# -- --- ---
#Cyan colours
#teal as above
dict set WEB_colour_map darkcyan 0-139-139 ;# #008B8B
dict set WEB_colour_map lightseagreen 32-178-170 ;# #20B2AA
dict set WEB_colour_map cadetblue 95-158-160 ;# #5F9EA0
dict set WEB_colour_map darkturquoise 0-206-209 ;# #00CED1
dict set WEB_colour_map mediumturquoise 72-209-204 ;# #48D1CC
dict set WEB_colour_map turquoise 64-224-208 ;# #40E0D0
#aqua as above
dict set WEB_colour_map cyan 0-255-255 ;# #00FFFF - same as aqua
dict set WEB_colour_map aquamarine 127-255-212 ;# #7FFFD4
dict set WEB_colour_map paleturquoise 175-238-238 ;# #AFEEEE
dict set WEB_colour_map lightcyan 224-255-255 ;# #E0FFFF
variable WEB_colour_map_cyan
dict set WEB_colour_map_cyan darkcyan 0-139-139 ;# #008B8B
dict set WEB_colour_map_cyan lightseagreen 32-178-170 ;# #20B2AA
dict set WEB_colour_map_cyan cadetblue 95-158-160 ;# #5F9EA0
dict set WEB_colour_map_cyan darkturquoise 0-206-209 ;# #00CED1
dict set WEB_colour_map_cyan mediumturquoise 72-209-204 ;# #48D1CC
dict set WEB_colour_map_cyan turquoise 64-224-208 ;# #40E0D0
dict set WEB_colour_map_cyan aqua 0-255-255 ;# #00FFFF
dict set WEB_colour_map_cyan cyan 0-255-255 ;# #00FFFF - same as aqua
dict set WEB_colour_map_cyan aquamarine 127-255-212 ;# #7FFFD4
dict set WEB_colour_map_cyan paleturquoise 175-238-238 ;# #AFEEEE
dict set WEB_colour_map_cyan lightcyan 224-255-255 ;# #E0FFFF
# -- --- ---
#Green colours
dict set WEB_colour_map darkgreen 0-100-0 ;# #006400
#green as above
dict set WEB_colour_map darkolivegreen 85-107-47 ;# #55682F
dict set WEB_colour_map forestgreen 34-139-34 ;# #228B22
dict set WEB_colour_map seagrean 46-139-87 ;# #2E8B57
#olive as above
dict set WEB_colour_map olivedrab 107-142-35 ;# #6B8E23
dict set WEB_colour_map mediumseagreen 60-179-113 ;# #3CB371
dict set WEB_colour_map limegreen 50-205-50 ;# #32CD32
#lime as above
dict set WEB_colour_map springgreen 0-255-127 ;# #00FF7F
dict set WEB_colour_map mediumspringgreen 0-250-154 ;# #00FA9A
dict set WEB_colour_map darkseagreen 143-188-143 ;# #8FBC8F
dict set WEB_colour_map mediumaquamarine 102-205-170 ;# #66CDAA
dict set WEB_colour_map yellowgreen 154-205-50 ;# #9ACD32
dict set WEB_colour_map lawngreen 124-252-0 ;# #7CFC00
dict set WEB_colour_map chartreuse 127-255-0 ;# #7FFF00
dict set WEB_colour_map lightgreen 144-238-144 ;# #90EE90
dict set WEB_colour_map greenyellow 173-255-47 ;# #ADFF2F
dict set WEB_colour_map palegreen 152-251-152 ;# #98FB98
variable WEB_colour_map_green
dict set WEB_colour_map_green darkgreen 0-100-0 ;# #006400
dict set WEB_colour_map_green green 0-128-0 ;# #008000
dict set WEB_colour_map_green darkolivegreen 85-107-47 ;# #55682F
dict set WEB_colour_map_green forestgreen 34-139-34 ;# #228B22
dict set WEB_colour_map_green seagreen 46-139-87 ;# #2E8B57
dict set WEB_colour_map_green olive 128-128-0 ;# #808000
dict set WEB_colour_map_green olivedrab 107-142-35 ;# #6B8E23
dict set WEB_colour_map_green mediumseagreen 60-179-113 ;# #3CB371
dict set WEB_colour_map_green limegreen 50-205-50 ;# #32CD32
dict set WEB_colour_map_green lime 0-255-0 ;# #00FF00
dict set WEB_colour_map_green springgreen 0-255-127 ;# #00FF7F
dict set WEB_colour_map_green mediumspringgreen 0-250-154 ;# #00FA9A
dict set WEB_colour_map_green darkseagreen 143-188-143 ;# #8FBC8F
dict set WEB_colour_map_green mediumaquamarine 102-205-170 ;# #66CDAA
dict set WEB_colour_map_green yellowgreen 154-205-50 ;# #9ACD32
dict set WEB_colour_map_green lawngreen 124-252-0 ;# #7CFC00
dict set WEB_colour_map_green chartreuse 127-255-0 ;# #7FFF00
dict set WEB_colour_map_green lightgreen 144-238-144 ;# #90EE90
dict set WEB_colour_map_green greenyellow 173-255-47 ;# #ADFF2F
dict set WEB_colour_map_green palegreen 152-251-152 ;# #98FB98
# -- --- ---
#White colours
dict set WEB_colour_map mistyrose 255-228-225 ;# #FFE4E1
dict set WEB_colour_map antiquewhite 250-235-215 ;# #FAEBD7
dict set WEB_colour_map linen 250-240-230 ;# #FAF0E6
dict set WEB_colour_map beige 245-245-220 ;# #F5F5DC
dict set WEB_colour_map whitesmoke 245-245-245 ;# #F5F5F5
dict set WEB_colour_map lavenderblush 255-240-245 ;# #FFF0F5
dict set WEB_colour_map oldlace 253-245-230 ;# #FDF5E6
dict set WEB_colour_map aliceblue 240-248-255 ;# #F0F8FF
dict set WEB_colour_map seashell 255-245-238 ;# #FFF5EE
dict set WEB_colour_map ghostwhite 248-248-255 ;# #F8F8FF
dict set WEB_colour_map honeydew 240-255-240 ;# #F0FFF0
dict set WEB_colour_map floralwhite 255-250-240 ;# #FFFAF0
dict set WEB_colour_map azure 240-255-255 ;# #F0FFFF
dict set WEB_colour_map mintcream 245-255-250 ;# #F5FFFA
dict set WEB_colour_map snow 255-250-250 ;# #FFFAFA
dict set WEB_colour_map ivory 255-255-240 ;# #FFFFF0
#white as above
variable WEB_colour_map_white
dict set WEB_colour_map_white mistyrose 255-228-225 ;# #FFE4E1
dict set WEB_colour_map_white antiquewhite 250-235-215 ;# #FAEBD7
dict set WEB_colour_map_white linen 250-240-230 ;# #FAF0E6
dict set WEB_colour_map_white beige 245-245-220 ;# #F5F5DC
dict set WEB_colour_map_white whitesmoke 245-245-245 ;# #F5F5F5
dict set WEB_colour_map_white lavenderblush 255-240-245 ;# #FFF0F5
dict set WEB_colour_map_white oldlace 253-245-230 ;# #FDF5E6
dict set WEB_colour_map_white aliceblue 240-248-255 ;# #F0F8FF
dict set WEB_colour_map_white seashell 255-245-238 ;# #FFF5EE
dict set WEB_colour_map_white ghostwhite 248-248-255 ;# #F8F8FF
dict set WEB_colour_map_white honeydew 240-255-240 ;# #F0FFF0
dict set WEB_colour_map_white floralwhite 255-250-240 ;# #FFFAF0
dict set WEB_colour_map_white azure 240-255-255 ;# #F0FFFF
dict set WEB_colour_map_white mintcream 245-255-250 ;# #F5FFFA
dict set WEB_colour_map_white snow 255-250-250 ;# #FFFAFA
dict set WEB_colour_map_white ivory 255-255-240 ;# #FFFFF0
dict set WEB_colour_map_white white 255-255-255 ;# #FFFFFF
# -- --- ---
#Gray and black colours
#black as above
dict set WEB_colour_map darkslategray 47-79-79 ;# #2F4F4F
dict set WEB_colour_map dimgray 105-105-105 ;# #696969
dict set WEB_colour_map slategray 112-128-144 ;# #708090
#gray as above
dict set WEB_colour_map lightslategray 119-136-153 ;# #778899
dict set WEB_colour_map darkgray 169-169-169 ;# #A9A9A9
dict set WEB_colour_map silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map lightgray 211-211-211 ;# #D3D3D3
dict set WEB_colour_map gainsboro 220-220-220 ;# #DCDCDC
variable WEB_colour_map_gray
dict set WEB_colour_map_gray black 0-0-0 ;# #000000
dict set WEB_colour_map_gray darkslategray 47-79-79 ;# #2F4F4F
dict set WEB_colour_map_gray dimgray 105-105-105 ;# #696969
dict set WEB_colour_map_gray slategray 112-128-144 ;# #708090
dict set WEB_colour_map_gray gray 128-128-128 ;# #808080
dict set WEB_colour_map_gray lightslategray 119-136-153 ;# #778899
dict set WEB_colour_map_gray darkgray 169-169-169 ;# #A9A9A9
dict set WEB_colour_map_gray silver 192-192-192 ;# #C0C0C0
dict set WEB_colour_map_gray lightgray 211-211-211 ;# #D3D3D3
dict set WEB_colour_map_gray gainsboro 220-220-220 ;# #DCDCDC
set WEB_colour_map [dict merge\
$WEB_colour_map_basic\
$WEB_colour_map_pink\
$WEB_colour_map_red\
$WEB_colour_map_orange\
$WEB_colour_map_yellow\
$WEB_colour_map_brown\
$WEB_colour_map_purple\
$WEB_colour_map_blue\
$WEB_colour_map_cyan\
$WEB_colour_map_green\
$WEB_colour_map_white\
$WEB_colour_map_gray\
]
#we should be able to use WEB_colour_map as a base and override only the conflicts for X11 colours ? Review - check if this is true
variable X11_colour_map
@ -1260,16 +1288,20 @@ namespace eval punk::ansi {
]
variable TERM_colour_map
set TERM_colour_map [dict create]
variable TERM_colour_map_reverse
set TERM_colour_map_reverse [dict create]
set cidx 0
foreach cname $xterm_names {
if {![dict exists $TERM_colour_map $cname]} {
dict set TERM_colour_map $cname $cidx
dict set TERM_colour_map_reverse $cidx $cname
} else {
set did_rename 0
#start suffixes at '-b'. The base name could be considered the '-a' version - but we don't create it.
foreach {suffix} {b c} {
if {![dict exists $TERM_colour_map $cname-$suffix]} {
dict set TERM_colour_map $cname-$suffix $cidx
dict set TERM_colour_map_reverse $cidx $cname-$suffix
set did_rename 1
break
}
@ -1284,7 +1316,7 @@ namespace eval punk::ansi {
#colour_hex2dec
#colour_hex2ansidec
#conversion of hex to format directly pluggable to ansi rgb format (colon separated e.g for foreground we need "38;2;$r;$g;$b" so we return $r;$g;$b)
#we want to support arbitrary rgb values specified in hex - so a table of 16M+ is probably not a great idea
#hex zero-padded - canonically upper case but mixed or lower accepted
@ -1293,10 +1325,23 @@ namespace eval punk::ansi {
# set webhex [::join [format %02X%02X%02X {*}$dectriple] ;# e.g 808080, FFFFFF, 000000
# dict set HEX_colour_map $webhex [join $dectriple {;}]
#}
proc colour_hex2dec {hex6} {
proc colour_hex2ansidec {hex6} {
return [join [::scan $hex6 %2X%2X%2X] {;}]
}
#convert between hex and decimal as used in the a+ function
# eg dec-dec-dec <-> #HHHHHH
#allow hex to be specified with or without leading #
proc colour_hex2dec {hex6} {
set hex6 [string map [list # ""] $hex6]
return [join [::scan $hex6 %2X%2X%2X] {-}]
}
proc colour_dec2hex {decimalcolourstring} {
set dec [string map [list {;} - , -] $decimalcolourstring]
set declist [split $dec -]
set hex #[format %02X%02X%02X {*}$declist]
}
proc get_sgr_map {} {
variable SGR_map
return $SGR_map
@ -1318,7 +1363,12 @@ namespace eval punk::ansi {
set bg [textblock::block 39 3 "[a+ $bgname] [a]"]
set colourmap ""
for {set i 8} {$i <= 15} {incr i} {
append colourmap "_[a+ black normal 48\;5\;$i] $i [a]" ;#black normal is blacker than black bold - which often displays as a grey
if {$i == 8} {
set fg "bold white"
} else {
set fg "black normal" ;#black normal is often blacker than black bold - which can display as a grey
}
append colourmap "_[a+ {*}$fg 48\;5\;$i] $i [a]"
}
set map2 [overtype::left -transparent _ $bg "\n$colourmap"]
return $map2
@ -1326,7 +1376,7 @@ namespace eval punk::ansi {
proc colourtable_216 {} {
package require textblock
set clist [list]
set fg black
set fg "black"
for {set i 16} {$i <=231} {incr i} {
if {$i % 18 == 16} {
if {$fg eq "black"} {
@ -1344,15 +1394,29 @@ namespace eval punk::ansi {
return $t
}
#1st 16 colours of 256 - match SGR colours
proc colourblock_16 {} {
set out ""
set fg "bold white"
for {set i 0} {$i <= 15} {incr i} {
#8 is black - so start black fg at 9
if {$i > 8} {
set fg "web-black"
}
append out "[a+ {*}$fg Term$i][format %3s $i] "
}
return $out[a]
}
#216 colours of 256
proc colourblock_216 {} {
set out ""
set fg black
set fg "web-black"
for {set i 16} {$i <=231} {incr i} {
if {$i % 18 == 16} {
if {$fg eq "black"} {
set fg "bold white"
if {$fg eq "web-black"} {
set fg "web-white"
} else {
set fg "black"
set fg "web-black"
}
set br "\n"
} else {
@ -1360,7 +1424,127 @@ namespace eval punk::ansi {
}
append out "$br[a+ {*}$fg Term$i][format %3s $i] "
}
return $out
append out [a]
return [string trimleft $out \n]
}
proc colourtable_216_names {} {
set out ""
#use the reverse lookup dict - the original xterm_names list has duplicates - we want the disambiguated (potentially suffixed) names
variable TERM_colour_map_reverse
set rows [list]
set row [list]
set fg "web-black"
set t [textblock::class::table new]
$t configure -show_seps 0 -show_edge 0
for {set i 16} {$i <=231} {incr i} {
if {$i % 9 == 7} {
if {$fg eq "web-black"} {
set fg "web-white"
} else {
set fg "web-black"
}
if {[llength $row]} {
lappend row "[a+ {*}$fg Term$i][format %3s $i] [dict get $TERM_colour_map_reverse $i]"
lappend rows $row
set row [list]
}
} else {
lappend row "[a+ {*}$fg Term$i][format %3s $i] [dict get $TERM_colour_map_reverse $i]"
}
#append out "$br[a+ {*}$fg Term$i][format %3s $i] "
}
foreach r $rows {
$t add_row $r
}
append out [$t print]
$t destroy
append out [a]
return [string trimleft $out \n]
}
#24 greys of 256
proc colourblock_24 {} {
set out ""
set fg "bold white"
for {set i 232} {$i <= 255} {incr i} {
if {$i > 243} {
set fg "web-black"
}
append out "[a+ {*}$fg Term$i][format %3s $i] "
}
return $out[a]
}
#set WEB_colour_map [dict merge\
# $WEB_colour_map_basic\
# $WEB_colour_map_pink\
# $WEB_colour_map_red\
# $WEB_colour_map_orange\
# $WEB_colour_map_yellow\
# $WEB_colour_map_brown\
# $WEB_colour_map_purple\
# $WEB_colour_map_blue\
# $WEB_colour_map_cyan\
# $WEB_colour_map_green\
# $WEB_colour_map_white\
# $WEB_colour_map_gray\
#]
proc colourtable_web {{groups *}} {
set all_groupnames [list basic pink red orange yellow brown purple blue cyan green white gray]
switch -- $groups {
"" - * {
set show_groups $all_groupnames
}
? {
return "Web group names: $all_groupnames"
}
default {
foreach g $groups {
if {$g ni $all_groupnames} {
error "colourtable_web group name '$g' not known. Known colour groups: $all_groupnames"
}
}
set show_groups $groups
}
}
set grouptables [list]
set white_fg_list [list\
mediumvioletred deeppink\
darkred red firebrick crimson indianred\
orangered\
maroon brown saddlebrown sienna\
indigo purple darkmagenta darkviolet darkslateblue blueviolet darkorchid fuchsia magenta slateblue mediumslateblue\
midnightblue navy darkblue mediumblue blue royalblue steelblue dodgerblue\
teal darkcyan\
darkgreen green darkolivegreen forestgreen seagreen olive olivedrab\
black darkslategray dimgray slategray\
]
foreach g $show_groups {
#upvar WEB_colour_map_$g map_$g
variable WEB_colour_map_$g
set t [textblock::class::table new]
$t configure -show_edge 0 -show_seps 0 -show_header 1
dict for {cname cdec} [set WEB_colour_map_$g] {
$t add_row [list "$cname " "[colour_dec2hex $cdec] " $cdec]
if {$cname in $white_fg_list} {
set fg "web-white"
} else {
set fg "web-black"
}
$t configure_row [expr {[$t row_count]-1}] -ansibase [a+ Rgb-$cdec $fg]
}
$t configure_column 0 -headers [list "[string totitle $g] colours"]
$t configure_column 0 -header_colspans [list all]
$t configure -ansibase_header [a+ Web-white web-black]
lappend grouptables [$t print]
$t destroy
}
#set displaytable [textblock::class::table new]
set displaytable [textblock::list_as_table 3 $grouptables -return object]
$displaytable configure -show_header 0 -show_vseps 0
#return $displaytable
set result [$displaytable print]
$displaytable destroy
return $result
}
proc a? {args} {
#*** !doctools
@ -1371,20 +1555,60 @@ namespace eval punk::ansi {
if {![llength $args]} {
set out ""
append out $SGR_setting_map \n
append out $SGR_colour_map \n
set indent " "
set RST [a]
append out "[a+ web-white]Standard SGR colours and attributes [a]" \n
set settings_applied $SGR_setting_map
set strmap [list]
dict for {k v} $SGR_setting_map {
switch -- $k {
bold - dim - italic - doubleunderline - blink - fastblink - strike - overline - framecircle {
lappend strmap " $k " " [a+ $k]$k$RST "
}
underline - reverse - frame {
#1st coloumn - no leading space
lappend strmap "$k " "[a+ $k]$k$RST "
}
noreverse {
#undo mapping of 'reverse' within this string
lappend strmap "$k" "noreverse"
}
}
}
set settings_applied [string trim $SGR_setting_map \n]
try {
package require overtype ;# circular dependency - many components require overtype. Here we only need it for nice layout in the a? query proc - so we'll do a soft-dependency by only loading when needed and also wrapping in a try
package require textblock
append out [textblock::join $indent [string map $strmap $settings_applied]] \n
append out [textblock::join $indent [string trim $SGR_colour_map \n]] \n
append out [textblock::join $indent "Example: \[a+ bold red White underline\]text\[a] -> [a+ bold red White underline]text[a]"] \n \n
set bgname "White"
set map1 [colourmap1 $bgname]
set map1 [overtype::centre -transparent 1 $map1 "[a black $bgname]Standard colours[a]"]
set map2 [colourmap2 $bgname]
set map2 [overtype::centre -transparent 1 $map2 "[a black $bgname]High-intensity colours[a]"]
append out [textblock::join $map1 " " $map2] \n
#append out $map1[a] \n
#append out $map2[a] \n
append out [colourblock_216]
append out [textblock::join $indent [textblock::join $map1 $map2]] \n
append out "[a+ web-white]216 colours of 256 terminal colours (To see names, use: a? term)[a]" \n
append out [textblock::join $indent [colourblock_216]] \n
append out "[a+ web-white]24 Greyscale colours[a]" \n
append out [textblock::join $indent [colourblock_24]] \n
append out \n
append out [textblock::join $indent "Example: \[a+ Term-92 term-49\]text\[a] -> [a+ Term-92 term-49]text[a]"] \n
append out [textblock::join $indent "Example: \[a+ Term-lightsteelblue term-gold1\]text\[a] -> [a+ Term-lightsteelblue term-gold1]text[a]"] \n
append out [textblock::join $indent "Example: \[a+ term-lightsteelblue Term-gold1\]text\[a] -> [a+ term-lightsteelblue Term-gold1]text[a]"] \n
append out \n
append out "[a+ web-white]16 Million colours[a]" \n
#dict set WEB_colour_map mediumvioletred 199-21-133 ;# #C71585
append out [textblock::join $indent "Example: \[a+ rgb-199-21-133\]text\[a] -> [a+ rgb-199-21-133]text[a]"] \n
append out [textblock::join $indent "Example: \[a+ Rgb#C71585\]text\[a] -> [a+ Rgb#C71585]text[a]"] \n
append out \n
append out "[a+ web-white]Web colours[a]" \n
append out [textblock::join $indent "To see all names use: a? web"] \n
append out [textblock::join $indent "To see specific colour groups use: a? web groupname1 groupname2..."] \n
append out [textblock::join $indent "Valid group names (can be listed in any order): basic pink red orange yellow brown purple blue cyan green white grey"] \n
append out \n
append out [textblock::join $indent "Example: \[a+ Web-springgreen web-crimson\]text\[a] -> [a+ Web-springgreen web-coral]text[a]"] \n
} on error {result options} {
@ -1394,6 +1618,17 @@ namespace eval punk::ansi {
return $out
}
} else {
switch -- [lindex $args 0] {
term {
return [colourtable_216_names]
}
web {
return [colourtable_web [lrange $args 1 end]]
}
x11 {
return "Display not implemented. Mostly same as web"
}
}
set result [list]
set map [dict merge $SGR_setting_map $SGR_colour_map]
set rmap [lreverse $map]

20
src/modules/punk/char-999999.0a1.0.tm

@ -1852,15 +1852,27 @@ namespace eval punk::char {
#intended for single grapheme - but will work for multiple
#cannot contain ansi or newlines
#(a cache of ansifreestring_width calls - as these are quite regex heavy)
proc grapheme_width_cached {ch} {
#review - effective memory leak on longrunning programs if never cleared
#tradeoff in fragmenting cache and reducing efficiency vs ability to clear in a scoped manner
proc grapheme_width_cached {ch {key ""}} {
variable grapheme_widths
if {[dict exists $grapheme_widths $ch]} {
return [dict get $grapheme_widths $ch]
#if key eq "*" - we won't be able to clear that cache individually. Perhaps that's ok
if {[dict exists $grapheme_widths $key $ch]} {
return [dict get $grapheme_widths $key $ch]
}
set width [punk::char::ansifreestring_width $ch] ;#review - can we provide faster version if we know it's a single grapheme rather than a string? (grapheme is still a string as it may have combiners/diacritics)
dict set grapheme_widths $ch $width
dict set grapheme_widths $key $ch $width
return $width
}
proc grapheme_width_cache_clear {key} {
variable grapheme_widths
if {$key eq "*} {
set grapheme_widths [dict create]
} else {
dict unset grapheme_widths $key
}
return
}
#no char_width - use grapheme_width terminology to be clearer
proc grapheme_width {char} {
error "grapheme_width unimplemented - use ansifreestring_width"

141
src/modules/punk/lib-999999.0a1.0.tm

@ -179,6 +179,54 @@ namespace eval punk::lib::compat {
}
#slight isolation - varnames don't leak - but calling context vars can be affected
proc lmaptcl2 {varnames list script} {
set result [list]
set values [list]
foreach v $varnames {
lappend values "\$$v"
}
set linkvars [uplevel 1 [list info vars]]
set nscaller [uplevel 1 [list namespace current]]
set apply_script ""
foreach vname $linkvars {
append apply_script [string map [list %vname% $vname]\
{upvar 2 %vname% %vname%}\
] \n
}
append apply_script $script \n
#puts "--> $apply_script"
foreach $varnames $list {
lappend result [apply\
[list\
$varnames\
$apply_script\
$nscaller\
] {*}[subst $values]\
]
}
return $result
}
if {"::lmap" ne [info commands ::lmap]} {
#puts stderr "Warning - no built-in lpop"
interp alias {} lpop {} ::punk::lib::compat::lmaptcl
}
#lmap came in Tcl 8.6 - so probably not much need for a tcl forward compatibility version - but here it is anyway
proc lmaptcl {varnames list script} {
set result [list]
set varlist [list]
foreach varname $varnames {
upvar 1 $varname var_$varname ;#ensure no collisions with vars in this proc
lappend varlist var_$varname
}
foreach $varlist $list {
lappend result [uplevel 1 $script]
}
return $result
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::lib::compat ---}]
@ -196,6 +244,99 @@ namespace eval punk::lib {
#[para] Core API functions for punk::lib
#[list_begin definitions]
#The closure-like behaviour is *very* slow especially when called from a context such as the global namespace with lots of vars and large arrays such as ::env
proc lmapflat_closure {varnames list script} {
set result [list]
set values [list]
foreach v $varnames {
lappend values "\$$v"
}
# -- --- ---
#capture - use uplevel 1 or namespace eval depending on context
set capture [uplevel 1 {
apply { varnames {
set capturevars [dict create]
set capturearrs [dict create]
foreach fullv $varnames {
set v [namespace tail $fullv]
upvar 1 $v var
if {[info exists var]} {
if {(![array exists var])} {
dict set capturevars $v $var
} else {
dict set capturearrs capturedarray_$v [array get var]
}
} else {
#A variable can show in the results for 'info vars' but still not 'exist'. e.g a 'variable x' declaration in the namespace where the variable has never been set
}
}
return [dict create vars $capturevars arrs $capturearrs]
} } [info vars]
} ]
# -- --- ---
set cvars [dict get $capture vars]
set carrs [dict get $capture arrs]
set apply_script ""
foreach arrayalias [dict keys $carrs] {
set realname [string range $arrayalias [string first _ $arrayalias]+1 end]
append apply_script [string map [list %realname% $realname %arrayalias% $arrayalias] {
array set %realname% [set %arrayalias%][unset %arrayalias%]
}]
}
append apply_script [string map [list %script% $script] {
#foreach arrayalias [info vars capturedarray_*] {
# set realname [string range $arrayalias [string first _ $arrayalias]+1 end]
# array set $realname [set $arrayalias][unset arrayalias]
#}
#return [eval %script%]
%script%
}]
#puts "--> $apply_script"
foreach $varnames $list {
lappend result {*}[apply\
[list\
[concat $varnames [dict keys $cvars] [dict keys $carrs] ]\
$apply_script\
] {*}[subst $values] {*}[dict values $cvars] {*}[dict values $carrs] ]
}
return $result
}
#link version - can write to vars in calling context - but keeps varnames themselves isolated
#performance much better than capture version - but still a big price to pay for the isolation
proc lmapflat_link {varnames list script} {
set result [list]
set values [list]
foreach v $varnames {
lappend values "\$$v"
}
set linkvars [uplevel 1 [list info vars]]
set nscaller [uplevel 1 [list namespace current]]
set apply_script ""
foreach vname $linkvars {
append apply_script [string map [list %vname% $vname]\
{upvar 2 %vname% %vname%}\
] \n
}
append apply_script $script \n
#puts "--> $apply_script"
foreach $varnames $list {
lappend result {*}[apply\
[list\
$varnames\
$apply_script\
$nscaller\
] {*}[subst $values]\
]
}
return $result
}
proc lmapflat {varnames list script} {
concat {*}[uplevel 1 [list lmap $varnames $list $script]]
}
proc dict_getdef {dictValue args} {
if {[llength $args] < 1} {

2
src/modules/punk/ns-999999.0a1.0.tm

@ -1580,7 +1580,7 @@ namespace eval punk::ns {
#review - upvar in apply within ns eval vs direct access of ${ns}::varname
set capture [namespace eval $ns {
apply { varnames {
while {"prev_args_[incr n]" in $varnames} {}
while {"prev_args[incr n]" in $varnames} {}
set capturevars [dict create]
set capturearrs [dict create]
foreach fullv $varnames {

219
src/modules/textblock-999999.0a1.0.tm

@ -1294,7 +1294,7 @@ namespace eval textblock {
tlc [dict get $fdef_header hlt]\
blc [dict get $fdef_header hlb]\
]
set framedef_leftbox [textblock::framedef $ftype_header left]
set framedef_leftbox [textblock::framedef $ftype_header -joins left]
set column_width_cache [dict create]
@ -1347,7 +1347,7 @@ namespace eval textblock {
set next_spanlist [dict get $all_colspans [expr {$h+1}]]
set spanbelow [lindex $next_spanlist $cidx]
if {$spanbelow == 0} {
#we don't want a down-join for blc - retrieve a framedef with only left joins
#we don't want a down-join for blc - use a framedef with only left joins
dict set startmap blc [dict get $framedef_leftbox blc]
}
} else {
@ -1355,8 +1355,8 @@ namespace eval textblock {
}
}
#todo - multiline header cells + multiple header lines (will be more useful when colspans implemented)
set header_cell_startspan [textblock::frame -width [expr {$colwidth+2}] -type [dict get $ftypes header]\
#review - contentwidth of hval can be greater than $colwidth+2 - if so frame function will detect and frame_cache will not be used
set header_cell_startspan [textblock::frame -usecache 1 -width [expr {$colwidth+2}] -type [dict get $ftypes header]\
-ansibase $ansibase_header -ansiborder $ansiborder_final\
-boxlimits $hlims -boxmap $startmap -joins $header_joins $hval\
]
@ -1407,12 +1407,12 @@ namespace eval textblock {
if {[llength $next_spanlist]} {
set spanbelow [lindex $next_spanlist $spancol]
if {$spanbelow != 0} {
set downbox [textblock::framedef $ftype_header {down}]
set downbox [textblock::framedef $ftype_header -joins {down}]
dict set this_span_map blc [dict get $downbox hlbj] ;#horizontal line bottom with down join - to same frametype
}
} else {
#join to body
set downbox [textblock::framedef $ftype_header [list down-$fname_body]]
set downbox [textblock::framedef $ftype_header -joins [list down-$fname_body]]
dict set this_span_map blc [dict get $downbox hlbj] ;#horizontal line bottom with down join - from header frametype to body frametype
}
}
@ -1478,6 +1478,7 @@ namespace eval textblock {
}
set spacemap [list hl " " vl " " tlc " " blc " " trc " " brc " "]
#set spacemap [list hl "\uFFFF" vl "\uFFFF" tlc "\uFFFF" blc "\uFFFF" trc "\uFFFF " brc "\uFFFF"] ;# a debug test
#-usecache 1 ok
set hblock [textblock::frame -type $spacemap -boxlimits $hlims -ansibase $ansibase_header $hval]
set spanned_frame [overtype::left -experimental test_mode -transparent 1 $spanned_frame $hblock]
}
@ -1522,6 +1523,7 @@ namespace eval textblock {
set h_lines [lrepeat $rowh $bline]
set hcell_blank [::join $h_lines \n]
set spacemap [list hl "\uFFFF" vll "\uFFFF" vlr "\uFFFF" tlc "\uFFFF" blc "\uFFFF" trc "\uFFFF " brc "\uFFFF"] ;# a debug test
# -usecache 1 ok
set header_frame [textblock::frame -width [expr {$padwidth+2}] -type [dict get $ftypes header]\
-ansibase $ansibase_header \
-boxlimits $hlims -boxmap $spacemap $hcell_blank\
@ -2745,7 +2747,40 @@ namespace eval textblock {
if {$width eq "auto"} {
set width $datawidth
}
set lines [list]
if {$block eq ""} {
#we need to treat as a line
return [string repeat $padchar $width]
}
#review - tcl format can only pad with zeros or spaces?
#experimental fallback to supposedly faster simpler 'format' but we still need to compensate for double-width or non-printing chars
if 0 {
#review - surprisingly, this doesn't seem to be a performance win
#No detectable diff on small blocks - slightly worse on large blocks
if {($padchar eq " " || $padchar eq "0") && ![punk::ansi::ta::detect $block]} {
#This will still be wrong for example with diacritics on terminals that don't collapse the space following a diacritic, and don't correctly report cursor position
#(i.e as at 2024 - lots of them) wezterm on windows at least does the right thing.
set block [string map [list \r\n \n] $block]
if {$which eq "l"} {
set fmt "%+${padchar}*s"
} else {
set fmt "%-${padchar}*s"
}
foreach ln [split $block \n] {
#set lnwidth [punk::char::ansifreestring_width $ln]
set lnwidth [punk::char::grapheme_width_cached $ln]
set lnlen [string length $ln]
set diff [expr $lnwidth - $lnlen]
set trickwidth [expr {$width - $diff}] ;#may 'subtract' a positive or negative int (ie will add to trickwidth if negative)
lappend lines [format $fmt $trickwidth $ln]
}
return [::join $lines \n]
}
}
set lnum 0
set parts [punk::ansi::ta::split_codes $block]
set line_chunks [list]
@ -2763,7 +2798,8 @@ namespace eval textblock {
set p 0
foreach pl $partlines {
lappend line_chunks $pl
incr line_len [punk::char::ansifreestring_width $pl]
#incr line_len [punk::char::ansifreestring_width $pl]
incr line_len [punk::char::grapheme_width_cached $pl] ;#memleak
if {$p != $last} {
#do padding
set missing [expr {$width - $line_len}]
@ -3032,7 +3068,8 @@ namespace eval textblock {
set row ""
foreach colidx $colindices {
#we know we have a single line, no ansi in underlay and no overflow required - so we can use renderline directly
append row [overtype::renderline -width $w($colidx) -insert_mode 0 -info 0 $c($colidx) $v($colidx)]
#append row [overtype::renderline -width $w($colidx) -insert_mode 0 -info 0 $c($colidx) $v($colidx)]
append row [textblock::pad $v($colidx) -width $w($colidx) -which right -padchar " "]
}
lappend outlines $row
}
@ -3185,11 +3222,33 @@ namespace eval textblock {
return [dict create category predefined type $f]
}
}
proc framedef {f {joins ""}} {
variable framedef_cache [dict create]
proc framedef {f args} {
#unicode box drawing only provides enough characters for seamless joining of unicode boxes light and heavy.
#e.g with characters such as \u2539 Box Drawings Right Light and Left Up Heavy.
#the double glyphs in box drawing can do a limited set of joins to light lines - but not enough for seamless table layouts.
#the arc set can't even join to itself e.g with curved equivalents of T-like shapes
variable framedef_cache
set cache_key [concat $f $args]
if {[dict exists $framedef_cache $cache_key]} {
return [dict get $framedef_cache $cache_key]
}
set defaults [dict create\
-joins ""\
-boxonly 0\
]
dict for {k v} $args {
switch -- $k {
-joins - -boxonly {}
default {
error "framedef unknown option '$k'. Known options [dict keys $args]"
}
}
}
set opts [dict merge $defaults $args]
set joins [dict get $opts -joins]
set boxonly [dict get $opts -boxonly]
#sorted order down left right up
#1 x choose 4
@ -4297,7 +4356,16 @@ namespace eval textblock {
set vlrj $vlr
}
}
return [dict create\
if {$boxonly} {
set result [dict create\
tlc $tlc hlt $hlt trc $trc\
vll $vll vlr $vlr\
blc $blc hlb $hlb brc $brc\
]
dict set framedef_cache $cache_key $result
return $result
} else {
set result [dict create\
tlc $tlc hlt $hlt trc $trc\
vll $vll vlr $vlr\
blc $blc hlb $hlb brc $brc\
@ -4306,7 +4374,31 @@ namespace eval textblock {
vllj $vllj\
vlrj $vlrj\
]
dict set framedef_cache $cache_key $result
return $result
}
}
variable frame_cache
set frame_cache [dict create]
proc frame_cache {{action ""}} {
if {$action ni [list clear ""]} {
error "frame_cache action '$action' not understood. Valid actions: clear"
}
variable frame_cache
set out ""
dict for {k v} $frame_cache {
lassign $v _f frame _used used
append out [textblock::join $k " " $frame " " $used]\n
}
if {$action eq "clear"} {
set frame_cache [dict create]
append out \nCLEARED
}
return $out
}
#options before content argument - which is allowed to be absent
#frame performance (noticeable with complex tables even of modest size) is improved significantly by frame_cache - but is still (2024) a fairly expensive operation.
proc frame {args} {
variable frametypes
set expect_optval 0
@ -4356,11 +4448,14 @@ namespace eval textblock {
-ansibase ""\
-align "left"\
-ellipsis 1\
-usecache 1\
-buildcache 1\
]
#use -buildcache 1 with -usecache 0 for debugging cache issues so we can inspect using textblock::frame_cache
set opts [dict merge $defaults $arglist]
foreach {k v} $opts {
switch -- $k {
-etabs - -type - -boxlimits - -boxmap - -joins - -title - -subtitle - -width - -height - -ansiborder - -ansibase - -align - -ellipsis {}
-etabs - -type - -boxlimits - -boxmap - -joins - -title - -subtitle - -width - -height - -ansiborder - -ansibase - -align - -ellipsis - -usecache - -buildcache {}
default {
error "frame option '$k' not understood. Valid options are [dict keys $defaults]"
}
@ -4372,6 +4467,10 @@ namespace eval textblock {
set opt_boxlimits [dict get $opts -boxlimits]
set opt_joins [dict get $opts -joins]
set opt_boxmap [dict get $opts -boxmap]
set opt_usecache [dict get $opts -usecache]
set opt_buildcache [dict get $opts -buildcache]
set usecache $opt_usecache ;#may need to override
set buildcache $opt_buildcache
set custom_keys [list hl hlt hlb vl vll vlr tlc trc blc brc]
set known_frametypes $frametypes ;# light, heavey etc as defined in textblock::frametypes variable
@ -4481,7 +4580,7 @@ namespace eval textblock {
switch -- $opt_align {
left - right - centre - center {}
default {
error "frame option -align must be left|right|centre|center - received: $$opt_align"
error "frame option -align must be left|right|centre|center - received: $opt_align"
}
}
#these are all valid commands for overtype::<cmd>
@ -4532,19 +4631,84 @@ namespace eval textblock {
if {$contentheight == 0 && $contentwidth == 0} {
set has_contents 0
}
#todo - render it with vertical overflow so we can process ansi moves?
#set linecount [textblock::height $contents]
set linecount $contentheight
# -- --- --- --- --- --- --- --- ---
variable frame_cache
#review - custom frame affects contentwidth - exclude from caching?
#set cache_key [concat $arglist $contentwidth $contentheight]
set hashables [concat $arglist $contentwidth $contentheight]
package require md5
set hash [md5::md5 -hex $hashables]
set cache_key "$hash-$contentwidth-$contentheight-actualcontentwidth:$actual_contentwidth"
set TSUB \u1FFF; #needs to be different to that used in table construction
#this occurs commonly in table building with colspans - review
if {$actual_contentwidth > $contentwidth || $actual_contentheight != $contentheight} {
set usecache 0
#set buildcache 0 ;#comment out for debug/analysis so we can see
set cache_key [a+ Web-red]$cache_key[a]
}
if {$buildcache && $actual_contentwidth < $contentwidth} {
#colourise cache_key to warn
if {$actual_contentwidth == 0} {
#we can still substitue with right length
set cache_key [a+ Web-steelblue web-black]$cache_key[a]
} else {
#actual_contentwidth is shorter - rather than choose an alignment and pad - we will opt out of caching
set usecache 0
set cache_key [a+ Web-orange web-black]$cache_key[a]
}
}
if {$usecache && [dict exists $frame_cache $cache_key]} {
set template [dict get $frame_cache $cache_key frame]
set used [dict get $frame_cache $cache_key used]
dict set frame_cache $cache_key used [expr {$used+1}]
set resultlines [list]
set overwritable [string repeat $TSUB $contentwidth]
set blankset [string repeat " " $contentwidth]
set contentindex 0
set clines [split $contents \n]
if {$actual_contentwidth == 0} {
foreach tline [split $template \n] {
if {[string first $TSUB $tline] >= 0} {
lappend resultlines [string map [list $overwritable $blankset] $tline]
incr contentindex
} else {
lappend resultlines $tline
}
}
} else {
foreach tline [split $template \n] {
if {[string first $TSUB $tline] >= 0} {
#set sublen [string length [lindex [regexp -inline "\[^$TSUB]*($TSUB*).*" $tline] 1]]
#set overwritable [string repeat $TSUB $sublen]
lappend resultlines [string map [list $overwritable [lindex $clines $contentindex]] $tline]
incr contentindex
} else {
lappend resultlines $tline
}
}
}
return [::join $resultlines \n]
}
# -- --- --- --- --- --- --- --- ---
set rst [a]
#set column [string repeat " " $contentwidth] ;#default - may need to override for custom frame
set underlayline [string repeat " " $contentwidth]
set underlay [::join [lrepeat $linecount $underlayline] \n]
set cache_underlayline [string repeat $TSUB $contentwidth]
set cache_underlay [::join [lrepeat $linecount $cache_underlayline] \n]
set vll_width 1 ;#default for all except custom (printing width)
set vlr_width 1
set framedef [textblock::framedef $framedef $opt_joins]
set framedef [textblock::framedef $framedef -joins $opt_joins]
dict with framedef {} ;#extract vll,hlt,tlc etc vars
#puts "---> $opt_boxmap"
@ -4565,6 +4729,7 @@ namespace eval textblock {
switch -- $frameset {
custom {
#if no ansi, these widths are reasonable to maintain in grapheme_width_cached indefinitely
set vll_width [punk::ansi::printing_length $vll]
set hlb_width [punk::ansi::printing_length $hlb]
set hlt_width [punk::ansi::printing_length $hlt]
@ -4592,6 +4757,7 @@ namespace eval textblock {
#set column [string repeat " " $contentwidth]
set underlayline [string repeat " " $contentwidth]
set underlay [::join [lrepeat $linecount $underlayline] \n]
#cache?
if {$hlt_width == 1} {
set tbar [string repeat $hlt $tbarwidth]
@ -4756,6 +4922,7 @@ namespace eval textblock {
set topborder 1
}
set fs ""
set fscached ""
#todo - output nothing except maybe newlines depending on if opt_height 0 and/or opt_width 0?
if {$topborder} {
if {$leftborder && $rightborder} {
@ -4770,27 +4937,42 @@ namespace eval textblock {
}
}
}
append fscached $fs
if {$has_contents || $opt_height > 2} {
#if {$topborder && $fs ne "xx"} {
# append fs \n
#}
if {$topborder} {
append fs \n
append fscached \n
}
#set inner [overtype::$opt_align -ellipsis $opt_ellipsis $opt_ansibase$underlay$rstbase $opt_ansibase$contents$rstbase]
set inner [overtype::$opt_align -ellipsis $opt_ellipsis $opt_ansibase$underlay$rstbase $contents]
#set cache_inner [overtype::$opt_align -ellipsis $opt_ellipsis $opt_ansibase$cache_underlay$rstbase $contents]
#review
set cache_inner $opt_ansibase$cache_underlay$rstbase
if {$leftborder && $rightborder} {
set bodyparts [list $lhs $opt_ansibase$inner$rstbase $rhs]
set cache_bodyparts [list $lhs $opt_ansibase$cache_inner$rstbase $rhs]
} else {
if {$leftborder} {
set bodyparts [list $lhs $opt_ansibase$inner$rstbase]
set cache_bodyparts [list $lhs $opt_ansibase$cache_inner$rstbase]
} elseif {$rightborder} {
set bodyparts [list $opt_ansibase$inner$rstbase $rhs]
set cache_bodyparts [list $opt_ansibase$cache_inner$rstbase $rhs]
} else {
set bodyparts [list $opt_ansibase$inner$rstbase]
set cache_bodyparts [list $opt_ansibase$cache_inner$rstbase]
}
}
set body [textblock::join -- {*}$bodyparts]
if {$buildcache} {
set cache_body [textblock::join -- {*}$cache_bodyparts]
append fscached $cache_body
}
append fs $body
}
@ -4802,21 +4984,28 @@ namespace eval textblock {
if {$bottomborder} {
if {($topborder & $fs ne "xx" ) || ($has_contents || $opt_height > 2)} {
append fs \n
append fscached \n
}
if {$leftborder && $rightborder} {
append fs $blc$bottombar$brc
append fscached $blc$bottombar$brc
} else {
if {$leftborder} {
append fs $blc$bottombar
append fscached $blc$bottombar
} elseif {$rightborder} {
append fs $bottombar$brc
append fscached $bottombar$brc
} else {
append fs $bottombar
append fscached $bottombar
}
}
}
}
if {$buildcache} {
dict set frame_cache $cache_key [list frame $fscached used 0]
}
return $fs
}

Loading…
Cancel
Save