aboutsummaryrefslogtreecommitdiff
path: root/examples/colorful
diff options
context:
space:
mode:
Diffstat (limited to 'examples/colorful')
-rw-r--r--examples/colorful/CHANGES.md13
-rw-r--r--examples/colorful/README.md70
-rw-r--r--examples/colorful/colorful.tm220
-rw-r--r--examples/colorful/modules.ini2
-rw-r--r--examples/colorful/test.colors9
5 files changed, 0 insertions, 314 deletions
diff --git a/examples/colorful/CHANGES.md b/examples/colorful/CHANGES.md
deleted file mode 100644
index 093cc077..00000000
--- a/examples/colorful/CHANGES.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Version History
-
-## v1.2
-
-- Version bump for patterns.
-
-## v1.1
-
-- Added syntax for `@(strikethrough:...)` or `@(s:...)`
-
-## v1.0
-
-Initial version
diff --git a/examples/colorful/README.md b/examples/colorful/README.md
deleted file mode 100644
index faded9b1..00000000
--- a/examples/colorful/README.md
+++ /dev/null
@@ -1,70 +0,0 @@
-# Colorful Lang
-
-Colorful is a `lang` that lets you write colorful text for the terminal without
-having to stress about managing state for color highlighting.
-
-## Grammar
-
-The grammar looks like this:
-
-```
-colorful <- ("@(at)" / "@(lparen)" / "@(rparen)" # Escapes
- / "@(" attributes ":" colorful ")" # Colorful text
- / .)* # Plain text
-
-attributes <- (attribute ("," attribute)*)?
-
-attribute <- color # Color defaults to foreground
- / "fg=" color # Foreground color
- / "bg=" color # Background color
- / "ul=" color # Underline color
- / "b" / "bold"
- / "d" / "dim"
- / "u" / "underline"
- / "i" / "italic"
- / "B" / "blink"
- / "r" / "reverse"
- # These are rarely supported by terminals:
- / "fraktur"
- / "frame"
- / "encircle"
- / "overline"
- / "super" / "superscript"
- / "sub" / "subscript"
-
-color <- "black" / "red" / "green" / "yellow" / "blue" / "magenta" / "cyan" / "white"
- # All caps colors are "bright" colors (not always supported):
- / "BLACK" / "RED" / "GREEN" / "YELLOW" / "BLUE" / "MAGENTA" / "CYAN" / "WHITE"
- / "default"
- / "#" 6 hex # Values 0x000000-0xFFFFFF
- / "#" 3 hex # Values 0x000-0xFFF
- / 1-3 digit # Values 0-255
-```
-
-## Command Line Usage
-
-You can run `colorful` as a standalone executable to render colorful text with
-ANSI escape sequences so it looks nice on a terminal.
-
-```
-colorful [--help] [texts...] [--by-line] [--files ...]
-```
-
-## Library Usage
-
-`colorful` can also be used as a Tomo library:
-
-```ini
-# modules.ini
-[colorful]
-version=v1.0
-```
-
-```tomo
-use colorful
-
-$Colorful"
- @(blue:Welcome to the @(bold:party)!)
- We have @(green,bold:colors)!
-".print()
-```
diff --git a/examples/colorful/colorful.tm b/examples/colorful/colorful.tm
deleted file mode 100644
index 5b01cfd5..00000000
--- a/examples/colorful/colorful.tm
+++ /dev/null
@@ -1,220 +0,0 @@
-# Colorful language
-
-HELP := "
- colorful: A domain-specific language for writing colored text to the terminal
- Usage: colorful [args...] [--by-line] [--files files...]
-"
-
-CSI := "\033["
-
-use patterns
-
-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")
-
- func for_terminal(c:Colorful -> Text)
- return CSI ++ "m" ++ _for_terminal(c, _TermState())
-
- 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
- colorful := Colorful.from_text(text)
- colorful.print(newline=no)
- if i == texts.length then say("")
- else say(" ", newline=no)
-
- 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")
- colorful := Colorful.from_text(line)
- colorful.print()
- 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))
-
-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
- 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}/)
- 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)
- 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
- 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
- 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
- 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
- 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
- return "58;2;$((hex >> 16) and 0xFF);$((hex >> 8) and 0xFF);$((hex >> 0) and 0xFF)"
- is Default
- return "59"
- 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
- sequences.insert(apply)
- else if cur and not new
- sequences.insert(unapply)
-
-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
- sequences.insert(unapply)
- cur1, cur2 = no, no # Wiped out
-
- if new1 and not cur1
- sequences.insert(apply1)
- if new2 and not cur2
- sequences.insert(apply2)
-
-struct _TermState(
- bold=no, dim=no, italic=no, underline=no, blink=no,
- 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)
- 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")
- _toggle(sequences, old.underline, new.underline, "4", "24")
- _toggle(sequences, old.blink, new.blink, "5", "25")
- _toggle(sequences, old.reverse, new.reverse, "7", "27")
- _toggle(sequences, old.conceal, new.conceal, "8", "28")
- _toggle(sequences, old.strikethrough, new.strikethrough, "9", "29")
- _toggle2(sequences, old.frame, old.encircle, new.frame, new.frame, "51", "52", "54")
- _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
- sequences.insert(new.bg.bg())
-
- if new.fg != old.fg
- sequences.insert(new.fg.fg())
-
- if new.underline_color != old.underline_color
- sequences.insert(new.underline_color.underline())
-
- 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 "@"
- 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=")
- new_state.fg = _Color.from_text(attr.from(4))!
- else if attr.starts_with("bg=")
- new_state.bg = _Color.from_text(attr.from(4))!
- else if attr.starts_with("ul=")
- new_state.underline_color = _Color.from_text(attr.from(4))!
- else if color := _Color.from_text(attr)
- new_state.fg = color
- else if attr == "b" or attr == "bold"
- new_state.bold = yes
- else if attr == "d" or attr == "dim"
- new_state.dim = yes
- else if attr == "i" or attr == "italic"
- new_state.italic = yes
- else if attr == "u" or attr == "underline"
- new_state.underline = yes
- else if attr == "s" or attr == "strikethrough"
- new_state.strikethrough = yes
- else if attr == "B" or attr == "blink"
- new_state.blink = yes
- else if attr == "r" or attr == "reverse"
- new_state.reverse = yes
- else if attr == "fraktur"
- new_state.fraktur = yes
- else if attr == "frame"
- new_state.frame = yes
- else if attr == "encircle"
- new_state.encircle = yes
- else if attr == "overline"
- new_state.overline = yes
- else if attr == "super" or attr == "superscript"
- new_state.superscript = yes
- else if attr == "sub" or attr == "subscript"
- new_state.subscript = yes
- 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 ++= new_state.apply(prev_state)
- return result
diff --git a/examples/colorful/modules.ini b/examples/colorful/modules.ini
deleted file mode 100644
index 5e4b5b0a..00000000
--- a/examples/colorful/modules.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[patterns]
-version=v1.1
diff --git a/examples/colorful/test.colors b/examples/colorful/test.colors
deleted file mode 100644
index 314b8b05..00000000
--- a/examples/colorful/test.colors
+++ /dev/null
@@ -1,9 +0,0 @@
-This is some text that has @(bold:@(red:c)@(yellow:o)@(green:l)@(cyan:o)@(blue:r)@(magenta:s))!
-
-@(fg=#aaf,b:You can have @(red:nested) color directives and stuff (even in
-parens) will be handled @(i:right))
-
-@(dim:The output @(bold:ANSI) sequences will be optimal, even if you have
-nested stuff like bold and dim)
-
-(which is distinct from @(bold:BOLD) by itself)