diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-04-06 16:07:23 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-04-06 16:07:23 -0400 |
| commit | 6782cc5570e194791ca6cdd695b88897e9145564 (patch) | |
| tree | a428e9d954aca251212ec1cf15bd35e0badce630 /examples/colorful/colorful.tm | |
| parent | 448e805293989b06e07878a4a87fdd378f7c6e02 (diff) | |
No more colons for blocks
Diffstat (limited to 'examples/colorful/colorful.tm')
| -rw-r--r-- | examples/colorful/colorful.tm | 202 |
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 |
