mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-14 22:33:47 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bc223d4b3 | ||
|
|
bef405bfa5 | ||
|
|
0612074abe | ||
|
|
3bf51d8362 | ||
|
|
2c8479a7c5 | ||
|
|
8c8b5b313e | ||
|
|
66d55fd893 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,6 +1,17 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
0.15.2
|
||||
------
|
||||
- Preview window is now scrollable
|
||||
- With mouse scroll or with bindable actions
|
||||
- `preview-up`
|
||||
- `preview-down`
|
||||
- `preview-page-up`
|
||||
- `preview-page-down`
|
||||
- Updated ANSI processor to support high intensity colors and ignore
|
||||
some VT100-related escape sequences
|
||||
|
||||
0.15.1
|
||||
------
|
||||
- Fixed panic when the pattern occurs after 2^15-th column
|
||||
|
||||
4
install
4
install
@@ -2,8 +2,8 @@
|
||||
|
||||
set -u
|
||||
|
||||
[[ "$@" =~ --pre ]] && version=0.15.1 pre=1 ||
|
||||
version=0.15.1 pre=0
|
||||
[[ "$@" =~ --pre ]] && version=0.15.2 pre=1 ||
|
||||
version=0.15.2 pre=0
|
||||
|
||||
auto_completion=
|
||||
key_bindings=
|
||||
|
||||
@@ -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 "Sep 2016" "fzf 0.15.1" "fzf-tmux - open fzf in tmux split pane"
|
||||
.TH fzf-tmux 1 "Sep 2016" "fzf 0.15.2" "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 "Sep 2016" "fzf 0.15.1" "fzf - a command-line fuzzy finder"
|
||||
.TH fzf 1 "Sep 2016" "fzf 0.15.2" "fzf - a command-line fuzzy finder"
|
||||
|
||||
.SH NAME
|
||||
fzf - a command-line fuzzy finder
|
||||
|
||||
@@ -32,7 +32,7 @@ fi
|
||||
|
||||
_fzf_orig_completion_filter() {
|
||||
sed 's/^\(.*-F\) *\([^ ]*\).* \([^ ]*\)$/export _fzf_orig_completion_\3="\1 %s \3 #\2";/' |
|
||||
awk -F= '{gsub(/[^a-z0-9_= ;]/, "_", $1); print $1"="$2}'
|
||||
awk -F= '{gsub(/[^A-Za-z0-9_= ;]/, "_", $1); print $1"="$2}'
|
||||
}
|
||||
|
||||
_fzf_opts_completion() {
|
||||
@@ -117,7 +117,7 @@ _fzf_handle_dynamic_completion() {
|
||||
__fzf_generic_path_completion() {
|
||||
local cur base dir leftover matches trigger cmd fzf
|
||||
[ "${FZF_TMUX:-1}" != 0 ] && fzf="fzf-tmux -d ${FZF_TMUX_HEIGHT:-40%}" || fzf="fzf"
|
||||
cmd=$(echo "${COMP_WORDS[0]}" | sed 's/[^a-z0-9_=]/_/g')
|
||||
cmd="${COMP_WORDS[0]//[^A-Za-z0-9_=]/_}"
|
||||
COMPREPLY=()
|
||||
trigger=${FZF_COMPLETION_TRIGGER-'**'}
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
@@ -162,7 +162,7 @@ _fzf_complete() {
|
||||
type -t "$post" > /dev/null 2>&1 || post=cat
|
||||
[ "${FZF_TMUX:-1}" != 0 ] && fzf="fzf-tmux -d ${FZF_TMUX_HEIGHT:-40%}" || fzf="fzf"
|
||||
|
||||
cmd=$(echo "${COMP_WORDS[0]}" | sed 's/[^a-z0-9_=]/_/g')
|
||||
cmd="${COMP_WORDS[0]//[^A-Za-z0-9_=]/_}"
|
||||
trigger=${FZF_COMPLETION_TRIGGER-'**'}
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
if [[ "$cur" == *"$trigger" ]]; then
|
||||
@@ -277,7 +277,7 @@ _fzf_defc() {
|
||||
cmd="$1"
|
||||
func="$2"
|
||||
opts="$3"
|
||||
orig_var="_fzf_orig_completion_$cmd"
|
||||
orig_var="_fzf_orig_completion_${cmd//[^A-Za-z0-9_]/_}"
|
||||
orig="${!orig_var}"
|
||||
if [ -n "$orig" ]; then
|
||||
printf -v def "$orig" "$func"
|
||||
|
||||
@@ -33,7 +33,7 @@ func (s *ansiState) equals(t *ansiState) bool {
|
||||
var ansiRegex *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
ansiRegex = regexp.MustCompile("\x1b\\[[0-9;]*[mK]")
|
||||
ansiRegex = regexp.MustCompile("\x1b.[0-9;]*.")
|
||||
}
|
||||
|
||||
func extractColor(str string, state *ansiState, proc func(string, *ansiState) bool) (string, *[]ansiOffset, *ansiState) {
|
||||
@@ -98,7 +98,7 @@ func interpretCode(ansiCode string, prevState *ansiState) *ansiState {
|
||||
} else {
|
||||
state = &ansiState{prevState.fg, prevState.bg, prevState.bold}
|
||||
}
|
||||
if ansiCode[len(ansiCode)-1] == 'K' {
|
||||
if ansiCode[1] != '[' || ansiCode[len(ansiCode)-1] != 'm' {
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -140,6 +140,10 @@ func interpretCode(ansiCode string, prevState *ansiState) *ansiState {
|
||||
state.fg = num - 30
|
||||
} else if num >= 40 && num <= 47 {
|
||||
state.bg = num - 40
|
||||
} else if num >= 90 && num <= 97 {
|
||||
state.fg = num - 90 + 8
|
||||
} else if num >= 100 && num <= 107 {
|
||||
state.bg = num - 100 + 8
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
const (
|
||||
// Current version
|
||||
version = "0.15.1"
|
||||
version = "0.15.2"
|
||||
|
||||
// Core
|
||||
coordinatorDelayMax time.Duration = 100 * time.Millisecond
|
||||
|
||||
@@ -663,6 +663,14 @@ func parseKeymap(keymap map[int]actionType, execmap map[int]string, str string)
|
||||
keymap[key] = actTogglePreview
|
||||
case "toggle-sort":
|
||||
keymap[key] = actToggleSort
|
||||
case "preview-up":
|
||||
keymap[key] = actPreviewUp
|
||||
case "preview-down":
|
||||
keymap[key] = actPreviewDown
|
||||
case "preview-page-up":
|
||||
keymap[key] = actPreviewPageUp
|
||||
case "preview-page-down":
|
||||
keymap[key] = actPreviewPageDown
|
||||
default:
|
||||
if isExecuteAction(actLower) {
|
||||
var offset int
|
||||
|
||||
@@ -28,6 +28,13 @@ const (
|
||||
jumpAcceptEnabled
|
||||
)
|
||||
|
||||
type previewer struct {
|
||||
text string
|
||||
lines int
|
||||
offset int
|
||||
enabled bool
|
||||
}
|
||||
|
||||
// Terminal represents terminal input/output
|
||||
type Terminal struct {
|
||||
initDelay time.Duration
|
||||
@@ -68,8 +75,7 @@ type Terminal struct {
|
||||
selected map[int32]selectedItem
|
||||
reqBox *util.EventBox
|
||||
preview previewOpts
|
||||
previewing bool
|
||||
previewTxt string
|
||||
previewer previewer
|
||||
previewBox *util.EventBox
|
||||
eventBox *util.EventBox
|
||||
mutex sync.Mutex
|
||||
@@ -119,6 +125,7 @@ const (
|
||||
reqPrintQuery
|
||||
reqPreviewEnqueue
|
||||
reqPreviewDisplay
|
||||
reqPreviewRefresh
|
||||
reqQuit
|
||||
)
|
||||
|
||||
@@ -165,6 +172,10 @@ const (
|
||||
actPrintQuery
|
||||
actToggleSort
|
||||
actTogglePreview
|
||||
actPreviewUp
|
||||
actPreviewDown
|
||||
actPreviewPageUp
|
||||
actPreviewPageDown
|
||||
actPreviousHistory
|
||||
actNextHistory
|
||||
actExecute
|
||||
@@ -275,8 +286,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
||||
selected: make(map[int32]selectedItem),
|
||||
reqBox: util.NewEventBox(),
|
||||
preview: opts.Preview,
|
||||
previewing: previewBox != nil && !opts.Preview.hidden,
|
||||
previewTxt: "",
|
||||
previewer: previewer{"", 0, 0, previewBox != nil && !opts.Preview.hidden},
|
||||
previewBox: previewBox,
|
||||
eventBox: eventBox,
|
||||
mutex: sync.Mutex{},
|
||||
@@ -772,9 +782,35 @@ func (t *Terminal) printHighlighted(result *Result, bold bool, col1 int, col2 in
|
||||
}
|
||||
}
|
||||
|
||||
func numLinesMax(str string, max int) int {
|
||||
lines := 0
|
||||
for lines < max {
|
||||
idx := strings.Index(str, "\n")
|
||||
if idx < 0 {
|
||||
break
|
||||
}
|
||||
str = str[idx+1:]
|
||||
lines++
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
func (t *Terminal) printPreview() {
|
||||
t.pwindow.Erase()
|
||||
extractColor(t.previewTxt, nil, func(str string, ansi *ansiState) bool {
|
||||
skip := t.previewer.offset
|
||||
extractColor(t.previewer.text, nil, func(str string, ansi *ansiState) bool {
|
||||
if skip > 0 {
|
||||
newlines := numLinesMax(str, skip)
|
||||
if skip <= newlines {
|
||||
for i := 0; i < skip; i++ {
|
||||
str = str[strings.Index(str, "\n")+1:]
|
||||
}
|
||||
skip = 0
|
||||
} else {
|
||||
skip -= newlines
|
||||
return true
|
||||
}
|
||||
}
|
||||
if ansi != nil && ansi.colored() {
|
||||
return t.pwindow.CFill(str, ansi.fg, ansi.bg, ansi.bold)
|
||||
}
|
||||
@@ -891,7 +927,7 @@ func (t *Terminal) hasPreviewWindow() bool {
|
||||
}
|
||||
|
||||
func (t *Terminal) isPreviewEnabled() bool {
|
||||
return t.previewBox != nil && t.previewing
|
||||
return t.previewBox != nil && t.previewer.enabled
|
||||
}
|
||||
|
||||
func (t *Terminal) current() string {
|
||||
@@ -1033,7 +1069,11 @@ func (t *Terminal) Loop() {
|
||||
}
|
||||
exit(exitNoMatch)
|
||||
case reqPreviewDisplay:
|
||||
t.previewTxt = value.(string)
|
||||
t.previewer.text = value.(string)
|
||||
t.previewer.lines = strings.Count(t.previewer.text, "\n")
|
||||
t.previewer.offset = 0
|
||||
t.printPreview()
|
||||
case reqPreviewRefresh:
|
||||
t.printPreview()
|
||||
case reqPrintQuery:
|
||||
C.Close()
|
||||
@@ -1085,6 +1125,11 @@ func (t *Terminal) Loop() {
|
||||
req(reqInfo)
|
||||
}
|
||||
}
|
||||
scrollPreview := func(amount int) {
|
||||
t.previewer.offset = util.Constrain(
|
||||
t.previewer.offset+amount, 0, t.previewer.lines-t.pwindow.Height)
|
||||
req(reqPreviewRefresh)
|
||||
}
|
||||
for key, ret := range t.expect {
|
||||
if keyMatch(key, event) {
|
||||
t.pressed = ret
|
||||
@@ -1118,10 +1163,10 @@ func (t *Terminal) Loop() {
|
||||
return false
|
||||
case actTogglePreview:
|
||||
if t.hasPreviewWindow() {
|
||||
t.previewing = !t.previewing
|
||||
t.previewer.enabled = !t.previewer.enabled
|
||||
t.resizeWindows()
|
||||
cnt := t.merger.Length()
|
||||
if t.previewing && cnt > 0 && cnt > t.cy {
|
||||
if t.previewer.enabled && cnt > 0 && cnt > t.cy {
|
||||
t.previewBox.Set(reqPreviewEnqueue, previewRequest{true, t.current()})
|
||||
}
|
||||
req(reqList, reqInfo)
|
||||
@@ -1131,6 +1176,22 @@ func (t *Terminal) Loop() {
|
||||
t.eventBox.Set(EvtSearchNew, t.sort)
|
||||
t.mutex.Unlock()
|
||||
return false
|
||||
case actPreviewUp:
|
||||
if t.isPreviewEnabled() {
|
||||
scrollPreview(-1)
|
||||
}
|
||||
case actPreviewDown:
|
||||
if t.isPreviewEnabled() {
|
||||
scrollPreview(1)
|
||||
}
|
||||
case actPreviewPageUp:
|
||||
if t.isPreviewEnabled() {
|
||||
scrollPreview(-t.pwindow.Height)
|
||||
}
|
||||
case actPreviewPageDown:
|
||||
if t.isPreviewEnabled() {
|
||||
scrollPreview(t.pwindow.Height)
|
||||
}
|
||||
case actBeginningOfLine:
|
||||
t.cx = 0
|
||||
case actBackwardChar:
|
||||
@@ -1299,6 +1360,8 @@ func (t *Terminal) Loop() {
|
||||
}
|
||||
t.vmove(me.S)
|
||||
req(reqList)
|
||||
} else if t.isPreviewEnabled() && t.pwindow.Enclose(my, mx) {
|
||||
scrollPreview(-me.S)
|
||||
}
|
||||
} else if t.window.Enclose(my, mx) {
|
||||
mx -= t.window.Left
|
||||
|
||||
Reference in New Issue
Block a user