From abe94aa1574363a416e0abe4b4208444e8d16afa Mon Sep 17 00:00:00 2001 From: Aleksey Lobanov Date: Tue, 26 Dec 2023 00:30:17 +0300 Subject: [PATCH] feat: First naive version --- .devcontainer/devcontainer.json | 25 ++++++++ go.mod | 3 + main.go | 100 ++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 go.mod create mode 100644 main.go diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..7783fb1 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,25 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/go +{ + "name": "Go", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/go:1-1.21-bullseye", + "features": { + "ghcr.io/guiyomh/features/gotestsum:0": {} + } + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "go version", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1820f7f --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gitea.likemath.ru/alex/gogrep + +go 1.21 diff --git a/main.go b/main.go new file mode 100644 index 0000000..dc413d1 --- /dev/null +++ b/main.go @@ -0,0 +1,100 @@ +package main + +import ( + "bufio" + "fmt" + "io/fs" + "log" + "os" + "path/filepath" + "regexp" +) + +const CHANNEL_BUFFERING = 10 + +type FileMatchData struct { + Path string + LineIndexes []int + Lines []string +} + +func ProcessSingleFile(re_pattern regexp.Regexp, path string, out chan FileMatchData) error { + file, err := os.Open(path) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + res := FileMatchData{Path: path, LineIndexes: make([]int, 0), Lines: make([]string, 0)} + scanner := bufio.NewScanner(file) + // optionally, resize scanner's capacity for lines over 64K, see next example + cur_line_ind := 1 + for scanner.Scan() { + line_text := scanner.Text() + if re_pattern.FindString(line_text) != "" { + res.LineIndexes = append(res.LineIndexes, cur_line_ind) + res.Lines = append(res.Lines, line_text) + } + cur_line_ind++ + } + + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + out <- res + return nil +} + +func main() { + path_pattern := "git/hook" + re_path_pattern, err := regexp.Compile(path_pattern) + if err != nil { + fmt.Printf("Unable to compile path pattern Regexp: %v\n", path_pattern) + return + } + + text_pattern := "the commit" + re_text_pattern, err := regexp.Compile(text_pattern) + if err != nil { + fmt.Printf("Unable to compile text pattern Regexp: %v\n", text_pattern) + return + } + processed_channel := make(chan FileMatchData, CHANNEL_BUFFERING) + total_files := 0 + err = filepath.Walk(".", func(path string, info fs.FileInfo, err error) error { + if err != nil { + fmt.Printf("prevent panic by handling failure accessing a path %q: %v\n", path, err) + return err + } + if re_path_pattern.FindString(path) == "" { + return nil + } + // if info.IsDir() && info.Name() == subDirToSkip { + // fmt.Printf("skipping a dir without errors: %+v \n", info.Name()) + // return filepath.SkipDir + // } + if info.IsDir() { + return nil + } + go ProcessSingleFile(*re_text_pattern, path, processed_channel) + total_files++ + + return nil + }) + for ; total_files > 0; total_files-- { + cur_processed := <-processed_channel + if len(cur_processed.Lines) == 0 { + continue + } + fmt.Printf("%s:\n", cur_processed.Path) + for i := 0; i < len(cur_processed.Lines); i++ { + fmt.Printf("%d:%s\n", cur_processed.LineIndexes[i], cur_processed.Lines[i]) + } + fmt.Print("\n") + } + + if err != nil { + fmt.Printf("error walking the path %q: %v\n", path_pattern, err) + return + } +}