options.go (sift-0.8.0) | : | options.go (sift-0.9.0) | ||
---|---|---|---|---|
skipping to change at line 43 | skipping to change at line 43 | |||
"golang.org/x/crypto/ssh/terminal" | "golang.org/x/crypto/ssh/terminal" | |||
) | ) | |||
type Options struct { | type Options struct { | |||
BinarySkip bool `long:"binary-skip" description:"skip files th at seem to be binary"` | BinarySkip bool `long:"binary-skip" description:"skip files th at seem to be binary"` | |||
BinaryAsText bool `short:"a" long:"binary-text" description:"pro cess files that seem to be binary as text"` | BinaryAsText bool `short:"a" long:"binary-text" description:"pro cess files that seem to be binary as text"` | |||
Blocksize string `long:"blocksize" description:"blocksize in by tes (with optional suffix K|M)"` | Blocksize string `long:"blocksize" description:"blocksize in by tes (with optional suffix K|M)"` | |||
Color string | Color string | |||
ColorFunc func() `long:"color" description:"enable colored ou tput (default: auto)" json:"-"` | ColorFunc func() `long:"color" description:"enable colored ou tput (default: auto)" json:"-"` | |||
NoColorFunc func() `long:"no-color" description:"disable colore d output" json:"-"` | NoColorFunc func() `long:"no-color" description:"disable colore d output" json:"-"` | |||
ConfigFile string `long:"conf" description:"load config file F ILE" value-name:"FILE" json:"-"` | ||||
Context int `short:"C" long:"context" description:"show NUM context lines" value-name:"NUM" json:"-"` | Context int `short:"C" long:"context" description:"show NUM context lines" value-name:"NUM" json:"-"` | |||
ContextAfter int `short:"A" long:"context-after" description: "show NUM context lines after match" value-name:"NUM" json:"-"` | ContextAfter int `short:"A" long:"context-after" description: "show NUM context lines after match" value-name:"NUM" json:"-"` | |||
ContextBefore int `short:"B" long:"context-before" description :"show NUM context lines before match" value-name:"NUM" json:"-"` | ContextBefore int `short:"B" long:"context-before" description :"show NUM context lines before match" value-name:"NUM" json:"-"` | |||
Cores int `short:"j" long:"cores" description:"limit u sed CPU Cores (default: 0 = all)" default-mask:"-"` | Cores int `short:"j" long:"cores" description:"limit u sed CPU Cores (default: 0 = all)" default-mask:"-"` | |||
Count bool `short:"c" long:"count" description:"print c ount of matches per file" json:"-"` | Count bool `short:"c" long:"count" description:"print c ount of matches per file" json:"-"` | |||
IncludeDirs []string `long:"dirs" description:"recurse only into directories whose name matches GLOB" value-name:"GLOB" default-mask:"-"` | IncludeDirs []string `long:"dirs" description:"recurse only into directories whose name matches GLOB" value-name:"GLOB" default-mask:"-"` | |||
ErrShowLineLength bool `long:"err-show-line-length" description:"sh ow all line length errors"` | ErrShowLineLength bool `long:"err-show-line-length" description:"sh ow all line length errors"` | |||
ErrSkipLineLength bool `long:"err-skip-line-length" description:"sk ip line length errors"` | ErrSkipLineLength bool `long:"err-skip-line-length" description:"sk ip line length errors"` | |||
ExcludeDirs []string `long:"exclude-dirs" description:"do not rec urse into directories whose name matches GLOB" value-name:"GLOB" default-mask:"- "` | ExcludeDirs []string `long:"exclude-dirs" description:"do not rec urse into directories whose name matches GLOB" value-name:"GLOB" default-mask:"- "` | |||
IncludeExtensions string `short:"x" long:"ext" description:"limit sea rch to specific file extensions (comma-separated)" default-mask:"-"` | IncludeExtensions string `short:"x" long:"ext" description:"limit sea rch to specific file extensions (comma-separated)" default-mask:"-"` | |||
ExcludeExtensions string `short:"X" long:"exclude-ext" description:"e xclude specific file extensions (comma-separated)" default-mask:"-"` | ExcludeExtensions string `short:"X" long:"exclude-ext" description:"e xclude specific file extensions (comma-separated)" default-mask:"-"` | |||
IncludeFiles []string `long:"files" description:"search only files whose name matches GLOB" value-name:"GLOB" default-mask:"-"` | IncludeFiles []string `long:"files" description:"search only files whose name matches GLOB" value-name:"GLOB" default-mask:"-"` | |||
ExcludeFiles []string `long:"exclude-files" description:"do not se lect files whose name matches GLOB while recursing" value-name:"GLOB" default-ma sk:"-"` | ExcludeFiles []string `long:"exclude-files" description:"do not se lect files whose name matches GLOB while recursing" value-name:"GLOB" default-ma sk:"-"` | |||
IncludePath string `long:"path" description:"search only files whose path matches PATTERN" value-name:"PATTERN" default-mask:"-"` | IncludePath string `long:"path" description:"search only files whose path matches PATTERN" value-name:"PATTERN" default-mask:"-"` | |||
IncludeIPath string `long:"ipath" description:"search only files whose path matches PATTERN (case insensitive)" value-name:"PATTERN" default-mas k:"-"` | IncludeIPath string `long:"ipath" description:"search only files whose path matches PATTERN (case insensitive)" value-name:"PATTERN" default-mas k:"-"` | |||
ExcludePath string `long:"exclude-path" description:"do not sea rch files whose path matches PATTERN" value-name:"PATTERN" default-mask:"-"` | ExcludePath string `long:"exclude-path" description:"do not sea rch files whose path matches PATTERN" value-name:"PATTERN" default-mask:"-"` | |||
ExcludeIPath string `long:"exclude-ipath" description:"do not se arch files whose path matches PATTERN (case insensitive)" value-name:"PATTERN" d efault-mask:"-"` | ExcludeIPath string `long:"exclude-ipath" description:"do not se arch files whose path matches PATTERN (case insensitive)" value-name:"PATTERN" d efault-mask:"-"` | |||
IncludeTypes string `short:"t" long:"type" description:"limit se arch to specific file types (comma-separated, see --list-types)" default-mask:"- "` | IncludeTypes string `short:"t" long:"type" description:"limit se arch to specific file types (comma-separated, see --list-types)" default-mask:"- "` | |||
ExcludeTypes string `short:"T" long:"no-type" description:"exclu | ExcludeTypes string `short:"T" long:"no-type" description:"exclu | |||
de specific file types (comma-separated, --list-types)" default-mask:"-"` | de specific file types (comma-separated, see --list-types)" default-mask:"-"` | |||
AddCustomTypes []string `long:"add-type" description:"add custom typ | ||||
e (see --list-types for format)" default-mask:"-" json:"-"` | ||||
DelCustomTypes []string `long:"del-type" description:"remove custom | ||||
type" default-mask:"-" json:"-"` | ||||
CustomTypes map[string]string | ||||
FieldSeparator string `long:"field-sep" description:"column separa | ||||
tor (default: \":\")" default-mask:"-"` | ||||
FilesWithMatches bool `short:"l" long:"files-with-matches" descrip tion:"list files containing matches"` | FilesWithMatches bool `short:"l" long:"files-with-matches" descrip tion:"list files containing matches"` | |||
FilesWithoutMatch bool `short:"L" long:"files-without-match" descri ption:"list files containing no match"` | FilesWithoutMatch bool `short:"L" long:"files-without-match" descri ption:"list files containing no match"` | |||
FollowSymlinks bool `long:"follow" description:"follow symlinks" ` | FollowSymlinks bool `long:"follow" description:"follow symlinks" ` | |||
Git bool `long:"git" description:"respect .gitignore files and skip .git directories"` | Git bool `long:"git" description:"respect .gitignore files and skip .git directories"` | |||
GroupByFile bool `long:"group" description:"group output by f ile (default: off)"` | GroupByFile bool `long:"group" description:"group output by f ile (default: off)"` | |||
NoGroupByFile func() `long:"no-group" description:"do not group o utput by file" json:"-"` | NoGroupByFile func() `long:"no-group" description:"do not group o utput by file" json:"-"` | |||
IgnoreCase bool `short:"i" long:"ignore-case" description:"c ase insensitive (default: off)"` | IgnoreCase bool `short:"i" long:"ignore-case" description:"c ase insensitive (default: off)"` | |||
NoIgnoreCase func() `short:"I" long:"no-ignore-case" description :"disable case insensitive" json:"-"` | NoIgnoreCase func() `short:"I" long:"no-ignore-case" description :"disable case insensitive" json:"-"` | |||
SmartCase bool `short:"s" long:"smart-case" description:"ca se insensitive unless pattern contains uppercase characters (default: off)"` | SmartCase bool `short:"s" long:"smart-case" description:"ca se insensitive unless pattern contains uppercase characters (default: off)"` | |||
NoSmartCase func() `short:"S" long:"no-smart-case" description: "disable smart case" json:"-"` | NoSmartCase func() `short:"S" long:"no-smart-case" description: "disable smart case" json:"-"` | |||
skipping to change at line 97 | skipping to change at line 102 | |||
Recursive bool `short:"r" long:"recursive" description:"rec urse into directories (default: on)"` | Recursive bool `short:"r" long:"recursive" description:"rec urse into directories (default: on)"` | |||
NoRecursive func() `short:"R" long:"no-recursive" description:" do not recurse into directories" json:"-"` | NoRecursive func() `short:"R" long:"no-recursive" description:" do not recurse into directories" json:"-"` | |||
Replace string `long:"replace" description:"replace numbere d or named (?P<name>pattern) capture groups. Use ${1}, ${2}, $name, ... for capt ured submatches" json:"-"` | Replace string `long:"replace" description:"replace numbere d or named (?P<name>pattern) capture groups. Use ${1}, ${2}, $name, ... for capt ured submatches" json:"-"` | |||
ShowFilename string | ShowFilename string | |||
ShowFilenameFunc func() `long:"filename" description:"enforce printing the filename before results (default: auto)" json:"-"` | ShowFilenameFunc func() `long:"filename" description:"enforce printing the filename before results (default: auto)" json:"-"` | |||
NoShowFilenameFunc func() `long:"no-filename" description:"disable print ing the filename before results" json:"-"` | NoShowFilenameFunc func() `long:"no-filename" description:"disable print ing the filename before results" json:"-"` | |||
ShowLineNumbers bool `short:"n" long:"line-number" description:"sho w line numbers (default: off)"` | ShowLineNumbers bool `short:"n" long:"line-number" description:"sho w line numbers (default: off)"` | |||
NoShowLineNumbers func() `short:"N" long:"no-line-number" description:" do not show line numbers" json:"-"` | NoShowLineNumbers func() `short:"N" long:"no-line-number" description:" do not show line numbers" json:"-"` | |||
ShowColumnNumbers bool `long:"column" description:"show column number s"` | ShowColumnNumbers bool `long:"column" description:"show column number s"` | |||
NoShowColumnNumbers func() `long:"no-column" description:"do not show col umn numbers" json:"-"` | NoShowColumnNumbers func() `long:"no-column" description:"do not show col umn numbers" json:"-"` | |||
ShowByteOffset bool `long:"byte-offset" description:"show the byte | ||||
offset before each output line"` | ||||
NoShowByteOffset func() `long:"no-byte-offset" description:"do not sho | ||||
w the byte offset before each output line" json:"-"` | ||||
Stats bool `long:"stats" description:"show statistics"` | Stats bool `long:"stats" description:"show statistics"` | |||
TargetsOnly bool `long:"targets" description:"only list selecte d files, do not search"` | TargetsOnly bool `long:"targets" description:"only list selecte d files, do not search"` | |||
ListTypes func() `long:"list-types" description:"list available file types" json:"-" default-mask:"-"` | ListTypes bool `long:"list-types" description:"list available file types" json:"-" default-mask:"-"` | |||
Version func() `short:"V" long:"version" description:"show ve rsion and license information" json:"-"` | Version func() `short:"V" long:"version" description:"show ve rsion and license information" json:"-"` | |||
WordRegexp bool `short:"w" long:"word-regexp" description:"onl y match on ASCII word boundaries"` | WordRegexp bool `short:"w" long:"word-regexp" description:"onl y match on ASCII word boundaries"` | |||
WriteConfig bool `long:"write-config" description:"save config for loaded configs + given command line arguments" json:"-"` | WriteConfig bool `long:"write-config" description:"save config for loaded configs + given command line arguments" json:"-"` | |||
Zip bool `short:"z" long:"zip" description:"search cont ent of compressed .gz files (default: off)"` | Zip bool `short:"z" long:"zip" description:"search cont ent of compressed .gz files (default: off)"` | |||
NoZip func() `short:"Z" long:"no-zip" description:"do not s earch content of compressed .gz files" json:"-"` | NoZip func() `short:"Z" long:"no-zip" description:"do not s earch content of compressed .gz files" json:"-"` | |||
FileConditions struct { | FileConditions struct { | |||
FileMatches []string `long:"file-matches" description:"only s how matches if file also matches PATTERN" value-name:"PATTERN"` | FileMatches []string `long:"file-matches" description:"only s how matches if file also matches PATTERN" value-name:"PATTERN"` | |||
LineMatches []string `long:"line-matches" description:"only s how matches if line NUM matches PATTERN" value-name:"NUM:PATTERN"` | LineMatches []string `long:"line-matches" description:"only s how matches if line NUM matches PATTERN" value-name:"NUM:PATTERN"` | |||
RangeMatches []string `long:"range-matches" description:"only show matches if lines X-Y match PATTERN" value-name:"X:Y:PATTERN"` | RangeMatches []string `long:"range-matches" description:"only show matches if lines X-Y match PATTERN" value-name:"X:Y:PATTERN"` | |||
skipping to change at line 170 | skipping to change at line 177 | |||
confpath := filepath.Join(path, SiftConfigFile) | confpath := filepath.Join(path, SiftConfigFile) | |||
if _, err := os.Stat(confpath); err == nil { | if _, err := os.Stat(confpath); err == nil { | |||
return confpath | return confpath | |||
} | } | |||
lp = path | lp = path | |||
path = filepath.Dir(path) | path = filepath.Dir(path) | |||
} | } | |||
return "" | return "" | |||
} | } | |||
// func listTypes list the available types (built-in and custom) and exits. | ||||
func listTypes() { | ||||
fmt.Println("The following list shows all file types supported.") | ||||
fmt.Println("Use --type/--no-type to include/exclude file types.") | ||||
fmt.Println("") | ||||
var types []string | ||||
for t := range global.fileTypesMap { | ||||
types = append(types, t) | ||||
} | ||||
sort.Strings(types) | ||||
for _, e := range types { | ||||
t := global.fileTypesMap[e] | ||||
var shebang string | ||||
if t.ShebangRegex != nil { | ||||
shebang = fmt.Sprintf("or first line matches /%s/", t.She | ||||
bangRegex) | ||||
} | ||||
fmt.Printf("%-15s:%s %s\n", e, strings.Join(t.Patterns, " "), she | ||||
bang) | ||||
} | ||||
fmt.Println("") | ||||
fmt.Println(`Custom types can be added with --add-type.`) | ||||
fmt.Println(`Example matching *.rb, *.erb, Rakefile and all files whose f | ||||
irst line matches the regular expression /\bruby\b/:`) | ||||
fmt.Println(`sift --add-type 'ruby=*.rb,*.erb,Rakefile;\bruby\b'`) | ||||
fmt.Println(`Write the definition to the config file:`) | ||||
fmt.Println(`sift --add-type 'ruby=*.rb,*.erb,Rakefile;\bruby\b' --write- | ||||
config`) | ||||
fmt.Println(`Remove the definition from the config file:`) | ||||
fmt.Println(`sift --del-type ruby --write-config`) | ||||
fmt.Println("") | ||||
os.Exit(0) | ||||
} | ||||
// LoadDefaults sets default options. | // LoadDefaults sets default options. | |||
func (o *Options) LoadDefaults() { | func (o *Options) LoadDefaults() { | |||
o.Cores = runtime.NumCPU() | o.Cores = runtime.NumCPU() | |||
o.OutputSeparator = "" | o.OutputSeparator = "" | |||
o.FieldSeparator = ":" | ||||
o.ShowFilename = "auto" | o.ShowFilename = "auto" | |||
o.Color = "auto" | o.Color = "auto" | |||
o.Recursive = true | o.Recursive = true | |||
o.CustomTypes = make(map[string]string) | ||||
o.ColorFunc = func() { | o.ColorFunc = func() { | |||
o.Color = "on" | o.Color = "on" | |||
} | } | |||
o.NoColorFunc = func() { | o.NoColorFunc = func() { | |||
o.Color = "off" | o.Color = "off" | |||
} | } | |||
o.NoIgnoreCase = func() { | o.NoIgnoreCase = func() { | |||
o.IgnoreCase = false | o.IgnoreCase = false | |||
} | } | |||
skipping to change at line 211 | skipping to change at line 250 | |||
} | } | |||
o.NoShowFilenameFunc = func() { | o.NoShowFilenameFunc = func() { | |||
o.ShowFilename = "off" | o.ShowFilename = "off" | |||
} | } | |||
o.NoShowLineNumbers = func() { | o.NoShowLineNumbers = func() { | |||
o.ShowLineNumbers = false | o.ShowLineNumbers = false | |||
} | } | |||
o.NoShowColumnNumbers = func() { | o.NoShowColumnNumbers = func() { | |||
o.ShowColumnNumbers = false | o.ShowColumnNumbers = false | |||
} | } | |||
o.NoShowByteOffset = func() { | ||||
o.ShowByteOffset = false | ||||
} | ||||
o.NoZip = func() { | o.NoZip = func() { | |||
o.Zip = false | o.Zip = false | |||
} | } | |||
o.Version = func() { | o.Version = func() { | |||
fmt.Printf("sift %s (%s/%s)\n", SiftVersion, runtime.GOOS, runtim e.GOARCH) | fmt.Printf("sift %s (%s/%s)\n", SiftVersion, runtime.GOOS, runtim e.GOARCH) | |||
fmt.Println("Copyright (C) 2014-2016 Sven Taute") | fmt.Println("Copyright (C) 2014-2016 Sven Taute") | |||
fmt.Println("") | fmt.Println("") | |||
fmt.Println("This program is free software: you can redistribute it and/or modify") | fmt.Println("This program is free software: you can redistribute it and/or modify") | |||
fmt.Println("it under the terms of the GNU General Public License as published by") | fmt.Println("it under the terms of the GNU General Public License as published by") | |||
fmt.Println("the Free Software Foundation, version 3 of the Licen se.") | fmt.Println("the Free Software Foundation, version 3 of the Licen se.") | |||
fmt.Println("") | fmt.Println("") | |||
fmt.Println("This program is distributed in the hope that it will be useful,") | fmt.Println("This program is distributed in the hope that it will be useful,") | |||
fmt.Println("but WITHOUT ANY WARRANTY; without even the implied w arranty of") | fmt.Println("but WITHOUT ANY WARRANTY; without even the implied w arranty of") | |||
fmt.Println("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the") | fmt.Println("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the") | |||
fmt.Println("GNU General Public License for more details.") | fmt.Println("GNU General Public License for more details.") | |||
fmt.Println("") | fmt.Println("") | |||
fmt.Println("You should have received a copy of the GNU General P ublic License") | fmt.Println("You should have received a copy of the GNU General P ublic License") | |||
fmt.Println("along with this program. If not, see <http://www.gnu .org/licenses/>.") | fmt.Println("along with this program. If not, see <http://www.gnu .org/licenses/>.") | |||
os.Exit(0) | os.Exit(0) | |||
} | } | |||
} | ||||
o.ListTypes = func() { | // loadConfigFile loads options from the given config file. | |||
fmt.Println("The following list shows all file types supported.") | func (o *Options) loadConfigFile(configFilePath string, label string) { | |||
fmt.Println("Use --type/--no-type to include/exclude file types." | configFile, err := ioutil.ReadFile(configFilePath) | |||
) | if err == nil && len(configFile) > 0 { | |||
fmt.Println("") | if err := json.Unmarshal(configFile, &o); err != nil { | |||
var types []string | errorLogger.Printf("cannot parse %s '%s': %s\n", label, c | |||
for t := range global.fileTypesMap { | onfigFilePath, err) | |||
types = append(types, t) | ||||
} | ||||
sort.Strings(types) | ||||
for _, e := range types { | ||||
t := global.fileTypesMap[e] | ||||
var shebang string | ||||
if t.ShebangRegex != nil { | ||||
shebang = fmt.Sprintf(" or first line matches /%s | ||||
/", t.ShebangRegex) | ||||
} | ||||
fmt.Printf("%-15s%s%s\n", t.Name+":", strings.Join(t.Patt | ||||
erns, " "), shebang) | ||||
} | } | |||
os.Exit(0) | } | |||
if err != nil { | ||||
errorLogger.Printf("cannot open %s '%s': %s\n", label, configFile | ||||
Path, err) | ||||
} | } | |||
} | } | |||
// LoadConfigs tries to load options from sift config files. | // LoadConfigs tries to load options from sift config files. | |||
func (o *Options) LoadConfigs() { | // if noConf is true, only a config file set via option --conf will be parsed. | |||
// load config from global sift config if file exists | func (o *Options) LoadConfigs(noConf bool, configFileArg string) { | |||
if homedir := getHomeDir(); homedir != "" { | if !noConf { | |||
configFilePath := filepath.Join(homedir, SiftConfigFile) | // load config from global sift config if file exists | |||
configFile, err := ioutil.ReadFile(configFilePath) | if homedir := getHomeDir(); homedir != "" { | |||
if err == nil && len(configFile) > 0 { | configFilePath := filepath.Join(homedir, SiftConfigFile) | |||
if err := json.Unmarshal(configFile, &o); err != nil { | if _, err := os.Stat(configFilePath); err == nil { | |||
errorLogger.Printf("cannot parse global config '% | o.loadConfigFile(configFilePath, "global config") | |||
s': %s\n", configFilePath, err) | ||||
} | } | |||
} | } | |||
} | ||||
// load config from local sift config if file exists | // load config from local sift config if file exists | |||
if configFilePath := findLocalConfig(); configFilePath != "" { | if configFilePath := findLocalConfig(); configFilePath != "" { | |||
configFile, err := ioutil.ReadFile(configFilePath) | if _, err := os.Stat(configFilePath); err == nil { | |||
if err == nil && len(configFile) > 0 { | o.loadConfigFile(configFilePath, "local config") | |||
if err := json.Unmarshal(configFile, &o); err != nil { | ||||
errorLogger.Printf("cannot parse local config '%s | ||||
': %s\n", configFilePath, err) | ||||
} | } | |||
} | } | |||
} | } | |||
// load config from config option | ||||
if configFileArg != "" { | ||||
o.loadConfigFile(configFileArg, "config") | ||||
} | ||||
} | } | |||
// Apply processes user provided options | // Apply processes user provided options | |||
func (o *Options) Apply(patterns []string, targets []string) error { | func (o *Options) Apply(patterns []string, targets []string) error { | |||
if err := o.processTypes(); err != nil { | ||||
return err | ||||
} | ||||
if err := o.checkFormats(); err != nil { | if err := o.checkFormats(); err != nil { | |||
return err | return err | |||
} | } | |||
if err := o.processConditions(); err != nil { | if err := o.processConditions(); err != nil { | |||
return err | return err | |||
} | } | |||
if err := o.checkCompatibility(patterns, targets); err != nil { | if err := o.checkCompatibility(patterns, targets); err != nil { | |||
return err | return err | |||
skipping to change at line 315 | skipping to change at line 356 | |||
} | } | |||
for i := range patterns { | for i := range patterns { | |||
patterns[i] = o.preparePattern(patterns[i]) | patterns[i] = o.preparePattern(patterns[i]) | |||
} | } | |||
runtime.GOMAXPROCS(o.Cores) | runtime.GOMAXPROCS(o.Cores) | |||
return nil | return nil | |||
} | } | |||
// processTypes processes custom types defined on the command line | ||||
// or in the config file. | ||||
func (o *Options) processTypes() error { | ||||
for _, e := range o.DelCustomTypes { | ||||
if _, ok := o.CustomTypes[e]; !ok { | ||||
return fmt.Errorf("No custom type definition for '%s' fou | ||||
nd", e) | ||||
} | ||||
delete(o.CustomTypes, e) | ||||
} | ||||
for _, e := range o.AddCustomTypes { | ||||
s := strings.SplitN(e, "=", 2) | ||||
if len(s) != 2 { | ||||
return fmt.Errorf("wrong format for type definition '%s'" | ||||
, e) | ||||
} | ||||
o.CustomTypes[s[0]] = s[1] | ||||
} | ||||
// parse type definition, e.g. '*.pl,*.pm;\bperl\b' | ||||
for name, e := range o.CustomTypes { | ||||
var ft FileType | ||||
s := strings.SplitN(e, ";", 2) | ||||
if len(s) == 2 && s[1] != "" { | ||||
re, err := regexp.Compile(s[1]) | ||||
if err != nil { | ||||
return fmt.Errorf("cannot parse regular expressio | ||||
n '%s' for custom type '%s': %s", s[1], name, err) | ||||
} | ||||
ft.ShebangRegex = re | ||||
} | ||||
patterns := strings.Split(s[0], ",") | ||||
ft.Patterns = patterns | ||||
global.fileTypesMap[name] = ft | ||||
} | ||||
if o.ListTypes { | ||||
listTypes() | ||||
} | ||||
return nil | ||||
} | ||||
// checkFormats checks options for illegal formats | // checkFormats checks options for illegal formats | |||
func (o *Options) checkFormats() error { | func (o *Options) checkFormats() error { | |||
if o.ExcludePath != "" { | if o.ExcludePath != "" { | |||
var err error | var err error | |||
global.excludeFilepathRegex, err = regexp.Compile(o.ExcludePath) | global.excludeFilepathRegex, err = regexp.Compile(o.ExcludePath) | |||
if err != nil { | if err != nil { | |||
return fmt.Errorf("cannot parse exclude filepath pattern '%s': %s\n", o.ExcludePath, err) | return fmt.Errorf("cannot parse exclude filepath pattern '%s': %s\n", o.ExcludePath, err) | |||
} | } | |||
} | } | |||
if o.ExcludeIPath != "" { | if o.ExcludeIPath != "" { | |||
End of changes. 17 change blocks. | ||||
40 lines changed or deleted | 131 lines changed or added |