aboutsummaryrefslogtreecommitdiffstats
path: root/hi.go
diff options
context:
space:
mode:
Diffstat (limited to 'hi.go')
-rw-r--r--hi.go131
1 files changed, 131 insertions, 0 deletions
diff --git a/hi.go b/hi.go
new file mode 100644
index 0000000..ec927b3
--- /dev/null
+++ b/hi.go
@@ -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)
+ }
+}