summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core.go4
-rw-r--r--src/options.go65
-rw-r--r--src/reader.go24
3 files changed, 83 insertions, 10 deletions
diff --git a/src/core.go b/src/core.go
index 56a2198e..3abda89c 100644
--- a/src/core.go
+++ b/src/core.go
@@ -117,7 +117,7 @@ func Run(opts *Options, version string, revision string) {
reader = NewReader(func(data []byte) bool {
return chunkList.Push(data)
}, eventBox, opts.ReadZero, opts.Filter == nil)
- go reader.ReadSource()
+ go reader.ReadSource(opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
}
// Matcher
@@ -165,7 +165,7 @@ func Run(opts *Options, version string, revision string) {
}
return false
}, eventBox, opts.ReadZero, false)
- reader.ReadSource()
+ reader.ReadSource(opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
} else {
eventBox.Unwatch(EvtReadNew)
eventBox.WaitFor(EvtReadFin)
diff --git a/src/options.go b/src/options.go
index 84e1c888..fdad058d 100644
--- a/src/options.go
+++ b/src/options.go
@@ -124,6 +124,12 @@ const usage = `usage: fzf [options]
(To allow remote process execution, use --listen-unsafe)
--version Display version information and exit
+ Directory traversal (Only used when $FZF_DEFAULT_COMMAND is not set)
+ --walker=OPTS [file][,dir][,follow][,hidden] (default: file,follow,hidden)
+ --walker-root=DIR Root directory from which to start walker (default: .)
+ --walker-skip=DIRS Comma-separated list of directory names to skip
+ (default: .git,node_modules)
+
Environment variables
FZF_DEFAULT_COMMAND Default command to use when input is tty
FZF_DEFAULT_OPTS Default options (e.g. '--layout=reverse --info=inline')
@@ -274,6 +280,13 @@ func firstLine(s string) string {
return strings.SplitN(s, "\n", 2)[0]
}
+type walkerOpts struct {
+ file bool
+ dir bool
+ hidden bool
+ follow bool
+}
+
// Options stores the values of command-line options
type Options struct {
Fuzzy bool
@@ -342,9 +355,22 @@ type Options struct {
ListenAddr *listenAddress
Unsafe bool
ClearOnExit bool
+ WalkerOpts walkerOpts
+ WalkerRoot string
+ WalkerSkip []string
Version bool
}
+func filterNonEmpty(input []string) []string {
+ output := make([]string, 0, len(input))
+ for _, str := range input {
+ if len(str) > 0 {
+ output = append(output, str)
+ }
+ }
+ return output
+}
+
func defaultPreviewOpts(command string) previewOpts {
return previewOpts{command, posRight, sizeSpec{50, true}, "", false, false, false, false, tui.DefaultBorderShape, 0, 0, nil}
}
@@ -413,6 +439,9 @@ func defaultOptions() *Options {
PreviewLabel: labelOpts{},
Unsafe: false,
ClearOnExit: true,
+ WalkerOpts: walkerOpts{file: true, hidden: true, follow: true},
+ WalkerRoot: ".",
+ WalkerSkip: []string{".git", "node_modules"},
Version: false}
}
@@ -966,6 +995,30 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) *tui.ColorTheme {
return theme
}
+func parseWalkerOpts(str string) walkerOpts {
+ opts := walkerOpts{}
+ for _, str := range strings.Split(strings.ToLower(str), ",") {
+ switch str {
+ case "file":
+ opts.file = true
+ case "dir":
+ opts.dir = true
+ case "hidden":
+ opts.hidden = true
+ case "follow":
+ opts.follow = true
+ case "":
+ // Ignored
+ default:
+ errorExit("invalid walker option: " + str)
+ }
+ }
+ if !opts.file && !opts.dir {
+ errorExit("at least one of 'file' or 'dir' should be specified")
+ }
+ return opts
+}
+
var (
executeRegexp *regexp.Regexp
splitRegexp *regexp.Regexp
@@ -1880,6 +1933,12 @@ func parseOptions(opts *Options, allArgs []string) {
opts.ClearOnExit = true
case "--no-clear":
opts.ClearOnExit = false
+ case "--walker":
+ opts.WalkerOpts = parseWalkerOpts(nextString(allArgs, &i, "walker options required [file][,dir][,follow][,hidden]"))
+ case "--walker-root":
+ opts.WalkerRoot = nextString(allArgs, &i, "directory required")
+ case "--walker-skip":
+ opts.WalkerSkip = filterNonEmpty(strings.Split(nextString(allArgs, &i, "directory names to ignore required"), ","))
case "--version":
opts.Version = true
case "--":
@@ -1977,6 +2036,12 @@ func parseOptions(opts *Options, allArgs []string) {
}
opts.ListenAddr = &addr
opts.Unsafe = true
+ } else if match, value := optString(arg, "--walker="); match {
+ opts.WalkerOpts = parseWalkerOpts(value)
+ } else if match, value := optString(arg, "--walker-root="); match {
+ opts.WalkerRoot = value
+ } else if match, value := optString(arg, "--walker-skip="); match {
+ opts.WalkerSkip = filterNonEmpty(strings.Split(value, ","))
} else if match, value := optString(arg, "--hscroll-off="); match {
opts.HscrollOff = atoi(value)
} else if match, value := optString(arg, "--scroll-off="); match {
diff --git a/src/reader.go b/src/reader.go
index fb45c7b9..47102ec1 100644
--- a/src/reader.go
+++ b/src/reader.go
@@ -93,13 +93,13 @@ func (r *Reader) restart(command string, environ []string) {
}
// ReadSource reads data from the default command or from standard input
-func (r *Reader) ReadSource() {
+func (r *Reader) ReadSource(root string, opts walkerOpts, ignores []string) {
r.startEventPoller()
var success bool
if util.IsTty() {
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
if len(cmd) == 0 {
- success = r.readFiles()
+ success = r.readFiles(root, opts, ignores)
} else {
// We can't export FZF_* environment variables to the default command
success = r.readFromCommand(cmd, nil)
@@ -145,9 +145,9 @@ func (r *Reader) readFromStdin() bool {
return true
}
-func (r *Reader) readFiles() bool {
+func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string) bool {
r.killed = false
- conf := fastwalk.Config{Follow: true}
+ conf := fastwalk.Config{Follow: opts.follow}
fn := func(path string, de os.DirEntry, err error) error {
if err != nil {
return nil
@@ -155,10 +155,18 @@ func (r *Reader) readFiles() bool {
path = filepath.Clean(path)
if path != "." {
isDir := de.IsDir()
- if isDir && filepath.Base(path)[0] == '.' {
- return filepath.SkipDir
+ if isDir {
+ base := filepath.Base(path)
+ if !opts.hidden && base[0] == '.' {
+ return filepath.SkipDir
+ }
+ for _, ignore := range ignores {
+ if ignore == base {
+ return filepath.SkipDir
+ }
+ }
}
- if !isDir && r.pusher([]byte(path)) {
+ if ((opts.file && !isDir) || (opts.dir && isDir)) && r.pusher([]byte(path)) {
atomic.StoreInt32(&r.event, int32(EvtReadNew))
}
}
@@ -169,7 +177,7 @@ func (r *Reader) readFiles() bool {
}
return nil
}
- return fastwalk.Walk(&conf, ".", fn) == nil
+ return fastwalk.Walk(&conf, root, fn) == nil
}
func (r *Reader) readFromCommand(command string, environ []string) bool {