aboutsummaryrefslogtreecommitdiff
path: root/examples/colorful/colorful.tm
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-04-06 16:07:23 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-04-06 16:07:23 -0400
commit6782cc5570e194791ca6cdd695b88897e9145564 (patch)
treea428e9d954aca251212ec1cf15bd35e0badce630 /examples/colorful/colorful.tm
parent448e805293989b06e07878a4a87fdd378f7c6e02 (diff)
No more colons for blocks
Diffstat (limited to 'examples/colorful/colorful.tm')
-rw-r--r--examples/colorful/colorful.tm202
1 files changed, 101 insertions, 101 deletions
diff --git a/examples/colorful/colorful.tm b/examples/colorful/colorful.tm
index 6769841d..d64afe6e 100644
--- a/examples/colorful/colorful.tm
+++ b/examples/colorful/colorful.tm
@@ -9,128 +9,128 @@ CSI := "$\033["
use patterns
-lang Colorful:
- convert(text:Text -> Colorful):
+lang Colorful
+ convert(text:Text -> Colorful)
text = text.translate({"@"="@(at)", "("="@(lparen)", ")"="@(rparen)"})
return Colorful.from_text(text)
- convert(i:Int -> Colorful): return Colorful.from_text("$i")
- convert(n:Num -> Colorful): return Colorful.from_text("$n")
+ convert(i:Int -> Colorful) return Colorful.from_text("$i")
+ convert(n:Num -> Colorful) return Colorful.from_text("$n")
- func for_terminal(c:Colorful -> Text):
+ func for_terminal(c:Colorful -> Text)
return CSI ++ "m" ++ _for_terminal(c, _TermState())
- func print(c:Colorful, newline=yes):
+ func print(c:Colorful, newline=yes)
say(c.for_terminal(), newline=newline)
-func main(texts:[Text], files:[Path]=[], by_line=no):
- for i,text in texts:
+func main(texts:[Text], files:[Path]=[], by_line=no)
+ for i,text in texts
colorful := Colorful.from_text(text)
colorful.print(newline=no)
- if i == texts.length: say("")
- else: say(" ", newline=no)
+ if i == texts.length say("")
+ else say(" ", newline=no)
- if texts.length == 0 and files.length == 0:
+ if texts.length == 0 and files.length == 0
files = [(/dev/stdin)]
- for file in files:
- if by_line:
- for line in file.by_line() or exit("Could not read file: $file"):
+ for file in files
+ if by_line
+ for line in file.by_line() or exit("Could not read file: $file")
colorful := Colorful.from_text(line)
colorful.print()
- else:
+ else
colorful := Colorful.from_text(file.read() or exit("Could not read file: $file"))
colorful.print(newline=no)
-func _for_terminal(c:Colorful, state:_TermState -> Text):
- return c.text.map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch): _add_ansi_sequences(m.captures[1], state))
+func _for_terminal(c:Colorful, state:_TermState -> Text)
+ return c.text.map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch) _add_ansi_sequences(m.captures[1], state))
-enum _Color(Default, Bright(color:Int16), Color8Bit(color:Int16), Color24Bit(color:Int32)):
- func from_text(text:Text -> _Color?):
- if text.matches_pattern($Pat/#{3-6 hex}/):
+enum _Color(Default, Bright(color:Int16), Color8Bit(color:Int16), Color24Bit(color:Int32))
+ func from_text(text:Text -> _Color?)
+ if text.matches_pattern($Pat/#{3-6 hex}/)
hex := text.from(2)
return none unless hex.length == 3 or hex.length == 6
- if hex.length == 3:
+ if hex.length == 3
hex = hex[1]++hex[1]++hex[2]++hex[2]++hex[3]++hex[3]
n := Int32.parse("0x" ++ hex) or return none
return Color24Bit(n)
- else if text.matches_pattern($Pat/{1-3 digit}/):
+ else if text.matches_pattern($Pat/{1-3 digit}/)
n := Int16.parse(text) or return none
- if n >= 0 and n <= 255: return Color8Bit(n)
- else if text == "black": return _Color.Color8Bit(0)
- else if text == "red": return _Color.Color8Bit(1)
- else if text == "green": return _Color.Color8Bit(2)
- else if text == "yellow": return _Color.Color8Bit(3)
- else if text == "blue": return _Color.Color8Bit(4)
- else if text == "magenta": return _Color.Color8Bit(5)
- else if text == "cyan": return _Color.Color8Bit(6)
- else if text == "white": return _Color.Color8Bit(7)
- else if text == "default": return _Color.Default
- else if text == "BLACK": return _Color.Bright(0)
- else if text == "RED": return _Color.Bright(1)
- else if text == "GREEN": return _Color.Bright(2)
- else if text == "YELLOW": return _Color.Bright(3)
- else if text == "BLUE": return _Color.Bright(4)
- else if text == "MAGENTA": return _Color.Bright(5)
- else if text == "CYAN": return _Color.Bright(6)
- else if text == "WHITE": return _Color.Bright(7)
+ if n >= 0 and n <= 255 return Color8Bit(n)
+ else if text == "black" return _Color.Color8Bit(0)
+ else if text == "red" return _Color.Color8Bit(1)
+ else if text == "green" return _Color.Color8Bit(2)
+ else if text == "yellow" return _Color.Color8Bit(3)
+ else if text == "blue" return _Color.Color8Bit(4)
+ else if text == "magenta" return _Color.Color8Bit(5)
+ else if text == "cyan" return _Color.Color8Bit(6)
+ else if text == "white" return _Color.Color8Bit(7)
+ else if text == "default" return _Color.Default
+ else if text == "BLACK" return _Color.Bright(0)
+ else if text == "RED" return _Color.Bright(1)
+ else if text == "GREEN" return _Color.Bright(2)
+ else if text == "YELLOW" return _Color.Bright(3)
+ else if text == "BLUE" return _Color.Bright(4)
+ else if text == "MAGENTA" return _Color.Bright(5)
+ else if text == "CYAN" return _Color.Bright(6)
+ else if text == "WHITE" return _Color.Bright(7)
return none
- func fg(c:_Color -> Text):
- when c is Color8Bit(color):
- if color >= 0 and color <= 7: return "$(30+color)"
- else if color >= 0 and color <= 255: return "38;5;$color"
- is Color24Bit(hex):
- if hex >= 0 and hex <= 0xFFFFFF:
+ func fg(c:_Color -> Text)
+ when c is Color8Bit(color)
+ if color >= 0 and color <= 7 return "$(30+color)"
+ else if color >= 0 and color <= 255 return "38;5;$color"
+ is Color24Bit(hex)
+ if hex >= 0 and hex <= 0xFFFFFF
return "38;2;$((hex >> 16) and 0xFF);$((hex >> 8) and 0xFF);$((hex >> 0) and 0xFF)"
- is Bright(color):
- if color <= 7: return "$(90+color)"
- is Default:
+ is Bright(color)
+ if color <= 7 return "$(90+color)"
+ is Default
return "39"
fail("Invalid foreground color: '$c'")
- func bg(c:_Color -> Text):
- when c is Color8Bit(color):
- if color >= 0 and color <= 7: return "$(40+color)"
- else if color >= 0 and color <= 255: return "48;5;$color"
- is Color24Bit(hex):
- if hex >= 0 and hex <= 0xFFFFFF:
+ func bg(c:_Color -> Text)
+ when c is Color8Bit(color)
+ if color >= 0 and color <= 7 return "$(40+color)"
+ else if color >= 0 and color <= 255 return "48;5;$color"
+ is Color24Bit(hex)
+ if hex >= 0 and hex <= 0xFFFFFF
return "48;2;$((hex >> 16) and 0xFF);$((hex >> 8) and 0xFF);$((hex >> 0) and 0xFF)"
- is Bright(color):
- if color <= 7: return "$(90+color)"
- is Default:
+ is Bright(color)
+ if color <= 7 return "$(90+color)"
+ is Default
return "49"
fail("Invalid background color: '$c'")
- func underline(c:_Color -> Text):
- when c is Color8Bit(color):
- if color >= 0 and color <= 255: return "58;5;$color"
- is Color24Bit(hex):
- if hex >= 0 and hex <= 0xFFFFFF:
+ func underline(c:_Color -> Text)
+ when c is Color8Bit(color)
+ if color >= 0 and color <= 255 return "58;5;$color"
+ is Color24Bit(hex)
+ if hex >= 0 and hex <= 0xFFFFFF
return "58;2;$((hex >> 16) and 0xFF);$((hex >> 8) and 0xFF);$((hex >> 0) and 0xFF)"
- is Default:
+ is Default
return "59"
- is Bright(color):
+ is Bright(color)
pass
fail("Invalid underline color: '$c'")
-func _toggle(sequences:&[Text], cur,new:Bool, apply,unapply:Text; inline):
- if new and not cur:
+func _toggle(sequences:&[Text], cur,new:Bool, apply,unapply:Text; inline)
+ if new and not cur
sequences.insert(apply)
- else if cur and not new:
+ else if cur and not new
sequences.insert(unapply)
-func _toggle2(sequences:&[Text], cur1,cur2,new1,new2:Bool, apply1,apply2,unapply:Text; inline):
+func _toggle2(sequences:&[Text], cur1,cur2,new1,new2:Bool, apply1,apply2,unapply:Text; inline)
return if new1 == cur1 and new2 == cur2
- if (cur1 and not new1) or (cur2 and not new2): # Gotta wipe at least one
+ if (cur1 and not new1) or (cur2 and not new2) # Gotta wipe at least one
sequences.insert(unapply)
cur1, cur2 = no, no # Wiped out
- if new1 and not cur1:
+ if new1 and not cur1
sequences.insert(apply1)
- if new2 and not cur2:
+ if new2 and not cur2
sequences.insert(apply2)
struct _TermState(
@@ -138,9 +138,9 @@ struct _TermState(
reverse=no, conceal=no, strikethrough=no, fraktur=no, frame=no,
encircle=no, overline=no, superscript=no, subscript=no,
bg=_Color.Default, fg=_Color.Default, underline_color=_Color.Default,
-):
+)
- func apply(old,new:_TermState -> Text):
+ func apply(old,new:_TermState -> Text)
sequences : &[Text] = &[]
_toggle2(sequences, old.bold, old.dim, new.bold, new.dim, "1", "2", "22")
_toggle2(sequences, old.italic, old.fraktur, new.italic, new.fraktur, "3", "20", "23")
@@ -153,66 +153,66 @@ struct _TermState(
_toggle(sequences, old.overline, new.overline, "53", "55")
_toggle2(sequences, old.subscript, old.subscript, new.superscript, new.superscript, "73", "74", "75")
- if new.bg != old.bg:
+ if new.bg != old.bg
sequences.insert(new.bg.bg())
- if new.fg != old.fg:
+ if new.fg != old.fg
sequences.insert(new.fg.fg())
- if new.underline_color != old.underline_color:
+ if new.underline_color != old.underline_color
sequences.insert(new.underline_color.underline())
- if sequences.length == 0:
+ if sequences.length == 0
return ""
return CSI ++ ";".join(sequences) ++ "m"
-func _add_ansi_sequences(text:Text, prev_state:_TermState -> Text):
- if text == "lparen": return "("
- else if text == "rparen": return ")"
- else if text == "@" or text == "at": return "@"
+func _add_ansi_sequences(text:Text, prev_state:_TermState -> Text)
+ if text == "lparen" return "("
+ else if text == "rparen" return ")"
+ else if text == "@" or text == "at" return "@"
parts := (
text.pattern_captures($Pat/{0+..}:{0+..}/) or
return "@("++_for_terminal(Colorful.from_text(text), prev_state)++")"
)
attributes := parts[1].split_pattern($Pat/{0+space},{0+space}/)
new_state := prev_state
- for attr in attributes:
- if attr.starts_with("fg="):
+ for attr in attributes
+ if attr.starts_with("fg=")
new_state.fg = _Color.from_text(attr.from(4))!
- else if attr.starts_with("bg="):
+ else if attr.starts_with("bg=")
new_state.bg = _Color.from_text(attr.from(4))!
- else if attr.starts_with("ul="):
+ else if attr.starts_with("ul=")
new_state.underline_color = _Color.from_text(attr.from(4))!
- else if color := _Color.from_text(attr):
+ else if color := _Color.from_text(attr)
new_state.fg = color
- else if attr == "b" or attr == "bold":
+ else if attr == "b" or attr == "bold"
new_state.bold = yes
- else if attr == "d" or attr == "dim":
+ else if attr == "d" or attr == "dim"
new_state.dim = yes
- else if attr == "i" or attr == "italic":
+ else if attr == "i" or attr == "italic"
new_state.italic = yes
- else if attr == "u" or attr == "underline":
+ else if attr == "u" or attr == "underline"
new_state.underline = yes
- else if attr == "B" or attr == "blink":
+ else if attr == "B" or attr == "blink"
new_state.blink = yes
- else if attr == "r" or attr == "reverse":
+ else if attr == "r" or attr == "reverse"
new_state.reverse = yes
- else if attr == "fraktur":
+ else if attr == "fraktur"
new_state.fraktur = yes
- else if attr == "frame":
+ else if attr == "frame"
new_state.frame = yes
- else if attr == "encircle":
+ else if attr == "encircle"
new_state.encircle = yes
- else if attr == "overline":
+ else if attr == "overline"
new_state.overline = yes
- else if attr == "super" or attr == "superscript":
+ else if attr == "super" or attr == "superscript"
new_state.superscript = yes
- else if attr == "sub" or attr == "subscript":
+ else if attr == "sub" or attr == "subscript"
new_state.subscript = yes
- else:
+ else
fail("Invalid attribute: '$attr'")
result := prev_state.apply(new_state)
- result ++= parts[2].map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch): _add_ansi_sequences(m.captures[1], new_state))
+ result ++= parts[2].map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch) _add_ansi_sequences(m.captures[1], new_state))
result ++= new_state.apply(prev_state)
return result