mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-15 23:03:47 -05:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e03e91477b | ||
|
|
88ac397158 | ||
|
|
6fd4be580b | ||
|
|
53348feb89 | ||
|
|
337cdbb37c | ||
|
|
05fdf91fc5 | ||
|
|
c387689d1c | ||
|
|
cb9238dc4e | ||
|
|
a484811f78 | ||
|
|
111d1934c4 | ||
|
|
972fb1a29d | ||
|
|
3a6af27586 | ||
|
|
c89ac341e4 | ||
|
|
cd59e5d07b | ||
|
|
0b940e4b2b | ||
|
|
b29375c844 | ||
|
|
76d3f6d248 |
@@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
0.16.6
|
||||
------
|
||||
- Minor bug fixes and improvements
|
||||
- Added `--no-clear` option for scripting purposes
|
||||
|
||||
0.16.5
|
||||
------
|
||||
- Minor bug fixes
|
||||
|
||||
@@ -230,8 +230,8 @@ fish.
|
||||
- Set `FZF_CTRL_T_COMMAND` to override the default command
|
||||
- Set `FZF_CTRL_T_OPTS` to pass additional options
|
||||
- `CTRL-R` - Paste the selected command from history onto the command line
|
||||
- Sort is disabled by default to respect chronological ordering
|
||||
- Press `CTRL-R` again to toggle sort
|
||||
- If you want to see the commands in chronological order, press `CTRL-R`
|
||||
again which toggles sorting by relevance
|
||||
- Set `FZF_CTRL_R_OPTS` to pass additional options
|
||||
- `ALT-C` - cd into the selected directory
|
||||
- Set `FZF_ALT_C_COMMAND` to override the default command
|
||||
|
||||
2
install
2
install
@@ -2,7 +2,7 @@
|
||||
|
||||
set -u
|
||||
|
||||
version=0.16.5
|
||||
version=0.16.6
|
||||
auto_completion=
|
||||
key_bindings=
|
||||
update_config=2
|
||||
|
||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
..
|
||||
.TH fzf-tmux 1 "Feb 2017" "fzf 0.16.5" "fzf-tmux - open fzf in tmux split pane"
|
||||
.TH fzf-tmux 1 "Mar 2017" "fzf 0.16.6" "fzf-tmux - open fzf in tmux split pane"
|
||||
|
||||
.SH NAME
|
||||
fzf-tmux - open fzf in tmux split pane
|
||||
|
||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
..
|
||||
.TH fzf 1 "Feb 2017" "fzf 0.16.5" "fzf - a command-line fuzzy finder"
|
||||
.TH fzf 1 "Mar 2017" "fzf 0.16.6" "fzf - a command-line fuzzy finder"
|
||||
|
||||
.SH NAME
|
||||
fzf - a command-line fuzzy finder
|
||||
@@ -339,6 +339,12 @@ Read input delimited by ASCII NUL characters instead of newline characters
|
||||
.B "--print0"
|
||||
Print output delimited by ASCII NUL characters instead of newline characters
|
||||
.TP
|
||||
.B "--no-clear"
|
||||
Do not clear finder interface on exit. If fzf was started in full screen mode,
|
||||
it will not switch back to the original screen, so you'll have to manually run
|
||||
\fBtput rmcup\fR to return. This option can be used to avoid flickering of the
|
||||
screen when your application needs to start fzf multiple times in order.
|
||||
.TP
|
||||
.B "--sync"
|
||||
Synchronous search for multi-staged filtering. If specified, fzf will launch
|
||||
ncurses finder only after the input stream is complete.
|
||||
|
||||
@@ -192,6 +192,16 @@ function! s:defaults()
|
||||
return empty(colors) ? '' : ('--color='.colors)
|
||||
endfunction
|
||||
|
||||
function! s:validate_layout(layout)
|
||||
for key in keys(a:layout)
|
||||
if index(s:layout_keys, key) < 0
|
||||
throw printf('Invalid entry in g:fzf_layout: %s (allowed: %s)%s',
|
||||
\ key, join(s:layout_keys, ', '), key == 'options' ? '. Use $FZF_DEFAULT_OPTS.' : '')
|
||||
endif
|
||||
endfor
|
||||
return a:layout
|
||||
endfunction
|
||||
|
||||
" [name string,] [opts dict,] [fullscreen boolean]
|
||||
function! fzf#wrap(...)
|
||||
let args = ['', {}, 0]
|
||||
@@ -200,7 +210,7 @@ function! fzf#wrap(...)
|
||||
for arg in copy(a:000)
|
||||
let tidx = index(expects, type(arg), tidx)
|
||||
if tidx < 0
|
||||
throw 'invalid arguments (expected: [name string] [opts dict] [fullscreen boolean])'
|
||||
throw 'Invalid arguments (expected: [name string] [opts dict] [fullscreen boolean])'
|
||||
endif
|
||||
let args[tidx] = arg
|
||||
let tidx += 1
|
||||
@@ -223,7 +233,7 @@ function! fzf#wrap(...)
|
||||
if !exists('g:fzf_layout') && exists('g:fzf_height')
|
||||
let opts.down = g:fzf_height
|
||||
else
|
||||
let opts = extend(opts, get(g:, 'fzf_layout', s:default_layout))
|
||||
let opts = extend(opts, s:validate_layout(get(g:, 'fzf_layout', s:default_layout)))
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -290,6 +300,10 @@ try
|
||||
throw v:exception
|
||||
endtry
|
||||
|
||||
if has('nvim') && !has_key(dict, 'dir')
|
||||
let dict.dir = getcwd()
|
||||
endif
|
||||
|
||||
if !has_key(dict, 'source') && !empty($FZF_DEFAULT_COMMAND)
|
||||
let temps.source = tempname().(s:is_win ? '.bat' : '')
|
||||
call writefile((s:is_win ? ['@echo off'] : []) + split($FZF_DEFAULT_COMMAND, "\n"), temps.source)
|
||||
@@ -306,7 +320,7 @@ try
|
||||
call writefile(source, temps.input)
|
||||
let prefix = (s:is_win ? 'type ' : 'cat ').s:shellesc(temps.input).'|'
|
||||
else
|
||||
throw 'invalid source type'
|
||||
throw 'Invalid source type'
|
||||
endif
|
||||
else
|
||||
let prefix = ''
|
||||
@@ -436,7 +450,7 @@ function! s:execute(dict, command, use_height, temps) abort
|
||||
if has('unix') && !a:use_height
|
||||
silent! !clear 2> /dev/null
|
||||
endif
|
||||
let escaped = escape(substitute(a:command, '\n', '\\n', 'g'), '%#')
|
||||
let escaped = escape(substitute(a:command, '\n', '\\n', 'g'), '%#!')
|
||||
if has('gui_running')
|
||||
let Launcher = get(a:dict, 'launcher', get(g:, 'Fzf_launcher', get(g:, 'fzf_launcher', s:launcher)))
|
||||
let fmt = type(Launcher) == 2 ? call(Launcher, []) : Launcher
|
||||
|
||||
@@ -143,7 +143,7 @@ _fzf_complete_unalias() {
|
||||
|
||||
fzf-completion() {
|
||||
local tokens cmd prefix trigger tail fzf matches lbuf d_cmds
|
||||
setopt localoptions noshwordsplit noksh_arrays
|
||||
setopt localoptions noshwordsplit noksh_arrays noposixbuiltins
|
||||
|
||||
# http://zsh.sourceforge.net/FAQ/zshfaq03.html
|
||||
# http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags
|
||||
|
||||
@@ -56,7 +56,7 @@ __fzf_history__() (
|
||||
shopt -u nocaseglob nocasematch
|
||||
line=$(
|
||||
HISTTIMEFORMAT= history |
|
||||
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS +s --tac -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m" $(__fzfcmd) |
|
||||
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS --tac -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m" $(__fzfcmd) |
|
||||
command grep '^ *[0-9]') &&
|
||||
if [[ $- =~ H ]]; then
|
||||
sed 's/^ *\([0-9]*\)\** .*/!\1/' <<< "$line"
|
||||
|
||||
@@ -45,7 +45,7 @@ function fzf_key_bindings
|
||||
function fzf-history-widget -d "Show command history"
|
||||
set -q FZF_TMUX_HEIGHT; or set FZF_TMUX_HEIGHT 40%
|
||||
begin
|
||||
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS +s --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m"
|
||||
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m"
|
||||
history | eval (__fzfcmd) -q '(commandline)' | read -l result
|
||||
and commandline -- $result
|
||||
end
|
||||
|
||||
@@ -58,9 +58,9 @@ bindkey '\ec' fzf-cd-widget
|
||||
# CTRL-R - Paste the selected command from history into the command line
|
||||
fzf-history-widget() {
|
||||
local selected num
|
||||
setopt localoptions noglobsubst pipefail 2> /dev/null
|
||||
setopt localoptions noglobsubst noposixbuiltins pipefail 2> /dev/null
|
||||
selected=( $(fc -l 1 |
|
||||
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS +s --tac -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS --query=${(q)LBUFFER} +m" $(__fzfcmd)) )
|
||||
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS --tac -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS --query=${(q)LBUFFER} +m" $(__fzfcmd)) )
|
||||
local ret=$?
|
||||
if [ -n "$selected" ]; then
|
||||
num=$selected[1]
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
const (
|
||||
// Current version
|
||||
version = "0.16.5"
|
||||
version = "0.16.6"
|
||||
|
||||
// Core
|
||||
coordinatorDelayMax time.Duration = 100 * time.Millisecond
|
||||
|
||||
@@ -186,6 +186,7 @@ type Options struct {
|
||||
Margin [4]sizeSpec
|
||||
Bordered bool
|
||||
Tabstop int
|
||||
ClearOnExit bool
|
||||
Version bool
|
||||
}
|
||||
|
||||
@@ -234,6 +235,7 @@ func defaultOptions() *Options {
|
||||
HeaderLines: 0,
|
||||
Margin: defaultMargin(),
|
||||
Tabstop: 8,
|
||||
ClearOnExit: true,
|
||||
Version: false}
|
||||
}
|
||||
|
||||
@@ -1099,6 +1101,10 @@ func parseOptions(opts *Options, allArgs []string) {
|
||||
nextString(allArgs, &i, "margin required (TRBL / TB,RL / T,RL,B / T,R,B,L)"))
|
||||
case "--tabstop":
|
||||
opts.Tabstop = nextInt(allArgs, &i, "tab stop required")
|
||||
case "--clear":
|
||||
opts.ClearOnExit = true
|
||||
case "--no-clear":
|
||||
opts.ClearOnExit = false
|
||||
case "--version":
|
||||
opts.Version = true
|
||||
default:
|
||||
|
||||
@@ -46,6 +46,7 @@ type itemLine struct {
|
||||
current bool
|
||||
selected bool
|
||||
label string
|
||||
queryLen int
|
||||
width int
|
||||
result Result
|
||||
}
|
||||
@@ -294,7 +295,14 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
||||
strongAttr = tui.AttrRegular
|
||||
}
|
||||
var renderer tui.Renderer
|
||||
if opts.Height.size > 0 {
|
||||
if opts.Height.size == 0 || opts.Height.percent && opts.Height.size == 100 {
|
||||
if tui.HasFullscreenRenderer() {
|
||||
renderer = tui.NewFullscreenRenderer(opts.Theme, opts.Black, opts.Mouse)
|
||||
} else {
|
||||
renderer = tui.NewLightRenderer(opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit,
|
||||
true, func(h int) int { return h })
|
||||
}
|
||||
} else {
|
||||
maxHeightFunc := func(termHeight int) int {
|
||||
var maxHeight int
|
||||
if opts.Height.percent {
|
||||
@@ -315,12 +323,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
||||
}
|
||||
return util.Min(termHeight, util.Max(maxHeight, effectiveMinHeight))
|
||||
}
|
||||
renderer = tui.NewLightRenderer(opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, maxHeightFunc)
|
||||
} else if tui.HasFullscreenRenderer() {
|
||||
renderer = tui.NewFullscreenRenderer(opts.Theme, opts.Black, opts.Mouse)
|
||||
} else {
|
||||
renderer = tui.NewLightRenderer(opts.Theme, opts.Black, opts.Mouse, opts.Tabstop,
|
||||
func(h int) int { return h })
|
||||
renderer = tui.NewLightRenderer(opts.Theme, opts.Black, opts.Mouse, opts.Tabstop, opts.ClearOnExit, false, maxHeightFunc)
|
||||
}
|
||||
wordRubout := "[^[:alnum:]][[:alnum:]]"
|
||||
wordNext := "[[:alnum:]][^[:alnum:]]|(.$)"
|
||||
@@ -599,7 +602,7 @@ func (t *Terminal) resizeWindows() {
|
||||
width,
|
||||
height, tui.BorderNone)
|
||||
}
|
||||
if !t.tui.IsOptimized() && t.theme != nil && t.theme.HasBg() {
|
||||
if !t.tui.IsOptimized() {
|
||||
for i := 0; i < t.window.Height(); i++ {
|
||||
t.window.MoveAndClear(i, 0)
|
||||
}
|
||||
@@ -657,9 +660,9 @@ func (t *Terminal) printInfo() {
|
||||
output := fmt.Sprintf("%d/%d", t.merger.Length(), t.count)
|
||||
if t.toggleSort {
|
||||
if t.sort {
|
||||
output += "/S"
|
||||
output += " +S"
|
||||
} else {
|
||||
output += " "
|
||||
output += " -S"
|
||||
}
|
||||
}
|
||||
if t.multi && len(t.selected) > 0 {
|
||||
@@ -737,11 +740,13 @@ func (t *Terminal) printItem(result *Result, line int, i int, current bool) {
|
||||
}
|
||||
|
||||
// Avoid unnecessary redraw
|
||||
newLine := itemLine{current: current, selected: selected, label: label, result: *result, width: 0}
|
||||
newLine := itemLine{current: current, selected: selected, label: label,
|
||||
result: *result, queryLen: len(t.input), width: 0}
|
||||
prevLine := t.prevLines[i]
|
||||
if prevLine.current == newLine.current &&
|
||||
prevLine.selected == newLine.selected &&
|
||||
prevLine.label == newLine.label &&
|
||||
prevLine.queryLen == newLine.queryLen &&
|
||||
prevLine.result == newLine.result {
|
||||
return
|
||||
}
|
||||
@@ -955,7 +960,7 @@ func (t *Terminal) printPreview() {
|
||||
trimmed, _ = t.trimRight(trimmed, maxWidth-t.pwindow.X())
|
||||
}
|
||||
str, _ = t.processTabs(trimmed, 0)
|
||||
if ansi != nil && ansi.colored() {
|
||||
if t.theme != nil && ansi != nil && ansi.colored() {
|
||||
fillRet = t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str)
|
||||
} else {
|
||||
fillRet = t.pwindow.Fill(str)
|
||||
|
||||
@@ -74,6 +74,7 @@ type LightRenderer struct {
|
||||
theme *ColorTheme
|
||||
mouse bool
|
||||
forceBlack bool
|
||||
clearOnExit bool
|
||||
prevDownTime time.Time
|
||||
clickY []int
|
||||
ttyin *os.File
|
||||
@@ -106,15 +107,16 @@ type LightWindow struct {
|
||||
bg Color
|
||||
}
|
||||
|
||||
func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, maxHeightFunc func(int) int) Renderer {
|
||||
func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) Renderer {
|
||||
r := LightRenderer{
|
||||
theme: theme,
|
||||
forceBlack: forceBlack,
|
||||
mouse: mouse,
|
||||
clearOnExit: clearOnExit,
|
||||
ttyin: openTtyIn(),
|
||||
yoffset: 0,
|
||||
tabstop: tabstop,
|
||||
fullscreen: false,
|
||||
fullscreen: fullscreen,
|
||||
upOneLine: false,
|
||||
maxHeightFunc: maxHeightFunc}
|
||||
return &r
|
||||
@@ -174,11 +176,7 @@ func (r *LightRenderer) Init() {
|
||||
}
|
||||
r.origState = origState
|
||||
terminal.MakeRaw(fd)
|
||||
terminalHeight, capHeight := r.updateTerminalSize()
|
||||
if capHeight == terminalHeight {
|
||||
r.fullscreen = true
|
||||
r.height = terminalHeight
|
||||
}
|
||||
r.updateTerminalSize()
|
||||
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
|
||||
|
||||
if r.fullscreen {
|
||||
@@ -240,20 +238,15 @@ func getEnv(name string, defaultValue int) int {
|
||||
return atoi(env, defaultValue)
|
||||
}
|
||||
|
||||
func (r *LightRenderer) updateTerminalSize() (int, int) {
|
||||
func (r *LightRenderer) updateTerminalSize() {
|
||||
width, height, err := terminal.GetSize(r.fd())
|
||||
if err == nil {
|
||||
r.width = width
|
||||
if r.fullscreen {
|
||||
r.height = height
|
||||
} else {
|
||||
r.height = r.maxHeightFunc(height)
|
||||
}
|
||||
r.height = r.maxHeightFunc(height)
|
||||
} else {
|
||||
r.width = getEnv("COLUMNS", defaultWidth)
|
||||
r.height = r.maxHeightFunc(getEnv("LINES", defaultHeight))
|
||||
}
|
||||
return height, r.height
|
||||
}
|
||||
|
||||
func (r *LightRenderer) getch(nonblock bool) (int, bool) {
|
||||
@@ -571,14 +564,20 @@ func (r *LightRenderer) Refresh() {
|
||||
|
||||
func (r *LightRenderer) Close() {
|
||||
// r.csi("u")
|
||||
if r.fullscreen {
|
||||
r.rmcup()
|
||||
} else {
|
||||
r.origin()
|
||||
if r.upOneLine {
|
||||
r.csi("A")
|
||||
if r.clearOnExit {
|
||||
if r.fullscreen {
|
||||
r.rmcup()
|
||||
} else {
|
||||
r.origin()
|
||||
if r.upOneLine {
|
||||
r.csi("A")
|
||||
}
|
||||
r.csi("J")
|
||||
}
|
||||
r.csi("J")
|
||||
} else if r.fullscreen {
|
||||
r.csi("G")
|
||||
} else {
|
||||
r.move(r.height, 0)
|
||||
}
|
||||
if r.mouse {
|
||||
r.csi("?1000l")
|
||||
|
||||
@@ -513,11 +513,11 @@ class TestGoFZF < TestBase
|
||||
tmux.send_keys "seq 1 111 | #{fzf "-m +s --tac #{opt} -q11"}", :Enter
|
||||
tmux.until { |lines| lines[-3].include? '> 111' }
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| lines[-2].include? '4/111 (1)' }
|
||||
tmux.until { |lines| lines[-2].include? '4/111 -S (1)' }
|
||||
tmux.send_keys 'C-R'
|
||||
tmux.until { |lines| lines[-3].include? '> 11' }
|
||||
tmux.send_keys :Tab
|
||||
tmux.until { |lines| lines[-2].include? '4/111/S (2)' }
|
||||
tmux.until { |lines| lines[-2].include? '4/111 +S (2)' }
|
||||
tmux.send_keys :Enter
|
||||
assert_equal ['111', '11'], readonce.split($/)
|
||||
end
|
||||
@@ -1296,6 +1296,14 @@ class TestGoFZF < TestBase
|
||||
tmux.until { |lines| lines[4] == '> 3' }
|
||||
tmux.until { |_| %w[1 2 3] == File.readlines(tempname).map(&:chomp) }
|
||||
end
|
||||
|
||||
def test_no_clear
|
||||
tmux.send_keys 'seq 100 | fzf --no-clear --inline-info --height 5', :Enter
|
||||
prompt = '> < 100/100'
|
||||
tmux.until { |lines| lines[-1] == prompt }
|
||||
tmux.send_keys :Enter
|
||||
tmux.until { |lines| lines[-2] == prompt && lines[-1] == '1' }
|
||||
end
|
||||
end
|
||||
|
||||
module TestShell
|
||||
@@ -1408,6 +1416,7 @@ module TestShell
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.until { |lines| lines.item_count > 0 }
|
||||
end
|
||||
tmux.send_keys 'C-r'
|
||||
tmux.send_keys '3d'
|
||||
tmux.until { |lines| lines[-3].end_with? 'echo 3rd' }
|
||||
tmux.send_keys :Enter
|
||||
|
||||
Reference in New Issue
Block a user