Glob matching for exclude

This commit is contained in:
Laurence Withers 2023-05-13 12:30:39 +01:00
parent 8b56504cd7
commit b481db737e
3 changed files with 21 additions and 10 deletions

1
go.mod
View File

@ -3,6 +3,7 @@ module src.lwithers.me.uk/go/gg
go 1.20 go 1.20
require ( require (
github.com/bmatcuk/doublestar/v4 v4.6.0
github.com/logrusorgru/aurora/v4 v4.0.0 github.com/logrusorgru/aurora/v4 v4.0.0
github.com/spf13/cobra v1.7.0 github.com/spf13/cobra v1.7.0
golang.org/x/sys v0.8.0 golang.org/x/sys v0.8.0

2
go.sum
View File

@ -1,3 +1,5 @@
github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=

28
main.go
View File

@ -5,17 +5,18 @@ package main
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"github.com/bmatcuk/doublestar/v4"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
// TODO: // TODO:
// - bold of escaped output doesn't work // - bold of escaped output doesn't work
// - ignore files by extension (or glob?)
func main() { func main() {
if err := rootCmd.Execute(); err != nil { if err := rootCmd.Execute(); err != nil {
@ -42,7 +43,11 @@ as paths to scan.
Search defaults to case-sensitive but the -i flag may be passed to make regular Search defaults to case-sensitive but the -i flag may be passed to make regular
expression searches case-insensitive. Alternatively, the "(?i)" construct may be expression searches case-insensitive. Alternatively, the "(?i)" construct may be
added to a regular expression to make that specific expression case insensitive. added to a regular expression to make that specific expression case insensitive.
Fixed pattern matches are always case-sensitive.`, Fixed pattern matches are always case-sensitive.
Files and directories can be excluded with the -x option. This supports bash-style
globs with '*', '?', '[a-z]', '{this,that}', or '/**/' to match zero or more
directories. By default, .git and vim swap files are ignored.`,
RunE: run, RunE: run,
} }
@ -53,10 +58,9 @@ var (
searchFixed []string searchFixed []string
searchBytes [][]byte searchBytes [][]byte
searchPath []string searchPath []string
ignoreList []string excludeList []string
binaryFile notPlainTextFlag binaryFile notPlainTextFlag
minifiedFile notPlainTextFlag minifiedFile notPlainTextFlag
ignoreMap map[string]struct{}
ignoreCase bool ignoreCase bool
noColour bool noColour bool
display *Display display *Display
@ -66,7 +70,7 @@ var (
func init() { func init() {
rootCmd.Flags().StringSliceVarP(&searchRegexp, "grep", "e", nil, "pattern to match (regular expression)") rootCmd.Flags().StringSliceVarP(&searchRegexp, "grep", "e", nil, "pattern to match (regular expression)")
rootCmd.Flags().StringSliceVarP(&searchFixed, "fixed", "Q", nil, "pattern to match (fixed string)") rootCmd.Flags().StringSliceVarP(&searchFixed, "fixed", "Q", nil, "pattern to match (fixed string)")
rootCmd.Flags().StringSliceVarP(&ignoreList, "exclude", "x", []string{".git"}, "files/directories to exclude") rootCmd.Flags().StringSliceVarP(&excludeList, "exclude", "x", []string{".git", ".*.swp"}, "files/directories to exclude")
rootCmd.Flags().BoolVarP(&ignoreCase, "ignore-case", "i", false, "make all searches case insensitive") rootCmd.Flags().BoolVarP(&ignoreCase, "ignore-case", "i", false, "make all searches case insensitive")
rootCmd.Flags().BoolVarP(&noColour, "no-colour", "C", false, "disable colour output") rootCmd.Flags().BoolVarP(&noColour, "no-colour", "C", false, "disable colour output")
rootCmd.Flags().Var(&binaryFile, "binary", "what to do with binary files") rootCmd.Flags().Var(&binaryFile, "binary", "what to do with binary files")
@ -89,9 +93,10 @@ func run(c *cobra.Command, args []string) error {
searchPath = append(searchPath, ".") searchPath = append(searchPath, ".")
} }
ignoreMap = make(map[string]struct{}, len(ignoreList)) for _, x := range excludeList {
for _, i := range ignoreList { if !doublestar.ValidatePattern(x) {
ignoreMap[i] = struct{}{} return fmt.Errorf("invalid exclude pattern %q", x)
}
} }
for _, r := range searchRegexp { for _, r := range searchRegexp {
@ -126,12 +131,15 @@ func recurse(path string) error {
} }
var errs []error var errs []error
NextFile:
for _, de := range d { for _, de := range d {
name := de.Name() name := de.Name()
fullPath := filepath.Join(path, name) fullPath := filepath.Join(path, name)
if _, ignored := ignoreMap[name]; ignored { for _, x := range excludeList {
continue if exclude, _ := doublestar.Match(x, fullPath); exclude {
continue NextFile
}
} }
if err := search(fullPath); err != nil { if err := search(fullPath); err != nil {