summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2024-06-29 17:11:09 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2024-06-29 17:13:31 +0900
commitbf515a3d3251c54d04cd8e2e9f422cdd3f789fb8 (patch)
treec618a7ed122d2c3174165838f8b8319576513b55
parenta06745826a4cba4f578a69258f9def75c59530fc (diff)
downloadfzf-bf515a3d3251c54d04cd8e2e9f422cdd3f789fb8.tar.gz
Add --walker-path-sep=CHAR to use a different path separator
This is needed when you run a Windows binary on WSL or zsh on Windows where forward slashes are expected. export FZF_DEFAULT_OPTS='--walker-path-sep /' Close #3859
-rw-r--r--CHANGELOG.md2
-rw-r--r--man/man1/fzf.14
-rw-r--r--src/core.go4
-rw-r--r--src/options.go23
-rw-r--r--src/reader.go17
5 files changed, 44 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31312ddd..4817c76f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -47,6 +47,8 @@ CHANGELOG
--bind 'start:reload:sleep 1; ps -ef' \
--bind 'load:change-header:Loaded!'
```
+- Added `--walker-path-sep=CHAR` option to change the default path separator used by the built-in walker
+ - Needed when running a Windows binary on WSL or zsh on Windows where forward slashes are expected
- Fixed mouse support on Windows
- Fixed crash when using `--tiebreak=end` with very long items
- zsh 5.0 compatibility (thanks to @LangLangBart)
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index 14761438..873325dd 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -1008,6 +1008,10 @@ The default value is the current working directory.
Comma-separated list of directory names to skip during the directory walk.
The default value is \fB.git,node_modules\fR.
+.TP
+.B "\-\-walker\-path\-sep=CHAR"
+Path separator to use (default: '/' on Unix, '\\' on Windows)
+
.SS Shell integration
.TP
.B "\-\-bash"
diff --git a/src/core.go b/src/core.go
index caada27c..1dc642f4 100644
--- a/src/core.go
+++ b/src/core.go
@@ -159,7 +159,7 @@ func Run(opts *Options) (int, error) {
// reload or reload-sync action is bound to 'start' event, no need to start the reader
eventBox.Set(EvtReadNone, nil)
} else {
- go reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
+ go reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, opts.WalkerSep)
}
}
@@ -212,7 +212,7 @@ func Run(opts *Options) (int, error) {
}
return false
}, eventBox, executor, opts.ReadZero, false)
- reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
+ reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, opts.WalkerSep)
} else {
eventBox.Unwatch(EvtReadNew)
eventBox.WaitFor(EvtReadFin)
diff --git a/src/options.go b/src/options.go
index d32daf10..58b5782b 100644
--- a/src/options.go
+++ b/src/options.go
@@ -147,6 +147,7 @@ Usage: fzf [options]
--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)
+ --walker-path-sep=CHAR Path separator to use (default: / on Unix, \ on Windows)
Shell integration
--bash Print script to set up Bash shell integration
@@ -489,6 +490,7 @@ type Options struct {
WalkerOpts walkerOpts
WalkerRoot string
WalkerSkip []string
+ WalkerSep byte
Version bool
Help bool
CPUProfile string
@@ -592,6 +594,7 @@ func defaultOptions() *Options {
WalkerOpts: walkerOpts{file: true, hidden: true, follow: true},
WalkerRoot: ".",
WalkerSkip: []string{".git", "node_modules"},
+ WalkerSep: os.PathSeparator,
Help: false,
Version: false}
}
@@ -1904,6 +1907,14 @@ func parseMarkerMultiLine(str string) (*[3]string, error) {
return &result, nil
}
+func parsePathSep(str string) (byte, error) {
+ bytes := []byte(str)
+ if len(bytes) != 1 {
+ return os.PathSeparator, errors.New("invalid path separator (expected: single-byte character)")
+ }
+ return bytes[0], nil
+}
+
func parseOptions(index *int, opts *Options, allArgs []string) error {
var err error
var historyMax int
@@ -2479,6 +2490,14 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
return err
}
opts.WalkerSkip = filterNonEmpty(strings.Split(str, ","))
+ case "--walker-path-sep":
+ str, err := nextString(allArgs, &i, "path separator required")
+ if err != nil {
+ return err
+ }
+ if opts.WalkerSep, err = parsePathSep(str); err != nil {
+ return err
+ }
case "--profile-cpu":
if opts.CPUProfile, err = nextString(allArgs, &i, "file path required: cpu"); err != nil {
return err
@@ -2666,6 +2685,10 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
opts.WalkerRoot = value
} else if match, value := optString(arg, "--walker-skip="); match {
opts.WalkerSkip = filterNonEmpty(strings.Split(value, ","))
+ } else if match, value := optString(arg, "--walker-path-sep="); match {
+ if opts.WalkerSep, err = parsePathSep(value); err != nil {
+ return err
+ }
} else if match, value := optString(arg, "--hscroll-off="); match {
if opts.HscrollOff, err = atoi(value); err != nil {
return err
diff --git a/src/reader.go b/src/reader.go
index f39f47f5..9d4fe160 100644
--- a/src/reader.go
+++ b/src/reader.go
@@ -111,7 +111,7 @@ func (r *Reader) readChannel(inputChan chan string) bool {
}
// ReadSource reads data from the default command or from standard input
-func (r *Reader) ReadSource(inputChan chan string, root string, opts walkerOpts, ignores []string) {
+func (r *Reader) ReadSource(inputChan chan string, root string, opts walkerOpts, ignores []string, sep byte) {
r.startEventPoller()
var success bool
if inputChan != nil {
@@ -119,7 +119,7 @@ func (r *Reader) ReadSource(inputChan chan string, root string, opts walkerOpts,
} else if util.IsTty(os.Stdin) {
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
if len(cmd) == 0 {
- success = r.readFiles(root, opts, ignores)
+ success = r.readFiles(root, opts, ignores, sep)
} else {
// We can't export FZF_* environment variables to the default command
success = r.readFromCommand(cmd, nil)
@@ -233,9 +233,10 @@ func isSymlinkToDir(path string, de os.DirEntry) bool {
return false
}
-func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string) bool {
+func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string, sep byte) bool {
r.killed = false
conf := fastwalk.Config{Follow: opts.follow}
+ replaceSep := sep != os.PathSeparator
fn := func(path string, de os.DirEntry, err error) error {
if err != nil {
return nil
@@ -254,7 +255,15 @@ func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string) bool
}
}
}
- if ((opts.file && !isDir) || (opts.dir && isDir)) && r.pusher([]byte(path)) {
+ bytes := stringBytes(path)
+ if replaceSep {
+ for i, b := range bytes {
+ if b == os.PathSeparator {
+ bytes[i] = sep
+ }
+ }
+ }
+ if ((opts.file && !isDir) || (opts.dir && isDir)) && r.pusher(bytes) {
atomic.StoreInt32(&r.event, int32(EvtReadNew))
}
}