summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2016-09-25 02:02:00 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2016-09-25 02:02:00 +0900
commit66d55fd89349b38e61ba2180ea8e7d8e5656c878 (patch)
tree1d317b4ff4d2c84d1c205be016fb7dc7f726dca6
parent7fa5e6c86184b3127f64ce0f7a45b945df077e77 (diff)
Make preview windows scrollable
Close #669 You can use your mouse or binadble preview-up and preview-down actions to scroll the content of the preview window. fzf --preview 'highlight -O ansi {}' --bind alt-j:preview-down,alt-k:preview-up
-rw-r--r--src/options.go4
-rw-r--r--src/terminal.go72
2 files changed, 67 insertions, 9 deletions
diff --git a/src/options.go b/src/options.go
index 6ff71c0f..3b412f83 100644
--- a/src/options.go
+++ b/src/options.go
@@ -663,6 +663,10 @@ 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
default:
if isExecuteAction(actLower) {
var offset int
diff --git a/src/terminal.go b/src/terminal.go
index 0e9436a7..9bb92629 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -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,8 @@ const (
actPrintQuery
actToggleSort
actTogglePreview
+ actPreviewUp
+ actPreviewDown
actPreviousHistory
actNextHistory
actExecute
@@ -275,8 +284,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 +780,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 +925,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 +1067,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()
@@ -1118,10 +1156,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 +1169,18 @@ func (t *Terminal) Loop() {
t.eventBox.Set(EvtSearchNew, t.sort)
t.mutex.Unlock()
return false
+ case actPreviewUp:
+ if t.isPreviewEnabled() {
+ t.previewer.offset = util.Constrain(
+ t.previewer.offset-1, 0, t.previewer.lines-t.pwindow.Height)
+ req(reqPreviewRefresh)
+ }
+ case actPreviewDown:
+ if t.isPreviewEnabled() {
+ t.previewer.offset = util.Constrain(
+ t.previewer.offset+1, 0, t.previewer.lines-t.pwindow.Height)
+ req(reqPreviewRefresh)
+ }
case actBeginningOfLine:
t.cx = 0
case actBackwardChar:
@@ -1299,6 +1349,10 @@ func (t *Terminal) Loop() {
}
t.vmove(me.S)
req(reqList)
+ } else if t.isPreviewEnabled() && t.pwindow.Enclose(my, mx) {
+ t.previewer.offset = util.Constrain(
+ t.previewer.offset-me.S, 0, t.previewer.lines-t.pwindow.Height)
+ req(reqPreviewRefresh)
}
} else if t.window.Enclose(my, mx) {
mx -= t.window.Left