From 2bf223751fd7c1a7266e82fe4723f7d31917d020 Mon Sep 17 00:00:00 2001 From: Paul Philion Date: Tue, 4 Jun 2024 16:43:56 -0700 Subject: [PATCH] adding file types and related options from ack3 --- .gitignore | 1 + file_types.go | 81 ++++++++++++++++++++++++++------------------------- mack.go | 45 ++++++++++++++++++++++++++-- option.go | 37 +++++++++++++++++------ 4 files changed, 114 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index 786321a..62ff142 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ pt !cmd/pt Godeps/_workspace/ main +.vscode/ diff --git a/file_types.go b/file_types.go index 0421694..a9c0093 100644 --- a/file_types.go +++ b/file_types.go @@ -5,45 +5,47 @@ type LanguageSpec struct { Exts []string } -var lang_spec = [...]LanguageSpec{ - {Name: "actionscript", Exts: []string{"as", "mxml"}}, - {Name: "ada", Exts: []string{"ada", "adb", "ads"}}, - {Name: "asciidoc", Exts: []string{"adoc", "ad", "asc", "asciidoc"}}, - {Name: "apl", Exts: []string{"apl"}}, - {Name: "asm", Exts: []string{"asm", "s"}}, - {Name: "asp", Exts: []string{"asp", "asa", "aspx", "asax", "ashx", "ascx", "asmx"}}, - {Name: "aspx", Exts: []string{"asp", "asa", "aspx", "asax", "ashx", "ascx", "asmx"}}, - {Name: "batch", Exts: []string{"bat", "cmd"}}, - {Name: "bazel", Exts: []string{"bazel"}}, - {Name: "bitbake", Exts: []string{"bb", "bbappend", "bbclass", "inc"}}, - {Name: "cc", Exts: []string{"c", "h", "xs"}}, - {Name: "cfmx", Exts: []string{"cfc", "cfm", "cfml"}}, - {Name: "chpl", Exts: []string{"chpl"}}, - {Name: "clojure", Exts: []string{"clj", "cljs", "cljc", "cljx", "edn"}}, - {Name: "coffee", Exts: []string{"coffee", "cjsx"}}, - {Name: "config", Exts: []string{"config"}}, - {Name: "coq", Exts: []string{"coq", "g", "v"}}, - {Name: "cpp", Exts: []string{"cpp", "cc", "C", "cxx", "m", "hpp", "hh", "h", "H", "hxx", "tpp"}}, - {Name: "crystal", Exts: []string{"cr", "ecr"}}, - {Name: "csharp", Exts: []string{"cs"}}, - {Name: "cshtml", Exts: []string{"cshtml"}}, - {Name: "css", Exts: []string{"css"}}, - {Name: "cython", Exts: []string{"pyx", "pxd", "pxi"}}, - {Name: "delphi", Exts: []string{"pas", "int", "dfm", "nfm", "dof", "dpk", "dpr", "dproj", "groupproj", "bdsgroup", "bdsproj"}}, - {Name: "dlang", Exts: []string{"d", "di"}}, - {Name: "dot", Exts: []string{"dot", "gv"}}, - {Name: "dts", Exts: []string{"dts", "dtsi"}}, - {Name: "ebuild", Exts: []string{"ebuild", "eclass"}}, - {Name: "elisp", Exts: []string{"el"}}, - {Name: "elixir", Exts: []string{"ex", "eex", "exs"}}, - {Name: "elm", Exts: []string{"elm"}}, - {Name: "erlang", Exts: []string{"erl", "hrl"}}, - {Name: "factor", Exts: []string{"factor"}}, - {Name: "fortran", Exts: []string{"f", "F", "f77", "f90", "F90", "f95", "f03", "for", "ftn", "fpp", "FPP"}}, - {Name: "fsharp", Exts: []string{"fs", "fsi", "fsx"}}, - {Name: "gettext", Exts: []string{"po", "pot", "mo"}}, - {Name: "glsl", Exts: []string{"vert", "tesc", "tese", "geom", "frag", "comp"}}, - {Name: "go", Exts: []string{"go"}}, +// borrowed from https://github.com/ggreer/the_silver_searcher/blob/a61f1780b64266587e7bc30f0f5f71c6cca97c0f/src/lang.c +var lang_spec = map[string]LanguageSpec{ + "actionscript": {Name: "actionscript", Exts: []string{"as", "mxml"}}, + "ada": {Name: "ada", Exts: []string{"ada", "adb", "ads"}}, + "asciidoc": {Name: "asciidoc", Exts: []string{"adoc", "ad", "asc", "asciidoc"}}, + "apl": {Name: "apl", Exts: []string{"apl"}}, + "asm": {Name: "asm", Exts: []string{"asm", "s"}}, + "asp": {Name: "asp", Exts: []string{"asp", "asa", "aspx", "asax", "ashx", "ascx", "asmx"}}, + "aspx": {Name: "aspx", Exts: []string{"asp", "asa", "aspx", "asax", "ashx", "ascx", "asmx"}}, + "batch": {Name: "batch", Exts: []string{"bat", "cmd"}}, + "bazel": {Name: "bazel", Exts: []string{"bazel"}}, + "bitbake": {Name: "bitbake", Exts: []string{"bb", "bbappend", "bbclass", "inc"}}, + "cc": {Name: "cc", Exts: []string{"c", "h", "xs"}}, + "cfmx": {Name: "cfmx", Exts: []string{"cfc", "cfm", "cfml"}}, + "chpl": {Name: "chpl", Exts: []string{"chpl"}}, + "clojure": {Name: "clojure", Exts: []string{"clj", "cljs", "cljc", "cljx", "edn"}}, + "coffee": {Name: "coffee", Exts: []string{"coffee", "cjsx"}}, + "config": {Name: "config", Exts: []string{"config"}}, + "coq": {Name: "coq", Exts: []string{"coq", "g", "v"}}, + "cpp": {Name: "cpp", Exts: []string{"cpp", "cc", "C", "cxx", "m", "hpp", "hh", "h", "H", "hxx", "tpp"}}, + "crystal": {Name: "crystal", Exts: []string{"cr", "ecr"}}, + "csharp": {Name: "csharp", Exts: []string{"cs"}}, + "cshtml": {Name: "cshtml", Exts: []string{"cshtml"}}, + "css": {Name: "css", Exts: []string{"css"}}, + "cython": {Name: "cython", Exts: []string{"pyx", "pxd", "pxi"}}, + "delphi": {Name: "delphi", Exts: []string{"pas", "int", "dfm", "nfm", "dof", "dpk", "dpr", "dproj", "groupproj", "bdsgroup", "bdsproj"}}, + "dlang": {Name: "dlang", Exts: []string{"d", "di"}}, + "dot": {Name: "dot", Exts: []string{"dot", "gv"}}, + "dts": {Name: "dts", Exts: []string{"dts", "dtsi"}}, + "ebuild": {Name: "ebuild", Exts: []string{"ebuild", "eclass"}}, + "elisp": {Name: "elisp", Exts: []string{"el"}}, + "elixir": {Name: "elixir", Exts: []string{"ex", "eex", "exs"}}, + "elm": {Name: "elm", Exts: []string{"elm"}}, + "erlang": {Name: "erlang", Exts: []string{"erl", "hrl"}}, + "factor": {Name: "factor", Exts: []string{"factor"}}, + "fortran": {Name: "fortran", Exts: []string{"f", "F", "f77", "f90", "F90", "f95", "f03", "for", "ftn", "fpp", "FPP"}}, + "fsharp": {Name: "fsharp", Exts: []string{"fs", "fsi", "fsx"}}, + "gettext": {Name: "gettext", Exts: []string{"po", "pot", "mo"}}, + "glsl": {Name: "glsl", Exts: []string{"vert", "tesc", "tese", "geom", "frag", "comp"}}, + "go": {Name: "go", Exts: []string{"go"}}, + /* fixme {Name: "gradle", Exts: []string{"gradle"}}, {Name: "groovy", Exts: []string{"groovy", "gtmpl", "gpp", "grunit", "gradle"}}, {Name: "haml", Exts: []string{"haml"}}, @@ -144,4 +146,5 @@ var lang_spec = [...]LanguageSpec{ {Name: "yaml", Exts: []string{"yaml", "yml"}}, {Name: "zeek", Exts: []string{"zeek", "bro", "bif"}}, {Name: "zephir", Exts: []string{"zep"}}, + */ } diff --git a/mack.go b/mack.go index b0f583e..f6a1c31 100644 --- a/mack.go +++ b/mack.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "github.com/jessevdk/go-flags" "github.com/monochromegane/conflag" @@ -44,10 +45,11 @@ func (p MarkdownAck) Run(args []string) int { args, err := parser.ParseArgs(args) if err != nil { + fmt.Fprintf(p.Err, "ERROR %s\n", err) + if ferr, ok := err.(*flags.Error); ok && ferr.Type == flags.ErrHelp { return ExitCodeOK } - fmt.Printf("ERROR %s\n", err) return ExitCodeError } @@ -56,7 +58,46 @@ func (p MarkdownAck) Run(args []string) int { return ExitCodeOK } - if len(args) == 0 && !opts.SearchOption.EnableFilesWithRegexp { + if opts.FileTypeOption.ListTypes { + for _, element := range lang_spec { + // place-holder + fmt.Printf(" %s: %s\n", element.Name, strings.Join(element.Exts, ", ")) + } + return ExitCodeOK + } + + if len(opts.FileTypeOption.FileType) > 0 { + // got filetype option, gather all extentions + opts.FileTypeOption.ExtSet = make(map[string]bool) + for _, ftype := range opts.FileTypeOption.FileType { + if spec, ok := lang_spec[ftype]; ok { + + for _, ext := range spec.Exts { + opts.FileTypeOption.ExtSet[ext] = true + } + } + } + + builder := strings.Builder{} + builder.WriteString(".*\\.(") + for ext := range opts.FileTypeOption.ExtSet { + builder.WriteString(ext) + builder.WriteString("|") + } + regex_str := builder.String() // convert to string + regex_str = regex_str[:len(regex_str)-1] // strip trailing '|' + regex_str += ")$" + + if opts.SearchOption.FileNamesOnly { + opts.SearchOption.EnableFilesWithRegexp = true + opts.SearchOption.PatternFilesWithRegexp = regex_str + } else { + opts.SearchOption.FileSearchRegexp = regex_str + } + } + + if len(args) == 0 && !(opts.SearchOption.EnableFilesWithRegexp) { + fmt.Printf("No regular expression found.\n") parser.WriteHelp(p.Err) return ExitCodeError } diff --git a/option.go b/option.go index 0d8e88f..aed12a3 100644 --- a/option.go +++ b/option.go @@ -6,9 +6,10 @@ import ( // Top level options type Option struct { - Version bool `long:"version" description:"Show version"` - OutputOption *OutputOption `group:"Output Options"` - SearchOption *SearchOption `group:"Search Options"` + Version bool `long:"version" description:"Show version"` + OutputOption *OutputOption `group:"Output Options"` + SearchOption *SearchOption `group:"Search Options"` + FileTypeOption *FileTypeOption `group:"File Type Options"` } // Output options. @@ -116,12 +117,13 @@ type SearchOption struct { GlobalGitIgnore bool `long:"global-gitignore" description:"Use git's global gitignore file for ignore patterns"` HomePtIgnore bool `long:"home-ptignore" description:"Use $Home/.ptignore file for ignore patterns"` SkipVcsIgnore bool `short:"U" long:"skip-vcs-ignores" description:"Don't use VCS ignore file for ignore patterns"` + FileNamesOnly bool `short:"f" description:"Only print the files selected, without searching. The PATTERN must not be specified."` FilesWithRegexp func(string) `short:"g" description:"Print filenames matching PATTERN"` EnableFilesWithRegexp bool // Enable files with regexp. Not user option. PatternFilesWithRegexp string // Pattern files with regexp. Not user option. FileSearchRegexp string `short:"G" long:"file-search-regexp" description:"PATTERN Limit search to filenames matching PATTERN"` Depth int `long:"depth" default:"25" description:"Search up to NUM directories deep"` - Follow bool `short:"f" long:"follow" description:"Follow symlinks"` + Follow bool `long:"follow" description:"Follow symlinks"` Hidden bool `long:"hidden" description:"Search hidden files and directories"` SearchStream bool // Input from pipe. Not user option. MarkdownQuery bool `short:"m" description:"Parse PATTERN as a Markdown query against MD files"` @@ -140,15 +142,32 @@ func newSearchOption() *SearchOption { return opt } -func newOptionParser(opts *Option) *flags.Parser { - output := flags.NewNamedParser("mack", flags.Default) - output.AddGroup("Output Options", "", &OutputOption{}) +type FileTypeOption struct { + //-t X, --type=X Include only X files, where X is a filetype, e.g. python, html, markdown, etc + FileType []string `short:"t" long:"type" description:"Include only X files, where X is a filetype, e.g. python, html, markdown, etc"` + + //-T X, --type=noX Exclude X files, where X is a filetype. + //ExcludeType []string `short:"T" long:"not-type" description:"Exclude X files, where X is a filetype."` + // SKIPPING for now + + //-k, --known-types Include only files of types that ack recognizes. + KnownTypes bool `short:"k" long:"known-types" description:"Include only files of types that mack recognizes."` - search := flags.NewNamedParser("mack", flags.Default) - search.AddGroup("Search Options", "", &SearchOption{}) + //--help-types Display all known types, and how they're defined. + ListTypes bool `long:"help-types" description:"Display all known types, and how they're defined."` + + ExtSet map[string]bool // private, to store all the interesting file name regexes. +} +func newFileTypeOption() *FileTypeOption { + opt := &FileTypeOption{} + return opt +} + +func newOptionParser(opts *Option) *flags.Parser { opts.OutputOption = newOutputOption() opts.SearchOption = newSearchOption() + opts.FileTypeOption = newFileTypeOption() parser := flags.NewParser(opts, flags.Default) parser.Name = "mack"