chromaterm

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 19 Imported by: 0

README

chromaterm-go

A Go port of ChromaTerm 0.10.7: colour terminal output by keyword (IP and MAC addresses, URLs, dates, times, sizes, numbers, and words like error, failed, warning, ok). No Python needed.

It keeps ChromaTerm's config format, default rules, colour handling and output buffering, so an existing ~/.chromaterm.yml works as is. Its tests replay the original ChromaTerm's output for the default rules and the highlighting algorithm.

go get github.com/jurger/chromaterm-go

Highlight text

cfg := chromaterm.NewConfig()
cfg.Load(chromaterm.DefaultConfig, true) // true: 24-bit colour; false: xterm-256
fmt.Println(cfg.Highlight("link to 10.0.0.1 is down"))

Highlight keeps colours already in the text and nests its own inside them. A Config remembers the colours it emitted, so feed one stream through one Config.

Highlight a program

RunInPTY runs a program in its own PTY: keystrokes pass through untouched, output is highlighted, the window size follows SIGWINCH, and the program's exit code is returned. This is how to colour ssh or a shell.

code, err := chromaterm.RunInPTY([]string{"ssh", "host"}, cfg, os.Stdin, os.Stdout)
if err != nil {
	// No PTY (e.g. on Windows): run the program without highlighting.
}
os.Exit(code)

For a stream that is not a PTY, use (&chromaterm.Stream{Config: cfg}).Run(in, out): it waits briefly for cut-off lines and leaves single typed characters alone, as ChromaTerm does.

Unlike ChromaTerm, output drawn on the alternate screen (vim, less, htop) is not highlighted.

Config

palette:
  alert: "#ff0000"

rules:
- description: Failed logins
  regex: (?i)failed password for (\w+)
  color:
    0: f.alert      # the whole match
    1: bold         # group 1
- description: Hosts
  regex: \bweb-\d+\b
  color: f#00aaff underline
  exclusive: true   # other rules can't colour these characters
  • Colours: f#rrggbb / b#rrggbb (foreground / background), f.name / b.name from the palette, and the styles blink, bold, invert, italic, strike and underline, combined with spaces.
  • Regular expressions: Python syntax, through regexp2: lookaround, backreferences, (?P<name>…) / (?P=name) and inline flags such as (?ix). Group numbers follow Python's order, named groups included.
  • Errors: Load returns one error per rule it had to skip and keeps the rest.

chromaterm.DefaultConfig holds ChromaTerm's default palette and rules as YAML; write it to a file to give users something to edit.

Platforms

Highlighting works everywhere. RunInPTY needs a Unix PTY (Linux, macOS, BSD); on Windows it returns an error (PTYSupported is false).

License

MIT. ChromaTerm is © 2020 Saria H.; see LICENSE.

Documentation

Overview

Package chromaterm colours terminal output by keyword. It is a Go port of ChromaTerm 0.10.7 (https://github.com/hSaria/ChromaTerm) that keeps its config format, default rules, colour handling and output buffering, so an existing ~/.chromaterm.yml works unchanged. No Python is involved.

Highlight text with a Config:

cfg := chromaterm.NewConfig()
cfg.Load(chromaterm.DefaultConfig, true) // true for 24-bit colour
fmt.Println(cfg.Highlight("ping 10.0.0.1 failed"))

Highlight a stream as it arrives, waiting briefly for cut-off lines the way ChromaTerm does, with (&Stream{Config: cfg}).Run(in, out). To colour an interactive program (ssh, a shell), run it with RunInPTY: the program gets its own PTY, keystrokes pass through, and its output is highlighted. Unlike ChromaTerm, output on the alternate screen (vim, less, htop) is left alone.

Rules use ChromaTerm's (Python) regular expression syntax, including lookaround and backreferences, through github.com/dlclark/regexp2.

Example
package main

import (
	"fmt"
	"strings"

	chromaterm "github.com/jurger/chromaterm-go"
)

func main() {
	cfg := chromaterm.NewConfig()
	cfg.Load(chromaterm.DefaultConfig, true)
	out := cfg.Highlight("link to 10.0.0.1 is down")
	fmt.Println(strings.ReplaceAll(out, "\x1b", `\e`))
}
Output:
link to \e[38;2;0;224;209m10.0.0.1\e[39m is \e[38;2;199;24;0mdown\e[39m

Index

Examples

Constants

View Source
const PTYSupported = true

PTYSupported reports whether RunInPTY works on this platform.

Variables

View Source
var DefaultConfig string

DefaultConfig is ChromaTerm's default palette and rules.

Functions

func ExitCode

func ExitCode(err error) int

ExitCode turns the error from running a program into its exit code: 0 for success, the program's code when it exited, 1 when it was killed by a signal, and 127 when it could not run at all.

func RunInPTY

func RunInPTY(program []string, cfg *Config, in *os.File, out io.Writer) (int, error)

RunInPTY runs program in a new PTY and returns its exit code. Input from in is copied raw (in is switched to raw mode if it is a terminal), output is highlighted with cfg on its way to out, and in's window size follows SIGWINCH. An error means the PTY could not be started; run the program without highlighting then.

Types

type Color

type Color struct {
	Spec string
	// contains filtered or unexported fields
}

Color is a parsed ChromaTerm colour such as "f#ff0000 bold" or "b.status-1".

func ParseColor

func ParseColor(spec string, palette Palette, rgb bool) (Color, error)

ParseColor parses a colour spec. rgb selects 24-bit colour codes; otherwise hex colours are downscaled to the xterm-256 palette.

type Config

type Config struct {
	Rules []*Rule
	// contains filtered or unexported fields
}

Config highlights data with its rules. It remembers the last colour of each type it emitted, so a highlight that ends in a later chunk restores the colour the program had set instead of the terminal default.

func NewConfig

func NewConfig() *Config

NewConfig returns a config with no rules.

func (*Config) Highlight

func (c *Config) Highlight(data string) string

Highlight returns data with the rules' colours added. Existing colours are stripped before matching so they don't interfere, then put back.

func (*Config) Load

func (c *Config) Load(data string, rgb bool) []error

Load parses a ChromaTerm YAML config (palette and rules). Rules that fail to parse are skipped and reported in the returned errors; a config that cannot be read at all leaves c unchanged.

Example
package main

import (
	"fmt"

	chromaterm "github.com/jurger/chromaterm-go"
)

func main() {
	cfg := chromaterm.NewConfig()
	errs := cfg.Load(`
palette:
  alert: "#ff0000"
rules:
- description: Failed logins
  regex: (?i)failed password for (\w+)
  color:
    0: f.alert
    1: bold
`, true)
	fmt.Println(len(cfg.Rules), errs)
}
Output:
1 []

type Palette

type Palette map[string]string

Palette maps colour names to hex colours, for "f.name" and "b.name".

func (Palette) Add

func (p Palette) Add(name, value string) error

Add registers a palette colour.

type Rule

type Rule struct {
	Description string
	Regex       string
	Exclusive   bool
	// contains filtered or unexported fields
}

Rule highlights the matches of a regular expression. Colours are keyed by regex group; group 0 colours the whole match.

func NewRule

func NewRule(regex string, colors map[any]Color, description string, exclusive bool) (*Rule, error)

NewRule compiles regex, which uses ChromaTerm's (Python) syntax: lookaround, backreferences and (?P<name>...) groups are supported. colors maps a group number or name to its colour.

type Stream

type Stream struct {
	Config *Config
	// contains filtered or unexported fields
}

Stream highlights everything read from in and writes it to out, until in reaches EOF. It is a port of ChromaTerm's process_input for a program run in a PTY: complete chunks are written at once, and the trailing chunk waits briefly for the rest of its line so a match is not split across reads.

func (*Stream) Run

func (s *Stream) Run(in io.Reader, out io.Writer) error

Run copies in to out with highlighting.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL