Replace --header-file with --header (#346)

and allow using --header and --header-lines at the same time.

Close #346.
This commit is contained in:
Junegunn Choi 2015-09-15 19:04:53 +09:00
parent 65d9d416b4
commit 2022a3ad96
7 changed files with 71 additions and 45 deletions

View File

@ -1,6 +1,16 @@
CHANGELOG CHANGELOG
========= =========
0.10.6
------
- Replaced `--header-file` with `--header` option
- `--header` and `--header-lines` can be used together
- Changed exit status
- 0: Okay
- 1: No match
- 2: Error/Interrupted
0.10.5 0.10.5
------ ------

View File

@ -285,11 +285,11 @@ When enabled, \fBCTRL-N\fR and \fBCTRL-P\fR are automatically remapped to
Maximum number of entries in the history file (default: 1000). The file is Maximum number of entries in the history file (default: 1000). The file is
automatically truncated when the number of the lines exceeds the value. automatically truncated when the number of the lines exceeds the value.
.TP .TP
.BI "--header-file=" "FILE" .BI "--header=" "STR"
The content of the file will be printed as the sticky header. The lines in the The given string will be printed as the sticky header. The lines are displayed
file are displayed in order from top to bottom regardless of \fB--reverse\fR, in the given order from top to bottom regardless of \fB--reverse\fR option, and
and are not affected by \fB--with-nth\fR. ANSI color codes are processed even are not affected by \fB--with-nth\fR. ANSI color codes are processed even when
when \fB--ansi\fR is not set. \fB--ansi\fR is not set.
.TP .TP
.BI "--header-lines=" "N" .BI "--header-lines=" "N"
The first N lines of the input are treated as the sticky header. When The first N lines of the input are treated as the sticky header. When

View File

@ -49,7 +49,7 @@ _fzf_opts_completion() {
--cycle --cycle
--history --history
--history-size --history-size
--header-file --header
--header-lines --header-lines
--margin" --margin"
@ -62,7 +62,7 @@ _fzf_opts_completion() {
COMPREPLY=( $(compgen -W "dark light 16 bw" -- ${cur}) ) COMPREPLY=( $(compgen -W "dark light 16 bw" -- ${cur}) )
return 0 return 0
;; ;;
--history|--header-file) --history)
COMPREPLY=() COMPREPLY=()
return 0 return 0
;; ;;

View File

@ -238,7 +238,7 @@ func Run(opts *Options) {
} }
case EvtHeader: case EvtHeader:
terminal.UpdateHeader(value.([]string), opts.HeaderLines) terminal.UpdateHeader(value.([]string))
case EvtSearchFin: case EvtSearchFin:
switch val := value.(type) { switch val := value.(type) {

View File

@ -1,7 +1,6 @@
package fzf package fzf
import ( import (
"io/ioutil"
"os" "os"
"regexp" "regexp"
"strconv" "strconv"
@ -45,7 +44,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=FILE The file whose content to be printed as header --header=STR String to print as header
--header-lines=N The first N lines of the input are treated as header --header-lines=N The first N lines of the input are treated as header
Scripting Scripting
@ -604,12 +603,8 @@ func checkToggleSort(keymap map[int]actionType, str string) map[int]actionType {
return keymap return keymap
} }
func readHeaderFile(filename string) []string { func strLines(str string) []string {
content, err := ioutil.ReadFile(filename) return strings.Split(strings.TrimSuffix(str, "\n"), "\n")
if err != nil {
errorExit("failed to read header file: " + filename)
}
return strings.Split(strings.TrimSuffix(string(content), "\n"), "\n")
} }
func parseMargin(margin string) [4]string { func parseMargin(margin string) [4]string {
@ -793,16 +788,13 @@ 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 "--no-header-file": case "--no-header":
opts.Header = []string{} opts.Header = []string{}
case "--no-header-lines": case "--no-header-lines":
opts.HeaderLines = 0 opts.HeaderLines = 0
case "--header-file": case "--header":
opts.Header = readHeaderFile( opts.Header = strLines(nextString(allArgs, &i, "header string required"))
nextString(allArgs, &i, "header file name required"))
opts.HeaderLines = 0
case "--header-lines": case "--header-lines":
opts.Header = []string{}
opts.HeaderLines = atoi( opts.HeaderLines = atoi(
nextString(allArgs, &i, "number of header lines required")) nextString(allArgs, &i, "number of header lines required"))
case "--no-margin": case "--no-margin":
@ -843,11 +835,9 @@ 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 { } else if match, value := optString(arg, "--header="); match {
opts.Header = readHeaderFile(value) opts.Header = strLines(value)
opts.HeaderLines = 0
} else if match, value := optString(arg, "--header-lines="); match { } else if match, value := optString(arg, "--header-lines="); match {
opts.Header = []string{}
opts.HeaderLines = atoi(value) opts.HeaderLines = atoi(value)
} else if match, value := optString(arg, "--margin="); match { } else if match, value := optString(arg, "--margin="); match {
opts.Margin = parseMargin(value) opts.Margin = parseMargin(value)

View File

@ -42,6 +42,7 @@ type Terminal struct {
history *History history *History
cycle bool cycle bool
header []string header []string
header0 []string
ansi bool ansi bool
margin [4]string margin [4]string
marginInt [4]int marginInt [4]int
@ -185,6 +186,12 @@ func defaultKeymap() map[int]actionType {
// NewTerminal returns new Terminal object // NewTerminal returns new Terminal object
func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
input := []rune(opts.Query) input := []rune(opts.Query)
var header []string
if opts.Reverse {
header = opts.Header
} else {
header = reverseStringArray(opts.Header)
}
return &Terminal{ return &Terminal{
inlineInfo: opts.InlineInfo, inlineInfo: opts.InlineInfo,
prompt: opts.Prompt, prompt: opts.Prompt,
@ -207,7 +214,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
margin: opts.Margin, margin: opts.Margin,
marginInt: [4]int{0, 0, 0, 0}, marginInt: [4]int{0, 0, 0, 0},
cycle: opts.Cycle, cycle: opts.Cycle,
header: opts.Header, header: header,
header0: header,
ansi: opts.Ansi, ansi: opts.Ansi,
reading: true, reading: true,
merger: EmptyMerger, merger: EmptyMerger,
@ -241,18 +249,19 @@ func (t *Terminal) UpdateCount(cnt int, final bool) {
} }
} }
// UpdateHeader updates the header func reverseStringArray(input []string) []string {
func (t *Terminal) UpdateHeader(header []string, lines int) { size := len(input)
t.mutex.Lock() reversed := make([]string, size)
t.header = make([]string, lines) for idx, str := range input {
copy(t.header, header) reversed[size-idx-1] = str
if !t.reverse {
reversed := make([]string, lines)
for idx, str := range t.header {
reversed[lines-idx-1] = str
}
t.header = reversed
} }
return reversed
}
// UpdateHeader updates the header
func (t *Terminal) UpdateHeader(header []string) {
t.mutex.Lock()
t.header = append(append([]string{}, t.header0...), header...)
t.mutex.Unlock() t.mutex.Unlock()
t.reqBox.Set(reqHeader, nil) t.reqBox.Set(reqHeader, nil)
} }
@ -436,9 +445,6 @@ func (t *Terminal) printHeader() {
max := t.maxHeight() max := t.maxHeight()
var state *ansiState var state *ansiState
for idx, lineStr := range t.header { for idx, lineStr := range t.header {
if !t.reverse {
idx = len(t.header) - idx - 1
}
line := idx + 2 line := idx + 2
if t.inlineInfo { if t.inlineInfo {
line-- line--

View File

@ -737,8 +737,8 @@ class TestGoFZF < TestBase
assert_equal '6', readonce.chomp assert_equal '6', readonce.chomp
end end
def test_header_file def test_header
tmux.send_keys "seq 100 | #{fzf "--header-file <(head -5 #{__FILE__})"}", :Enter tmux.send_keys "seq 100 | #{fzf "--header \\\"\\$(head -5 #{__FILE__})\\\""}", :Enter
header = File.readlines(__FILE__).take(5).map(&:strip) header = File.readlines(__FILE__).take(5).map(&:strip)
tmux.until do |lines| tmux.until do |lines|
lines[-2].include?('100/100') && lines[-2].include?('100/100') &&
@ -746,8 +746,8 @@ class TestGoFZF < TestBase
end end
end end
def test_header_file_reverse def test_header_reverse
tmux.send_keys "seq 100 | #{fzf "--header-file=<(head -5 #{__FILE__}) --reverse"}", :Enter tmux.send_keys "seq 100 | #{fzf "--header=\\\"\\$(head -5 #{__FILE__})\\\" --reverse"}", :Enter
header = File.readlines(__FILE__).take(5).map(&:strip) header = File.readlines(__FILE__).take(5).map(&:strip)
tmux.until do |lines| tmux.until do |lines|
lines[1].include?('100/100') && lines[1].include?('100/100') &&
@ -755,6 +755,26 @@ class TestGoFZF < TestBase
end end
end end
def test_header_and_header_lines
tmux.send_keys "seq 100 | #{fzf "--header-lines 10 --header \\\"\\$(head -5 #{__FILE__})\\\""}", :Enter
header = File.readlines(__FILE__).take(5).map(&:strip)
tmux.until do |lines|
lines[-2].include?('90/90') &&
lines[-7...-2].map(&:strip) == header &&
lines[-17...-7].map(&:strip) == (1..10).map(&:to_s).reverse
end
end
def test_header_and_header_lines_reverse
tmux.send_keys "seq 100 | #{fzf "--reverse --header-lines 10 --header \\\"\\$(head -5 #{__FILE__})\\\""}", :Enter
header = File.readlines(__FILE__).take(5).map(&:strip)
tmux.until do |lines|
lines[1].include?('90/90') &&
lines[2...7].map(&:strip) == header &&
lines[7...17].map(&:strip) == (1..10).map(&:to_s)
end
end
def test_canel def test_canel
tmux.send_keys "seq 10 | #{fzf "--bind 2:cancel"}", :Enter tmux.send_keys "seq 10 | #{fzf "--bind 2:cancel"}", :Enter
tmux.until { |lines| lines[-2].include?('10/10') } tmux.until { |lines| lines[-2].include?('10/10') }