mirror of
https://github.com/junegunn/fzf.git
synced 2025-08-31 12:23:50 -07:00
Compare commits
7 Commits
v0.54.2
...
history-hi
Author | SHA1 | Date | |
---|---|---|---|
|
e8a39eeb0f | ||
|
c790ab2024 | ||
|
d9404fcce4 | ||
|
5c01fee5a9 | ||
|
9b27d68a37 | ||
|
b99d884e57 | ||
|
587df594b8 |
@@ -1,6 +1,14 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
0.54.3
|
||||
------
|
||||
- Fixed incompatibility of adaptive height and 'start:reload'
|
||||
- Environment variables are now available to `$FZF_DEFAULT_COMMAND`
|
||||
```sh
|
||||
FZF_DEFAULT_COMMAND='echo $FZF_QUERY' fzf --query foo
|
||||
```
|
||||
|
||||
0.54.2
|
||||
------
|
||||
- Fixed incorrect syntax highlighting of truncated multi-line entries
|
||||
|
@@ -54,7 +54,45 @@ __fzf_cd__() {
|
||||
) && printf 'builtin cd -- %q' "$(builtin unset CDPATH && builtin cd -- "$dir" && builtin pwd)"
|
||||
}
|
||||
|
||||
if command -v perl > /dev/null; then
|
||||
if command -v ruby > /dev/null; then
|
||||
__fzf_history__() {
|
||||
local n output
|
||||
builtin history -w /tmp/fzf-bash-history
|
||||
output=$(
|
||||
ruby -e '
|
||||
fmt = begin
|
||||
require "rouge"
|
||||
formatter = Rouge::Formatters::Terminal256.new(Rouge::Themes::Monokai.new)
|
||||
lexer = Rouge::Lexers::Shell.new
|
||||
lambda { |c| formatter.format(lexer.lex(c)) }
|
||||
rescue LoadError
|
||||
lambda { |c| c }
|
||||
end
|
||||
|
||||
h = {}
|
||||
i = 0
|
||||
File.read("/tmp/fzf-bash-history").encode!("UTF-8", "UTF-8", :invalid => :replace).scan(/^#([0-9]+)$\n(.*?)\n(?=^#[0-9]+$|\z)/m) do |t, c|
|
||||
next if c.empty?
|
||||
h.delete(c)
|
||||
h[c] = [i += 1, t]
|
||||
end
|
||||
h.to_a.reverse.each do |c, it|
|
||||
i, t = it
|
||||
print "\x1b[33m#{i}\t\x1b[32m#{Time.at(t.to_i).strftime(%[%F %T])}\x1b[m "
|
||||
print fmt[c.gsub("\n", "\n\t")]
|
||||
print "\0"
|
||||
end
|
||||
' | FZF_DEFAULT_OPTS=$(__fzf_defaults "" "-n1,4.. --ansi --scheme=history --bind=ctrl-r:toggle-sort --wrap-sign '"$'\t'"↳ ' --highlight-line ${FZF_CTRL_R_OPTS-} +m --read0") \
|
||||
FZF_DEFAULT_OPTS_FILE='' $(__fzfcmd) --query "$READLINE_LINE" --bind 'enter:become:echo {4..}'
|
||||
) || return
|
||||
READLINE_LINE=$(command perl -pe 's/^\d*\t//' <<< "$output")
|
||||
if [[ -z "$READLINE_POINT" ]]; then
|
||||
echo "$READLINE_LINE"
|
||||
else
|
||||
READLINE_POINT=0x7fffffff
|
||||
fi
|
||||
}
|
||||
elif command -v perl > /dev/null; then
|
||||
__fzf_history__() {
|
||||
local output script
|
||||
script='BEGIN { getc; $/ = "\n\t"; $HISTCOUNT = $ENV{last_hist} + 1 } s/^[ *]//; s/\n/\n\t/gm; print $HISTCOUNT - $. . "\t$_" if !$seen{$_}++'
|
||||
|
@@ -58,7 +58,6 @@ const (
|
||||
const (
|
||||
EvtReadNew util.EventType = iota
|
||||
EvtReadFin
|
||||
EvtReadNone
|
||||
EvtSearchNew
|
||||
EvtSearchProgress
|
||||
EvtSearchFin
|
||||
|
42
src/core.go
42
src/core.go
@@ -146,8 +146,25 @@ func Run(opts *Options) (int, error) {
|
||||
// Process executor
|
||||
executor := util.NewExecutor(opts.WithShell)
|
||||
|
||||
// Terminal I/O
|
||||
var terminal *Terminal
|
||||
var err error
|
||||
var initialEnv []string
|
||||
initialReload := opts.extractReloadOnStart()
|
||||
if opts.Filter == nil {
|
||||
terminal, err = NewTerminal(opts, eventBox, executor)
|
||||
if err != nil {
|
||||
return ExitError, err
|
||||
}
|
||||
if len(initialReload) > 0 {
|
||||
var temps []string
|
||||
initialReload, temps = terminal.replacePlaceholderInInitialCommand(initialReload)
|
||||
initialEnv = terminal.environ()
|
||||
defer removeFiles(temps)
|
||||
}
|
||||
}
|
||||
|
||||
// Reader
|
||||
reloadOnStart := opts.reloadOnStart()
|
||||
streamingFilter := opts.Filter != nil && !sort && !opts.Tac && !opts.Sync
|
||||
var reader *Reader
|
||||
if !streamingFilter {
|
||||
@@ -155,12 +172,7 @@ func Run(opts *Options) (int, error) {
|
||||
return chunkList.Push(data)
|
||||
}, eventBox, executor, opts.ReadZero, opts.Filter == nil)
|
||||
|
||||
if reloadOnStart {
|
||||
// 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, initialReload, initialEnv)
|
||||
}
|
||||
|
||||
// Matcher
|
||||
@@ -212,7 +224,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, initialReload, initialEnv)
|
||||
} else {
|
||||
eventBox.Unwatch(EvtReadNew)
|
||||
eventBox.WaitFor(EvtReadFin)
|
||||
@@ -234,8 +246,7 @@ func Run(opts *Options) (int, error) {
|
||||
}
|
||||
|
||||
// Synchronous search
|
||||
sync := opts.Sync && !reloadOnStart
|
||||
if sync {
|
||||
if opts.Sync {
|
||||
eventBox.Unwatch(EvtReadNew)
|
||||
eventBox.WaitFor(EvtReadFin)
|
||||
}
|
||||
@@ -244,18 +255,14 @@ func Run(opts *Options) (int, error) {
|
||||
go matcher.Loop()
|
||||
defer matcher.Stop()
|
||||
|
||||
// Terminal I/O
|
||||
terminal, err := NewTerminal(opts, eventBox, executor)
|
||||
if err != nil {
|
||||
return ExitError, err
|
||||
}
|
||||
// Handling adaptive height
|
||||
maxFit := 0 // Maximum number of items that can fit on screen
|
||||
padHeight := 0
|
||||
heightUnknown := opts.Height.auto
|
||||
if heightUnknown {
|
||||
maxFit, padHeight = terminal.MaxFitAndPad()
|
||||
}
|
||||
deferred := opts.Select1 || opts.Exit0 || sync
|
||||
deferred := opts.Select1 || opts.Exit0 || opts.Sync
|
||||
go terminal.Loop()
|
||||
if !deferred && !heightUnknown {
|
||||
// Start right away
|
||||
@@ -322,9 +329,6 @@ func Run(opts *Options) (int, error) {
|
||||
err = quitSignal.err
|
||||
stop = true
|
||||
return
|
||||
case EvtReadNone:
|
||||
reading = false
|
||||
terminal.UpdateCount(0, false, nil)
|
||||
case EvtReadNew, EvtReadFin:
|
||||
if evt == EvtReadFin && nextCommand != nil {
|
||||
restart(*nextCommand, nextEnviron)
|
||||
|
@@ -2964,17 +2964,18 @@ func ParseOptions(useDefaults bool, args []string) (*Options, error) {
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (opts *Options) reloadOnStart() bool {
|
||||
// Not compatible with --filter
|
||||
if opts.Filter != nil {
|
||||
return false
|
||||
}
|
||||
func (opts *Options) extractReloadOnStart() string {
|
||||
cmd := ""
|
||||
if actions, prs := opts.Keymap[tui.Start.AsEvent()]; prs {
|
||||
filtered := []*action{}
|
||||
for _, action := range actions {
|
||||
if action.t == actReload || action.t == actReloadSync {
|
||||
return true
|
||||
cmd = action.a
|
||||
} else {
|
||||
filtered = append(filtered, action)
|
||||
}
|
||||
}
|
||||
opts.Keymap[tui.Start.AsEvent()] = filtered
|
||||
}
|
||||
return false
|
||||
return cmd
|
||||
}
|
||||
|
@@ -111,18 +111,19 @@ 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, initCmd string, initEnv []string) {
|
||||
r.startEventPoller()
|
||||
var success bool
|
||||
if inputChan != nil {
|
||||
success = r.readChannel(inputChan)
|
||||
} else if len(initCmd) > 0 {
|
||||
success = r.readFromCommand(initCmd, initEnv)
|
||||
} else if util.IsTty(os.Stdin) {
|
||||
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
|
||||
if len(cmd) == 0 {
|
||||
success = r.readFiles(root, opts, ignores)
|
||||
} else {
|
||||
// We can't export FZF_* environment variables to the default command
|
||||
success = r.readFromCommand(cmd, nil)
|
||||
success = r.readFromCommand(cmd, initEnv)
|
||||
}
|
||||
} else {
|
||||
success = r.readFromStdin()
|
||||
|
@@ -2946,6 +2946,10 @@ type replacePlaceholderParams struct {
|
||||
executor *util.Executor
|
||||
}
|
||||
|
||||
func (t *Terminal) replacePlaceholderInInitialCommand(template string) (string, []string) {
|
||||
return t.replacePlaceholder(template, false, string(t.input), []*Item{nil, nil})
|
||||
}
|
||||
|
||||
func (t *Terminal) replacePlaceholder(template string, forcePlus bool, input string, list []*Item) (string, []string) {
|
||||
return replacePlaceholder(replacePlaceholderParams{
|
||||
template: template,
|
||||
|
Reference in New Issue
Block a user