12 Commits

Author SHA1 Message Date
Junegunn Choi
879db51d09 Update README.md 2025-09-03 09:59:37 +09:00
phanium
3725f364cc Fix cmd hisotry correctly (#1594) 2025-06-20 17:04:48 +09:00
Junegunn Choi
98dcd77a18 Fix dictionary alignments 2025-06-08 10:51:25 +09:00
Scott Lai
a2ed9fb885 Add :BMarks command (#1593)
And allow passing arguments of :marks to :Marks command. Close #1158.

Co-authored-by: Junegunn Choi <junegunn.c@gmail.com>
2025-06-08 10:48:17 +09:00
Max Coplan
3ed6ac56d0 feat(preview): teach preview.sh to print directories (#1590) 2025-05-24 19:00:23 +09:00
Mo-tmd
3cb44a8ba5 Add workaround for normal! bug in nvim terminals (#1588)
There's a known issue regarding `normal` usage in neovim. See
https://github.com/neovim/neovim/issues/4895 for more details.

As a temporary workaround, use setpos to set the
bookmark instead.
2025-04-16 07:58:52 +09:00
Junegunn Choi
1fff637559 Use FugitiveWorkTree() to find the git root
Fix #1586
2025-03-21 17:31:10 +09:00
Junegunn Choi
245eaf8e50 Allow specifying command-level fzf options
Close #1583
2025-03-03 19:35:54 +09:00
Simon Désaulniers
f06bd1e69b autoload/fzf: don't user fzf#shellescape in favor of shellescape (#1582)
fzf#shellescape should only be used when building commands that fzf will run.
2025-02-22 10:41:20 +09:00
Junegunn Choi
6cda389bde Update README 2025-02-02 23:27:53 +09:00
Junegunn Choi
b3a49d7993 Apply --scheme=path where appropriate
See https://github.com/junegunn/fzf/pull/4192
2025-01-30 00:26:53 +09:00
Junegunn Choi
80d1cc2e68 Clean up scroll offset expression 2025-01-30 00:19:58 +09:00
5 changed files with 89 additions and 46 deletions

View File

@@ -1,20 +1,16 @@
<div align="center">
<sup>Special thanks to:</sup>
<br>
<br>
<a href="https://warp.dev/?utm_source=github&utm_medium=referral&utm_campaign=fzfvim_20240209">
<div>
<img src="https://raw.githubusercontent.com/junegunn/i/master/warp.png" width="300" alt="Warp">
</div>
<b>Warp is a modern, Rust-based terminal with AI built in so you and your team can build great software, faster.</b>
<div>
<sup>Visit warp.dev to learn more.</sup>
</div>
</a>
<br>
<hr>
<div align="center" markdown="1">
<sup>Special thanks to:</sup>
<br>
<a href="https://tuple.app/fzf.vim">
<img alt="Tuple's sponsorship image" src="https://raw.githubusercontent.com/junegunn/i/master/tuple.png" width="400">
</a>
### [Tuple, the premier screen sharing app for developers](https://tuple.app/fzf.vim)
[Available for MacOS & Windows](https://tuple.app/fzf.vim)<br>
</div>
<br>
---
fzf :heart: vim
===============
@@ -97,6 +93,7 @@ Commands
| `:BTags [QUERY]` | Tags in the current buffer |
| `:Changes` | Changelist across all open buffers |
| `:Marks` | Marks |
| `:BMarks` | Marks in the current buffer |
| `:Jumps` | Jumps |
| `:Windows` | Windows |
| `:Locate PATTERN` | `locate` command output |
@@ -201,6 +198,19 @@ let g:fzf_vim.tags_command = 'ctags -R'
let g:fzf_vim.commands_expect = 'alt-enter,ctrl-x'
```
#### Command-level fzf options
You can set fzf options for each command by setting
`g:fzf_vim.{command}_options`.
```vim
" In string
let g:fzf_vim.buffers_options = '--style full --border-label " Open Buffers "'
" In list (No need to quote or escape values)
let g:fzf_vim.buffers_options = ['--style', 'full', '--border-label', ' Open Buffers ']
```
#### List type to handle multiple selections
The following commands will fill the quickfix list when multiple entries are

View File

@@ -340,6 +340,10 @@ function! s:fzf(name, opts, extra)
let eopts = has_key(extra, 'options') ? remove(extra, 'options') : ''
let merged = extend(copy(a:opts), extra)
call s:merge_opts(merged, eopts)
" Command-level fzf options
call s:merge_opts(merged, s:conf(a:name.'_options', []))
return fzf#run(s:wrap(a:name, merged, bang))
endfunction
@@ -365,7 +369,7 @@ function! s:action_for(key, ...)
" errors. e.g. E471: Argument required: tab drop
if !a:0
if !edit
normal! m'
call setpos("''", getpos('.'))
silent! call s:execute_silent(cmd)
endif
else
@@ -374,7 +378,7 @@ function! s:action_for(key, ...)
" instructed to stay on the current buffer.
let stay = edit && (a:0 > 1 && a:2 || fnamemodify(a:1, ':p') ==# expand('%:p'))
if !stay
normal! m'
call setpos("''", getpos('.'))
call s:execute_silent((len(cmd) ? cmd : 'edit').' '.s:escape(a:1))
endif
endif
@@ -455,7 +459,7 @@ function! fzf#vim#files(dir, ...)
let dir = s:shortpath()
endif
let args.options = ['-m', '--prompt', strwidth(dir) < &columns / 2 - 20 ? dir : '> ']
let args.options = ['--scheme', 'path', '-m', '--prompt', strwidth(dir) < &columns / 2 - 20 ? dir : '> ']
call s:merge_opts(args, s:conf('files_options', []))
return s:fzf('files', args, a:000)
endfunction
@@ -665,9 +669,8 @@ function! s:history_sink(type, lines)
let key = a:lines[0]
let item = matchstr(a:lines[1], ' *[0-9]\+ *\zs.*')
if key == 'ctrl-e'
call histadd(a:type, item)
redraw
call feedkeys(a:type."\<up>", 'n')
call feedkeys(a:type.item, 'nt')
else
if a:type == ':'
call histadd(a:type, item)
@@ -711,8 +714,11 @@ endfunction
" ------------------------------------------------------------------
function! s:get_git_root(dir)
if empty(a:dir) && exists('*FugitiveWorkTree')
return FugitiveWorkTree()
endif
let dir = len(a:dir) ? a:dir : substitute(split(expand('%:p:h'), '[/\\]\.git\([/\\]\|$\)')[0], '^fugitive://', '', '')
let root = systemlist('git -C ' . fzf#shellescape(dir) . ' rev-parse --show-toplevel')[0]
let root = systemlist('git -C ' . shellescape(dir) . ' rev-parse --show-toplevel')[0]
return v:shell_error ? '' : (len(a:dir) ? fnamemodify(a:dir, ':p') : root)
endfunction
@@ -748,7 +754,7 @@ function! fzf#vim#gitfiles(args, ...)
return s:fzf('gfiles', {
\ 'source': source,
\ 'dir': root,
\ 'options': '-m --read0 --prompt "GitFiles> "'
\ 'options': '--scheme path -m --read0 --prompt "GitFiles> "'
\}, a:000)
endif
@@ -766,7 +772,7 @@ function! fzf#vim#gitfiles(args, ...)
let wrapped = fzf#wrap({
\ 'source': prefix . '-c color.status=always status --short --untracked-files=all',
\ 'dir': root,
\ 'options': ['--ansi', '--multi', '--nth', '2..,..', '--tiebreak=index', '--prompt', 'GitFiles?> ', '--preview', preview]
\ 'options': ['--scheme', 'path', '--ansi', '--multi', '--nth', '2..,..', '--tiebreak=index', '--prompt', 'GitFiles?> ', '--preview', preview]
\})
call s:remove_layout(wrapped)
let wrapped.common_sink = remove(wrapped, 'sink*')
@@ -856,7 +862,7 @@ function! fzf#vim#buffers(...)
return s:fzf('buffers', {
\ 'source': map(sorted, 'fzf#vim#_format_buffer(v:val)'),
\ 'sink*': s:function('s:bufopen'),
\ 'options': ['+m', '-x', '--tiebreak=index', header_lines, '--ansi', '-d', '\t', '--with-nth', '3..', '-n', '2,1..2', '--prompt', 'Buf> ', '--query', query, '--preview-window', '+{2}-/2', '--tabstop', tabstop]
\ 'options': ['+m', '-x', '--tiebreak=index', header_lines, '--ansi', '-d', '\t', '--with-nth', '3..', '-n', '2,1..2', '--prompt', 'Buf> ', '--query', query, '--preview-window', '+{2}/2', '--tabstop', tabstop]
\}, args)
endfunction
@@ -965,7 +971,7 @@ function! fzf#vim#grep(grep_command, ...)
let opts = {
\ 'options': ['--ansi', '--prompt', capname.'> ',
\ '--multi', '--bind', 'alt-a:select-all,alt-d:deselect-all',
\ '--delimiter', ':', '--preview-window', '+{2}-/2']
\ '--delimiter', ':', '--preview-window', '+{2}/2']
\}
if len(args) && type(args[0]) == s:TYPE.bool
call remove(args, 0)
@@ -1001,11 +1007,11 @@ function! fzf#vim#grep2(command_prefix, query, ...)
let name = join(words, '-')
let fallback = s:is_win ? '' : ' || :'
let opts = {
\ 'source': s:is_win ? 'cd .' : ':',
\ 'source': s:is_win ? 'cd .' : ':',
\ 'options': ['--ansi', '--prompt', toupper(name).'> ', '--query', a:query,
\ '--disabled',
\ '--multi', '--bind', 'alt-a:select-all,alt-d:deselect-all',
\ '--delimiter', ':', '--preview-window', '+{2}-/2']
\ '--delimiter', ':', '--preview-window', '+{2}/2']
\}
let [opts, suffix] = s:grep_multi_line(opts)
@@ -1082,7 +1088,7 @@ function! fzf#vim#buffer_tags(query, ...)
return s:fzf('btags', {
\ 'source': s:btags_source(tag_cmds),
\ 'sink*': s:function('s:btags_sink'),
\ 'options': s:reverse_list(['-m', '-d', '\t', '--with-nth', '1,4..', '-n', '1', '--prompt', 'BTags> ', '--query', a:query, '--preview-window', '+{3}-/2'])}, args)
\ 'options': s:reverse_list(['-m', '-d', '\t', '--with-nth', '1,4..', '-n', '1', '--prompt', 'BTags> ', '--query', a:query, '--preview-window', '+{3}/2'])}, args)
catch
return s:warn(v:exception)
endtry
@@ -1229,9 +1235,9 @@ function! s:command_sink(lines)
endif
let cmd = matchstr(a:lines[1], s:tab.'\zs\S*\ze'.s:tab)
if empty(a:lines[0])
call feedkeys(':'.cmd.(a:lines[1][0] == '!' ? '' : ' '), 'n')
call feedkeys(':'.cmd.(a:lines[1][0] == '!' ? '' : ' '), 'nt')
else
call feedkeys(':'.cmd."\<cr>", 'n')
call feedkeys(':'.cmd."\<cr>", 'nt')
endif
endfunction
@@ -1355,15 +1361,25 @@ function! s:mark_sink(lines)
execute 'normal! `'.matchstr(a:lines[1], '\S').'zz'
endfunction
function! fzf#vim#marks(...)
function! fzf#vim#marks(...) abort
let [initial_marks, extra] = (a:0 && type(a:1) == type('')) ?
\ [a:1, a:000[1:]] : ['', a:000]
redir => cout
silent marks
execute 'silent! marks' initial_marks
redir END
let list = split(cout, "\n")
" If first line is not the expected header, no marks found
if empty(list) || list[0] =~# '^E'
return s:warn('No marks found')
endif
return s:fzf('marks', {
\ 'source': extend(list[0:0], map(list[1:], 's:format_mark(v:val)')),
\ 'sink*': s:function('s:mark_sink'),
\ 'options': '+m -x --ansi --tiebreak=index --header-lines 1 --tiebreak=begin --prompt "Marks> "'}, a:000)
\ 'options': '+m -x --ansi --tiebreak=index --header-lines 1 --tiebreak=begin --prompt "Marks> "'}, extra)
endfunction
" ------------------------------------------------------------------
@@ -1413,9 +1429,9 @@ function! fzf#vim#jumps(...)
let s:jump_current = pos
let current = -pos-1
return s:fzf('jumps', {
\ 'source' : map(s:jumplist, 's:jump_format(v:val)'),
\ 'sink*' : s:function('s:jump_sink'),
\ 'options' : ['+m', '-x', '--ansi', '--tiebreak=index', '--cycle', '--scroll-off=999', '--sync', '--bind', 'start:pos('.current.')+offset-middle', '--tac', '--tiebreak=begin', '--prompt', 'Jumps> ', '--preview-window', '+{3}-/2', '--tabstop=2', '--delimiter', '[:\s]+'],
\ 'source': map(s:jumplist, 's:jump_format(v:val)'),
\ 'sink*': s:function('s:jump_sink'),
\ 'options': ['+m', '-x', '--ansi', '--tiebreak=index', '--cycle', '--scroll-off=999', '--sync', '--bind', 'start:pos('.current.')+offset-middle', '--tac', '--tiebreak=begin', '--prompt', 'Jumps> ', '--preview-window', '+{3}/2', '--tabstop=2', '--delimiter', '[:\s]+'],
\ }, a:000)
endfunction

View File

@@ -66,7 +66,7 @@ if [[ -z "$BATCAT" ]]; then
fi
fi
if [ -z "$FZF_PREVIEW_COMMAND" ] && [ "${BATCAT:+x}" ]; then
if [ -z "$FZF_PREVIEW_COMMAND" ] && [ "${BATCAT:+x}" ] && [[ ! -d "$FILE" ]] ; then
${BATCAT} --style="${BAT_STYLE:-numbers}" --color=always --pager=never \
--highlight-line=$CENTER -- "$FILE"
exit $?
@@ -74,12 +74,15 @@ fi
FILE_LENGTH=${#FILE}
MIME=$(file --dereference --mime -- "$FILE")
if [[ "${MIME:FILE_LENGTH}" =~ binary ]]; then
if [[ "${MIME:FILE_LENGTH}" =~ binary ]] && [[ ! -d "$FILE" ]]; then
echo "$MIME"
exit 0
fi
DEFAULT_COMMAND="highlight -O ansi -l {} || coderay {} || rougify {} || cat {}"
if [[ -d "$FILE" ]]; then
DEFAULT_COMMAND="tree -C -L2 {} || ls -l --color=always {}"
fi
CMD=${FZF_PREVIEW_COMMAND:-$DEFAULT_COMMAND}
CMD=${CMD//{\}/"$(printf %q "$FILE")"}

View File

@@ -1,4 +1,4 @@
fzf-vim.txt fzf-vim Last change: October 29 2024
fzf-vim.txt fzf-vim Last change: June 8 2025
FZF-VIM - TABLE OF CONTENTS *fzf-vim* *fzf-vim-toc*
==============================================================================
@@ -14,6 +14,7 @@ FZF-VIM - TABLE OF CONTENTS *fzf-vim* *fzf-vim-to
Configuration options for fzf.vim |fzf-vim-configuration-options-for-fzf-vim|
Preview window |fzf-vim-preview-window|
Command-level options |fzf-vim-command-level-options|
Command-level fzf options |fzf-vim-command-level-fzf-options|
List type to handle multiple selections |fzf-vim-list-type-to-handle-multiple-selections|
Advanced customization |fzf-vim-advanced-customization|
Vim functions |fzf-vim-vim-functions|
@@ -109,8 +110,8 @@ COMMANDS *fzf-vim-commands*
==============================================================================
*:Files* *:GFiles* *:Buffers* *:Colors* *:Ag* *:Rg* *:RG* *:Lines* *:BLines* *:Tags* *:BTags*
*:Changes* *:Marks* *:Jumps* *:Windows* *:Locate* *:History* *:Snippets* *:Commits* *:BCommits*
*:Commands* *:Maps* *:Helptags* *:Filetypes*
*:Changes* *:Marks* *:BMarks* *:Jumps* *:Windows* *:Locate* *:History* *:Snippets* *:Commits*
*:BCommits* *:Commands* *:Maps* *:Helptags* *:Filetypes*
-----------------------+--------------------------------------------------------------------------------------
Command | List ~
@@ -129,6 +130,7 @@ COMMANDS *fzf-vim-commands*
`:BTags [QUERY]` | Tags in the current buffer
`:Changes` | Changelist across all open buffers
`:Marks` | Marks
`:BMarks` | Marks in the current buffer
`:Jumps` | Jumps
`:Windows` | Windows
`:Locate PATTERN` | `locate` command output
@@ -228,7 +230,7 @@ Command-level options~
*g:fzf_vim.commands_expect* *g:fzf_vim.tags_command* *g:fzf_vim.commits_log_options*
*g:fzf_vim.buffers_jump*
>
" [Buffers] Jump to the existing window if possible
" [Buffers] Jump to the existing window if possible (default: 0)
let g:fzf_vim.buffers_jump = 1
" [Ag|Rg|RG] Display path on a separate line for narrow screens (default: 0)
@@ -253,6 +255,19 @@ Command-level options~
let g:fzf_vim.commands_expect = 'alt-enter,ctrl-x'
<
Command-level fzf options~
*fzf-vim-command-level-fzf-options*
You can set fzf options for each command by setting
`g:fzf_vim.{command}_options`.
>
" In string
let g:fzf_vim.buffers_options = '--style full --border-label " Open Buffers "'
" In list (No need to quote or escape values)
let g:fzf_vim.buffers_options = ['--style', 'full', '--border-label', ' Open Buffers ']
<
List type to handle multiple selections~
*fzf-vim-list-type-to-handle-multiple-selections*
@@ -383,8 +398,6 @@ Example: git grep wrapper~
The following example implements `GGrep` command that works similarly to
predefined `Ag` or `Rg` using `fzf#vim#grep`.
*:LINE*
- We set the base directory to git root by setting `dir` attribute in spec
dictionary.
- {The preview script}{12} supports `grep` format (`FILE_PATH:LINE_NO:...`), so

View File

@@ -67,7 +67,8 @@ call s:defs([
\'command! -bar -bang Snippets call fzf#vim#snippets(<bang>0)',
\'command! -bar -bang Commands call fzf#vim#commands(<bang>0)',
\'command! -bar -bang Jumps call fzf#vim#jumps(fzf#vim#with_preview({ "placeholder": "{2..4}"}), <bang>0)',
\'command! -bar -bang Marks call fzf#vim#marks(<bang>0)',
\'command! -bar -bang -nargs=* Marks call fzf#vim#marks(<q-args>, <bang>0)',
\'command! -bar -bang -nargs=* BMarks call fzf#vim#marks("abcdefghijklmnopqrstuvwxyz", <bang>0)',
\'command! -bar -bang Changes call fzf#vim#changes(<bang>0)',
\'command! -bar -bang Helptags call fzf#vim#helptags(fzf#vim#with_preview({ "placeholder": "--tag {2}:{3}:{4}" }), <bang>0)',
\'command! -bar -bang Windows call fzf#vim#windows(fzf#vim#with_preview({ "placeholder": "{2}" }), <bang>0)',