Add --header-file option

This commit is contained in:
Junegunn Choi 2015-07-22 00:19:37 +09:00
parent c9abe1b1ff
commit d459e9abce
4 changed files with 62 additions and 11 deletions

View File

@ -122,6 +122,7 @@ e.g. \fBfzf --color=bg+:24\fR
\fBpointer \fRPointer to the current line \fBpointer \fRPointer to the current line
\fBmarker \fRMulti-select marker \fBmarker \fRMulti-select marker
\fBspinner \fRStreaming input indicator \fBspinner \fRStreaming input indicator
\fBheader \fRHeader
.RE .RE
.TP .TP
.B "--black" .B "--black"

View File

@ -94,6 +94,7 @@ const (
ColInfo ColInfo
ColCursor ColCursor
ColSelected ColSelected
ColHeader
ColUser ColUser
) )
@ -114,6 +115,7 @@ type ColorTheme struct {
Info int16 Info int16
Cursor int16 Cursor int16
Selected int16 Selected int16
Header int16
} }
type Event struct { type Event struct {
@ -164,7 +166,8 @@ func init() {
Spinner: C.COLOR_GREEN, Spinner: C.COLOR_GREEN,
Info: C.COLOR_WHITE, Info: C.COLOR_WHITE,
Cursor: C.COLOR_RED, Cursor: C.COLOR_RED,
Selected: C.COLOR_MAGENTA} Selected: C.COLOR_MAGENTA,
Header: C.COLOR_CYAN}
Dark256 = &ColorTheme{ Dark256 = &ColorTheme{
UseDefault: true, UseDefault: true,
Fg: 15, Fg: 15,
@ -177,7 +180,8 @@ func init() {
Spinner: 148, Spinner: 148,
Info: 144, Info: 144,
Cursor: 161, Cursor: 161,
Selected: 168} Selected: 168,
Header: 110}
Light256 = &ColorTheme{ Light256 = &ColorTheme{
UseDefault: true, UseDefault: true,
Fg: 15, Fg: 15,
@ -190,7 +194,8 @@ func init() {
Spinner: 65, Spinner: 65,
Info: 101, Info: 101,
Cursor: 161, Cursor: 161,
Selected: 168} Selected: 168,
Header: 31}
} }
func attrColored(pair int, bold bool) C.int { func attrColored(pair int, bold bool) C.int {
@ -308,6 +313,7 @@ func initPairs(theme *ColorTheme, black bool) {
C.init_pair(ColInfo, C.short(theme.Info), bg) C.init_pair(ColInfo, C.short(theme.Info), bg)
C.init_pair(ColCursor, C.short(theme.Cursor), darkBG) C.init_pair(ColCursor, C.short(theme.Cursor), darkBG)
C.init_pair(ColSelected, C.short(theme.Selected), darkBG) C.init_pair(ColSelected, C.short(theme.Selected), darkBG)
C.init_pair(ColHeader, C.short(theme.Header), bg)
} }
func Close() { func Close() {

View File

@ -2,6 +2,7 @@ package fzf
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"regexp" "regexp"
"strconv" "strconv"
@ -44,6 +45,7 @@ const usage = `usage: fzf [options]
--bind=KEYBINDS Custom key bindings. Refer to the man page. --bind=KEYBINDS Custom key bindings. Refer to the man page.
--history=FILE History file --history=FILE History file
--history-size=N Maximum number of history entries (default: 1000) --history-size=N Maximum number of history entries (default: 1000)
--header-file=N Header file
Scripting Scripting
-q, --query=STR Start the finder with the given query -q, --query=STR Start the finder with the given query
@ -122,6 +124,7 @@ type Options struct {
ReadZero bool ReadZero bool
Sync bool Sync bool
History *History History *History
Header []string
Version bool Version bool
} }
@ -164,6 +167,7 @@ func defaultOptions() *Options {
ReadZero: false, ReadZero: false,
Sync: false, Sync: false,
History: nil, History: nil,
Header: make([]string, 0),
Version: false} Version: false}
} }
@ -413,6 +417,8 @@ func parseTheme(defaultTheme *curses.ColorTheme, str string) *curses.ColorTheme
theme.Cursor = ansi theme.Cursor = ansi
case "marker": case "marker":
theme.Selected = ansi theme.Selected = ansi
case "header":
theme.Header = ansi
default: default:
fail() fail()
} }
@ -571,6 +577,14 @@ func checkToggleSort(keymap map[int]actionType, str string) map[int]actionType {
return keymap return keymap
} }
func readHeaderFile(filename string) []string {
content, err := ioutil.ReadFile(filename)
if err != nil {
errorExit("failed to read header file: " + filename)
}
return strings.Split(strings.TrimSuffix(string(content), "\n"), "\n")
}
func parseOptions(opts *Options, allArgs []string) { func parseOptions(opts *Options, allArgs []string) {
keymap := make(map[int]actionType) keymap := make(map[int]actionType)
var historyMax int var historyMax int
@ -710,6 +724,9 @@ func parseOptions(opts *Options, allArgs []string) {
setHistory(nextString(allArgs, &i, "history file path required")) setHistory(nextString(allArgs, &i, "history file path required"))
case "--history-size": case "--history-size":
setHistoryMax(nextInt(allArgs, &i, "history max size required")) setHistoryMax(nextInt(allArgs, &i, "history max size required"))
case "--header-file":
opts.Header = readHeaderFile(
nextString(allArgs, &i, "header file name required"))
case "--version": case "--version":
opts.Version = true opts.Version = true
default: default:
@ -743,6 +760,8 @@ func parseOptions(opts *Options, allArgs []string) {
setHistory(value) setHistory(value)
} else if match, value := optString(arg, "--history-size="); match { } else if match, value := optString(arg, "--history-size="); match {
setHistoryMax(atoi(value)) setHistoryMax(atoi(value))
} else if match, value := optString(arg, "--header-file="); match {
opts.Header = readHeaderFile(value)
} else { } else {
errorExit("unknown option: " + arg) errorExit("unknown option: " + arg)
} }

View File

@ -40,6 +40,7 @@ type Terminal struct {
printQuery bool printQuery bool
history *History history *History
cycle bool cycle bool
header []string
count int count int
progress int progress int
reading bool reading bool
@ -197,6 +198,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
printQuery: opts.PrintQuery, printQuery: opts.PrintQuery,
history: opts.History, history: opts.History,
cycle: opts.Cycle, cycle: opts.Cycle,
header: opts.Header,
reading: true, reading: true,
merger: EmptyMerger, merger: EmptyMerger,
selected: make(map[uint32]selectedItem), selected: make(map[uint32]selectedItem),
@ -354,17 +356,39 @@ func (t *Terminal) printInfo() {
C.CPrint(C.ColInfo, false, output) C.CPrint(C.ColInfo, false, output)
} }
func (t *Terminal) printHeader() {
if len(t.header) == 0 {
return
}
for idx, lineStr := range t.header {
if !t.reverse {
idx = len(t.header) - idx - 1
}
trimmed, colors := extractColor(&lineStr)
item := &Item{
text: trimmed,
index: 0,
colors: colors,
rank: Rank{0, 0, 0}}
line := idx + 2
if t.inlineInfo {
line -= 1
}
t.move(line, 2, true)
t.printHighlighted(item, false, C.ColHeader, 0, false)
}
}
func (t *Terminal) printList() { func (t *Terminal) printList() {
t.constrain() t.constrain()
maxy := t.maxItems() maxy := t.maxItems()
count := t.merger.Length() - t.offset count := t.merger.Length() - t.offset
for i := 0; i < maxy; i++ { for i := 0; i < maxy; i++ {
var line int line := i + 2 + len(t.header)
if t.inlineInfo { if t.inlineInfo {
line = i + 1 line -= 1
} else {
line = i + 2
} }
t.move(line, 0, true) t.move(line, 0, true)
if i < count { if i < count {
@ -606,6 +630,7 @@ func (t *Terminal) Loop() {
t.placeCursor() t.placeCursor()
C.Refresh() C.Refresh()
t.printInfo() t.printInfo()
t.printHeader()
t.mutex.Unlock() t.mutex.Unlock()
go func() { go func() {
timer := time.NewTimer(initialDelay) timer := time.NewTimer(initialDelay)
@ -883,9 +908,9 @@ func (t *Terminal) Loop() {
if !t.reverse { if !t.reverse {
my = C.MaxY() - my - 1 my = C.MaxY() - my - 1
} }
min := 2 min := 2 + len(t.header)
if t.inlineInfo { if t.inlineInfo {
min = 1 min -= 1
} }
if me.S != 0 { if me.S != 0 {
// Scroll // Scroll
@ -977,7 +1002,7 @@ func (t *Terminal) vset(o int) bool {
func (t *Terminal) maxItems() int { func (t *Terminal) maxItems() int {
if t.inlineInfo { if t.inlineInfo {
return C.MaxY() - 1 return C.MaxY() - 1 - len(t.header)
} }
return C.MaxY() - 2 return C.MaxY() - 2 - len(t.header)
} }