diff --git a/src/core.go b/src/core.go index 61cabf9..c727708 100644 --- a/src/core.go +++ b/src/core.go @@ -113,7 +113,7 @@ func Run(opts *Options) { // Reader streamingFilter := opts.Filter != nil && !sort && !opts.Tac && !opts.Sync if !streamingFilter { - reader := Reader{func(str string) { chunkList.Push(str) }, eventBox} + reader := Reader{func(str string) { chunkList.Push(str) }, eventBox, opts.ReadZero} go reader.ReadSource() } @@ -139,7 +139,7 @@ func Run(opts *Options) { if pattern.MatchItem(item) { fmt.Println(*item.text) } - }, eventBox} + }, eventBox, opts.ReadZero} reader.ReadSource() } else { eventBox.Unwatch(EvtReadNew) diff --git a/src/options.go b/src/options.go index 63037ea..70d81cd 100644 --- a/src/options.go +++ b/src/options.go @@ -50,6 +50,7 @@ const usage = `usage: fzf [options] -1, --select-1 Automatically select the only match -0, --exit-0 Exit immediately when there's no match -f, --filter=STR Filter mode. Do not start interactive finder. + --null Read null-byte separated strings from input --print-query Print query as the first line --expect=KEYS Comma-separated list of keys to complete fzf --sync Synchronous search for multi-staged filtering @@ -117,6 +118,7 @@ type Options struct { Expect []int Keymap map[int]actionType PrintQuery bool + ReadZero bool Sync bool Version bool } @@ -155,6 +157,7 @@ func defaultOptions() *Options { Expect: []int{}, Keymap: defaultKeymap(), PrintQuery: false, + ReadZero: false, Sync: false, Version: false} } @@ -525,6 +528,8 @@ func parseOptions(opts *Options, allArgs []string) { opts.Exit0 = true case "+0", "--no-exit-0": opts.Exit0 = false + case "--null": + opts.ReadZero = true case "--print-query": opts.PrintQuery = true case "--no-print-query": diff --git a/src/reader.go b/src/reader.go index 7496b77..356c2db 100644 --- a/src/reader.go +++ b/src/reader.go @@ -13,6 +13,7 @@ import ( type Reader struct { pusher func(string) eventBox *util.EventBox + delimNil bool } // ReadSource reads data from the default command or from standard input @@ -30,31 +31,24 @@ func (r *Reader) ReadSource() { } func (r *Reader) feed(src io.Reader) { + delim := byte('\n') + if r.delimNil { + delim = '\000' + } reader := bufio.NewReader(src) - eof := false -Loop: - for !eof { - buf := []byte{} - iter := 0 // TODO: max size? - for { - // "ReadLine either returns a non-nil line or it returns an error, never both" - line, isPrefix, err := reader.ReadLine() - eof = err == io.EOF - if eof { - break - } else if err != nil { - break Loop + for { + line, err := reader.ReadString(delim) + if line != "" { + // "ReadString returns err != nil if and only if the returned data does not end in delim." + if err == nil { + line = line[:len(line)-1] } - iter++ - buf = append(buf, line...) - if !isPrefix { - break - } - } - if iter > 0 { - r.pusher(string(buf)) + r.pusher(line) r.eventBox.Set(EvtReadNew, nil) } + if err != nil { + break + } } }