diff options
Diffstat (limited to 'hi.go')
| -rw-r--r-- | hi.go | 131 |
1 files changed, 131 insertions, 0 deletions
@@ -0,0 +1,131 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "regexp" + "strings" +) + +func init() { + highlightColor = red + flag.Var((*colorFlag)(&highlightColor), "c", fmt.Sprintf("highlight `color` %s", colorsChoices)) + background = defaultColor + flag.Var((*colorFlag)(&background), "bg", fmt.Sprintf("background `color` default|%s", colorsChoices)) +} + +var ( + highlightColor ansiColor + background ansiColor +) + +//go:generate stringer -type=ansiColor -linecomment +type ansiColor int + +const ( + black ansiColor = iota + red + green + yellow + blue + magenta + cyan + white + defaultColor ansiColor = 9 // default +) + +var colorsChoices = func() string { + nColors := white - black + 1 + colors := make([]string, nColors) + for i := range nColors { + colors[i] = (black + i).String() + } + return strings.Join(colors, "|") +}() + +func (c ansiColor) Foreground() int { + return 30 + int(c) +} + +func (c ansiColor) Background() int { + return 40 + int(c) +} + +type colorFlag int + +func (c *colorFlag) Set(val string) error { + var ac ansiColor + switch strings.ToLower(val) { + case "default": + ac = defaultColor + case "black": + ac = black + case "red": + ac = red + case "green": + ac = green + case "yellow": + ac = yellow + case "blue": + ac = blue + case "magenta": + ac = magenta + case "cyan": + ac = cyan + case "white": + ac = white + default: + return fmt.Errorf("unknown color %q (valid choices: %s)", val, colorsChoices) + } + *c = colorFlag(ac) + return nil +} + +func (c *colorFlag) String() string { + return ansiColor(*c).String() +} + +func run() error { + args := flag.Args() + if len(args) == 0 { + fmt.Fprintf(os.Stderr, "missing regexp to highlight\n") + flag.Usage() + } + if len(args) > 2 { + fmt.Fprintf(os.Stderr, "too many positional arguments\n") + flag.Usage() + } + highlightRE, err := regexp.CompilePOSIX(args[0]) + if err != nil { + return fmt.Errorf("invalid highlight regexp: %s", err) + } + foregroundColor := highlightColor.Foreground() + backgroundColor := background.Background() + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + line := scanner.Text() + loc := highlightRE.FindStringIndex(line) + if loc == nil { + fmt.Printf("%s\n", line) + continue + } + startIdx, endIdx := loc[0], loc[1] + fmt.Printf("%s\033[%d;%dm%s\033[39;49m%s\n", line[:startIdx], foregroundColor, backgroundColor, line[startIdx:endIdx], line[endIdx:]) + } + return scanner.Err() +} + +func main() { + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage: hi [OPTIONS] REGEXP\n") + flag.PrintDefaults() + os.Exit(2) + } + flag.Parse() + if err := run(); err != nil { + fmt.Fprintf(os.Stderr, "hi: %s\n", err) + os.Exit(1) + } +} |
