Skip to content

Commit

Permalink
alternate between text colors and background colors
Browse files Browse the repository at this point in the history
  • Loading branch information
EugenDueck committed Mar 29, 2024
1 parent d77a35a commit 04fd64b
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 52 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ jobs:
- name: Download dependencies
run: go mod tidy

# Run tests
- name: Run tests
run: go test ./...

# Build Linux
- name: Build Linux
run: |
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ something that is not easy to achieve with tools like `grep` and `less`.
```
Usage: colorexp [options] patterns...
-F, --fixed-strings Do not interpret regular expression metacharacters.
-H, --highlight Color by changing the background color. The default is to change the foreground color.
-h, --no-highlight Do not color by changing the background color.
-H, --only-highlight Only color by changing the background color.
-i, --ignore-case Perform case insensitive matching.
-g, --vary-group-colors-off Turn off changing of colors for every capturing group. Defaults to on if exactly one pattern is given.
-G, --vary-group-colors-on Turn on changing of colors for every capturing group. Defaults to on if exactly one pattern is given.
```
## Examples

### Basic Usage
- use the `-H` option to colorize the background, instead of the text
- use the `-h`/`-H` options to only colorize the text, or only the background

![Example](example-basic.png)

Expand All @@ -39,7 +40,7 @@ Usage: colorexp [options] patterns...
- when multiple patterns are given, the default is to use the same colors for all capturing groups of a pattern
- in case of a single pattern, the `-g` option can be used to enforce use of a single color

![Example](example-group-same-colors.png)
![Example](example-group-same-color.png)

# Installation

Expand Down
72 changes: 48 additions & 24 deletions colorexp.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"regexp"
)

const version = "1.0.5"
const version = "1.0.6"

var foregroundColors = []string{
//"\033[30m", // Black
Expand Down Expand Up @@ -105,7 +105,7 @@ func match(line string, regexps []*regexp.Regexp, varyGroupColors bool) []rangeW
for i := 0; i < groupsToColorize; i++ {
curColorIdx := colorIdx
if varyGroupColors {
curColorIdx += i
curColorIdx += groupsToColorize - 1 - i
}
gIdx := (i + firstGroupToColorize) * 2
matchRangeStart := matchRange[gIdx]
Expand All @@ -115,19 +115,27 @@ func match(line string, regexps []*regexp.Regexp, varyGroupColors bool) []rangeW
}
}
}
colorIdx += groupsToColorize
if varyGroupColors {
colorIdx += groupsToColorize
} else {
colorIdx++
}
}
return ranges
}

func colorize(s string, colors []string, resetColor string, ranges []rangeWithID) string {
func colorize(s string, colors [][]string, ranges []rangeWithID, patternColorCount int) string {
for i, r := range ranges {
color := colors[r.id%len(colors)]
s = insertString(s, color, r.startIndex)
incRanges(ranges, len(color))
colorIdx := patternColorCount - r.id - 1
for colorIdx < 0 {
colorIdx += len(colors)
}
color := colors[colorIdx%len(colors)]
s = insertString(s, color[0], r.startIndex)
incRanges(ranges, len(color[0]))
// ranges[i] was modified by incRanges, so we need to use that, not the stale r
s = insertString(s, resetColor, ranges[i].endIndex)
incRanges(ranges, len(resetColor))
s = insertString(s, color[1], ranges[i].endIndex)
incRanges(ranges, len(color[1]))
}
return s
}
Expand All @@ -147,7 +155,8 @@ func main() {
var (
fixedStrings bool
showHelp bool
highlight bool
noHighlight bool
onlyHighlight bool
ignoreCase bool
showVersion bool
varyGroupColorsOn bool
Expand All @@ -156,8 +165,9 @@ func main() {
)

pflag.BoolVarP(&fixedStrings, "fixed-strings", "F", false, "Do not interpret regular expression metacharacters.")
pflag.BoolVarP(&showHelp, "help", "h", false, "Display this help and exit.")
pflag.BoolVarP(&highlight, "highlight", "H", false, "Color by changing the background color. The default is to change the foreground color.")
pflag.BoolVarP(&showHelp, "help", "", false, "Display this help and exit.")
pflag.BoolVarP(&noHighlight, "no-highlight", "h", false, "Do not color by changing the background color.")
pflag.BoolVarP(&onlyHighlight, "only-highlight", "H", false, "Only color by changing the background color.")
pflag.BoolVarP(&ignoreCase, "ignore-case", "i", false, "Perform case insensitive matching.")
pflag.BoolVarP(&showVersion, "version", "V", false, "Display version information and exit.")

Expand All @@ -179,14 +189,14 @@ func main() {
regexStrings := pflag.Args()

if len(regexStrings) == 0 {
_, _ = fmt.Println("Error: At least one pattern argument is required.\n")
_, _ = fmt.Printf("Error: At least one pattern argument is required.\n\n")
printUsage()
os.Exit(1)
}

if pflag.Lookup("vary-group-colors-on").Changed {
if pflag.Lookup("vary-group-colors-off").Changed {
_, _ = fmt.Println("Error: -G/-g arguments cannot both be used at the same time.\n")
_, _ = fmt.Printf("Error: -g/-G arguments cannot both be used at the same time.\n\n")
printUsage()
os.Exit(1)
}
Expand All @@ -211,26 +221,40 @@ func main() {
_, _ = fmt.Printf("Invalid regular expression: %v\n", err)
os.Exit(1)
}
// insert at the beginning of the slice, to invert the order,
// insert at the beginning of the slice, to reverse the order,
// so that the last regex takes precedence
regexps = append([]*regexp.Regexp{re}, regexps...)
//regexps = append(regexps, re)
}

var colors []string
var resetColor string
if highlight {
colors = backgroundColors
resetColor = resetBackgroundColor
} else {
colors = foregroundColors
resetColor = resetForegroundColor
var colors [][]string
if !pflag.Lookup("only-highlight").Changed {
for _, foreColor := range foregroundColors {
colors = append(colors, []string{foreColor, resetForegroundColor})
}
} else if pflag.Lookup("no-highlight").Changed {
_, _ = fmt.Printf("Error: -h/-H arguments cannot both be used at the same time.\n\n")
printUsage()
os.Exit(1)
}
if !pflag.Lookup("no-highlight").Changed {
for _, backColor := range backgroundColors {
colors = append(colors, []string{backColor, resetBackgroundColor})
}
}

patternColorCount := len(regexps)
if varyGroupColors {
for _, re := range regexps {
patternColorCount += max(0, re.NumSubexp()-1)
}
}

scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
ranges := match(line, regexps, varyGroupColors)
colorizedLine := colorize(line, colors, resetColor, ranges)
colorizedLine := colorize(line, colors, ranges, patternColorCount)
fmt.Println(colorizedLine)
}

Expand Down
50 changes: 25 additions & 25 deletions colorexp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,42 +86,42 @@ func TestAddRange(t *testing.T) {

func TestColorize(t *testing.T) {
tests := []struct {
name string
s string
colors []string
resetColor string
ranges []rangeWithID
want string
name string
s string
reversedColors [][]string
patternColorCount int
ranges []rangeWithID
want string
}{
{
name: "single colorization",
s: "Hello, world!",
colors: []string{"\033[31m"},
resetColor: "\033[0m",
ranges: []rangeWithID{{7, 12, 0}},
want: "Hello, \033[31mworld\033[0m!",
name: "single colorization",
s: "Hello, world!",
reversedColors: [][]string{{"\033[31m", "\033[0m"}},
patternColorCount: 1,
ranges: []rangeWithID{{7, 12, 0}},
want: "Hello, \033[31mworld\033[0m!",
},
{
name: "multiple colorization",
s: "Hello, beautiful world!",
colors: []string{"\033[31m", "\033[32m"},
resetColor: "\033[0m",
ranges: []rangeWithID{{7, 16, 0}, {17, 22, 1}},
want: "Hello, \033[31mbeautiful\033[0m \033[32mworld\033[0m!",
name: "multiple colorization",
s: "Hello, beautiful world!",
reversedColors: [][]string{{"\033[32m", "\033[0m"}, {"\033[31m", "\033[0m"}},
patternColorCount: 2,
ranges: []rangeWithID{{7, 16, 0}, {17, 22, 1}},
want: "Hello, \033[31mbeautiful\033[0m \033[32mworld\033[0m!",
},
{
name: "cycle colors",
s: "Hello, beautiful world!",
colors: []string{"\033[31m", "\033[32m"},
resetColor: "\033[0m",
ranges: []rangeWithID{{7, 16, 0}, {17, 22, 2}},
want: "Hello, \033[31mbeautiful\033[0m \033[31mworld\033[0m!",
name: "cycle colors",
s: "Hello, beautiful world!",
reversedColors: [][]string{{"\033[32m", "\033[0m"}, {"\033[31m", "\033[0m"}},
patternColorCount: 2,
ranges: []rangeWithID{{7, 16, 0}, {17, 22, 2}},
want: "Hello, \033[31mbeautiful\033[0m \033[31mworld\033[0m!",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := colorize(tt.s, tt.colors, tt.resetColor, tt.ranges)
got := colorize(tt.s, tt.reversedColors, tt.ranges, tt.patternColorCount)
if got != tt.want {
t.Errorf("colorize() = %v, want %v", got, tt.want)
}
Expand Down
Binary file modified example-basic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example-group-same-color.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed example-group-same-colors.png
Binary file not shown.
Binary file modified example-group-varying-colors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example-overlaps.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 04fd64b

Please sign in to comment.