summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/options.go298
-rw-r--r--src/terminal.go49
2 files changed, 184 insertions, 163 deletions
diff --git a/src/options.go b/src/options.go
index d536dae6..1b57fe16 100644
--- a/src/options.go
+++ b/src/options.go
@@ -66,7 +66,8 @@ const usage = `usage: fzf [options]
--border-label=LABEL Label to print on the border
--border-label-pos=COL Position of the border label
[POSITIVE_INTEGER: columns from left|
- NEGATIVE_INTEGER: columns from right] (default: 0)
+ NEGATIVE_INTEGER: columns from right][:bottom]
+ (default: 0 or center)
--margin=MARGIN Screen margin (TRBL | TB,RL | T,RL,B | T,R,B,L)
--padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L)
--info=STYLE Finder info style [default|inline|hidden[:nosep]]
@@ -97,7 +98,8 @@ const usage = `usage: fzf [options]
[,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES]
[,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)]
--preview-label=LABEL
- --preview-label-pos=COL
+ --preview-label-pos=N Same as --border-label and --border-label-pos,
+ but for preview window
Scripting
-q, --query=STR Start the finder with the given query
@@ -183,6 +185,12 @@ const (
infoHidden
)
+type labelOpts struct {
+ label string
+ column int
+ bottom bool
+}
+
type previewOpts struct {
command string
position windowPosition
@@ -198,11 +206,21 @@ type previewOpts struct {
alternative *previewOpts
}
-func parseLabelPosition(arg string) int {
- if strings.ToLower(arg) == "center" {
- return 0
+func parseLabelPosition(opts *labelOpts, arg string) {
+ opts.column = 0
+ opts.bottom = false
+ for _, token := range splitRegexp.Split(strings.ToLower(arg), -1) {
+ switch token {
+ case "center":
+ opts.column = 0
+ case "bottom":
+ opts.bottom = true
+ case "top":
+ opts.bottom = false
+ default:
+ opts.column = atoi(token)
+ }
}
- return atoi(arg)
}
func (a previewOpts) aboveOrBelow() bool {
@@ -221,68 +239,66 @@ func (a previewOpts) sameContentLayout(b previewOpts) bool {
// Options stores the values of command-line options
type Options struct {
- Fuzzy bool
- FuzzyAlgo algo.Algo
- Scheme string
- Extended bool
- Phony bool
- Case Case
- Normalize bool
- Nth []Range
- WithNth []Range
- Delimiter Delimiter
- Sort int
- Tac bool
- Criteria []criterion
- Multi int
- Ansi bool
- Mouse bool
- Theme *tui.ColorTheme
- Black bool
- Bold bool
- Height heightSpec
- MinHeight int
- Layout layoutType
- Cycle bool
- KeepRight bool
- Hscroll bool
- HscrollOff int
- ScrollOff int
- FileWord bool
- InfoStyle infoStyle
- JumpLabels string
- Prompt string
- Pointer string
- Marker string
- Query string
- Select1 bool
- Exit0 bool
- Filter *string
- ToggleSort bool
- Expect map[tui.Event]string
- Keymap map[tui.Event][]*action
- Preview previewOpts
- PrintQuery bool
- ReadZero bool
- Printer func(string)
- PrintSep string
- Sync bool
- History *History
- Header []string
- HeaderLines int
- HeaderFirst bool
- Ellipsis string
- Margin [4]sizeSpec
- Padding [4]sizeSpec
- BorderShape tui.BorderShape
- Label string
- LabelPos int
- PLabel string
- PLabelPos int
- Unicode bool
- Tabstop int
- ClearOnExit bool
- Version bool
+ Fuzzy bool
+ FuzzyAlgo algo.Algo
+ Scheme string
+ Extended bool
+ Phony bool
+ Case Case
+ Normalize bool
+ Nth []Range
+ WithNth []Range
+ Delimiter Delimiter
+ Sort int
+ Tac bool
+ Criteria []criterion
+ Multi int
+ Ansi bool
+ Mouse bool
+ Theme *tui.ColorTheme
+ Black bool
+ Bold bool
+ Height heightSpec
+ MinHeight int
+ Layout layoutType
+ Cycle bool
+ KeepRight bool
+ Hscroll bool
+ HscrollOff int
+ ScrollOff int
+ FileWord bool
+ InfoStyle infoStyle
+ JumpLabels string
+ Prompt string
+ Pointer string
+ Marker string
+ Query string
+ Select1 bool
+ Exit0 bool
+ Filter *string
+ ToggleSort bool
+ Expect map[tui.Event]string
+ Keymap map[tui.Event][]*action
+ Preview previewOpts
+ PrintQuery bool
+ ReadZero bool
+ Printer func(string)
+ PrintSep string
+ Sync bool
+ History *History
+ Header []string
+ HeaderLines int
+ HeaderFirst bool
+ Ellipsis string
+ Margin [4]sizeSpec
+ Padding [4]sizeSpec
+ BorderShape tui.BorderShape
+ BorderLabel labelOpts
+ PreviewLabel labelOpts
+ Unicode bool
+ Tabstop int
+ ClearOnExit bool
+ Version bool
}
func defaultPreviewOpts(command string) previewOpts {
@@ -291,66 +307,64 @@ func defaultPreviewOpts(command string) previewOpts {
func defaultOptions() *Options {
return &Options{
- Fuzzy: true,
- FuzzyAlgo: algo.FuzzyMatchV2,
- Scheme: "default",
- Extended: true,
- Phony: false,
- Case: CaseSmart,
- Normalize: true,
- Nth: make([]Range, 0),
- WithNth: make([]Range, 0),
- Delimiter: Delimiter{},
- Sort: 1000,
- Tac: false,
- Criteria: []criterion{byScore, byLength},
- Multi: 0,
- Ansi: false,
- Mouse: true,
- Theme: tui.EmptyTheme(),
- Black: false,
- Bold: true,
- MinHeight: 10,
- Layout: layoutDefault,
- Cycle: false,
- KeepRight: false,
- Hscroll: true,
- HscrollOff: 10,
- ScrollOff: 0,
- FileWord: false,
- InfoStyle: infoStyle{layout: infoDefault, separator: true},
- JumpLabels: defaultJumpLabels,
- Prompt: "> ",
- Pointer: ">",
- Marker: ">",
- Query: "",
- Select1: false,
- Exit0: false,
- Filter: nil,
- ToggleSort: false,
- Expect: make(map[tui.Event]string),
- Keymap: make(map[tui.Event][]*action),
- Preview: defaultPreviewOpts(""),
- PrintQuery: false,
- ReadZero: false,
- Printer: func(str string) { fmt.Println(str) },
- PrintSep: "\n",
- Sync: false,
- History: nil,
- Header: make([]string, 0),
- HeaderLines: 0,
- HeaderFirst: false,
- Ellipsis: "..",
- Margin: defaultMargin(),
- Padding: defaultMargin(),
- Unicode: true,
- Tabstop: 8,
- Label: "",
- LabelPos: 0,
- PLabel: "",
- PLabelPos: 0,
- ClearOnExit: true,
- Version: false}
+ Fuzzy: true,
+ FuzzyAlgo: algo.FuzzyMatchV2,
+ Scheme: "default",
+ Extended: true,
+ Phony: false,
+ Case: CaseSmart,
+ Normalize: true,
+ Nth: make([]Range, 0),
+ WithNth: make([]Range, 0),
+ Delimiter: Delimiter{},
+ Sort: 1000,
+ Tac: false,
+ Criteria: []criterion{byScore, byLength},
+ Multi: 0,
+ Ansi: false,
+ Mouse: true,
+ Theme: tui.EmptyTheme(),
+ Black: false,
+ Bold: true,
+ MinHeight: 10,
+ Layout: layoutDefault,
+ Cycle: false,
+ KeepRight: false,
+ Hscroll: true,
+ HscrollOff: 10,
+ ScrollOff: 0,
+ FileWord: false,
+ InfoStyle: infoStyle{layout: infoDefault, separator: true},
+ JumpLabels: defaultJumpLabels,
+ Prompt: "> ",
+ Pointer: ">",
+ Marker: ">",
+ Query: "",
+ Select1: false,
+ Exit0: false,
+ Filter: nil,
+ ToggleSort: false,
+ Expect: make(map[tui.Event]string),
+ Keymap: make(map[tui.Event][]*action),
+ Preview: defaultPreviewOpts(""),
+ PrintQuery: false,
+ ReadZero: false,
+ Printer: func(str string) { fmt.Println(str) },
+ PrintSep: "\n",
+ Sync: false,
+ History: nil,
+ Header: make([]string, 0),
+ HeaderLines: 0,
+ HeaderFirst: false,
+ Ellipsis: "..",
+ Margin: defaultMargin(),
+ Padding: defaultMargin(),
+ Unicode: true,
+ Tabstop: 8,
+ BorderLabel: labelOpts{},
+ PreviewLabel: labelOpts{},
+ ClearOnExit: true,
+ Version: false}
}
func help(code int) {
@@ -847,7 +861,10 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) *tui.ColorTheme {
return theme
}
-var executeRegexp *regexp.Regexp
+var (
+ executeRegexp *regexp.Regexp
+ splitRegexp *regexp.Regexp
+)
func firstKey(keymap map[tui.Event]string) tui.Event {
for k := range keymap {
@@ -867,6 +884,7 @@ func init() {
// "~!@#$%^&*;/|".each_char.map { |c| Regexp.escape(c) }.map { |c| "#{c}[^#{c}]*#{c}" }.join('|')
executeRegexp = regexp.MustCompile(
`(?si)[:+](execute(?:-multi|-silent)?|reload|preview|change-prompt|change-preview-window|change-preview|(?:re|un)bind):.+|[:+](execute(?:-multi|-silent)?|reload|preview|change-prompt|change-preview-window|change-preview|(?:re|un)bind)(\([^)]*\)|\[[^\]]*\]|~[^~]*~|![^!]*!|@[^@]*@|\#[^\#]*\#|\$[^\$]*\$|%[^%]*%|\^[^\^]*\^|&[^&]*&|\*[^\*]*\*|;[^;]*;|/[^/]*/|\|[^\|]*\|)`)
+ splitRegexp = regexp.MustCompile("[,:]+")
}
func parseKeymap(keymap map[tui.Event][]*action, str string) {
@@ -1229,7 +1247,7 @@ func parseInfoStyle(str string) infoStyle {
layout := infoDefault
separator := true
- for _, token := range regexp.MustCompile("[,:]").Split(strings.ToLower(str), -1) {
+ for _, token := range splitRegexp.Split(strings.ToLower(str), -1) {
switch token {
case "default":
layout = infoDefault
@@ -1594,16 +1612,20 @@ func parseOptions(opts *Options, allArgs []string) {
case "--border":
hasArg, arg := optionalNextString(allArgs, &i)
opts.BorderShape = parseBorder(arg, !hasArg)
+ case "--no-border-label":
+ opts.BorderLabel.label = ""
case "--border-label":
- opts.Label = nextString(allArgs, &i, "label required")
+ opts.BorderLabel.label = nextString(allArgs, &i, "label required")
case "--border-label-pos":
pos := nextString(allArgs, &i, "label position required (positive or negative integer or 'center')")
- opts.LabelPos = parseLabelPosition(pos)
+ parseLabelPosition(&opts.BorderLabel, pos)
+ case "--no-preview-label":
+ opts.PreviewLabel.label = ""
case "--preview-label":
- opts.PLabel = nextString(allArgs, &i, "preview label required")
+ opts.PreviewLabel.label = nextString(allArgs, &i, "preview label required")
case "--preview-label-pos":
pos := nextString(allArgs, &i, "preview label position required (positive or negative integer or 'center')")
- opts.PLabelPos = parseLabelPosition(pos)
+ parseLabelPosition(&opts.PreviewLabel, pos)
case "--no-unicode":
opts.Unicode = false
case "--unicode":
@@ -1640,13 +1662,13 @@ func parseOptions(opts *Options, allArgs []string) {
} else if match, value := optString(arg, "--border="); match {
opts.BorderShape = parseBorder(value, false)
} else if match, value := optString(arg, "--border-label="); match {
- opts.Label = value
+ opts.BorderLabel.label = value
} else if match, value := optString(arg, "--border-label-pos="); match {
- opts.LabelPos = parseLabelPosition(value)
+ parseLabelPosition(&opts.BorderLabel, value)
} else if match, value := optString(arg, "--preview-label="); match {
- opts.PLabel = value
+ opts.PreviewLabel.label = value
} else if match, value := optString(arg, "--preview-label-pos="); match {
- opts.PLabelPos = parseLabelPosition(value)
+ parseLabelPosition(&opts.PreviewLabel, value)
} else if match, value := optString(arg, "--prompt="); match {
opts.Prompt = value
} else if match, value := optString(arg, "--pointer="); match {
diff --git a/src/terminal.go b/src/terminal.go
index 2764ff85..57055c17 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -114,12 +114,12 @@ type Terminal struct {
spinner []string
prompt func()
promptLen int
- borderLabel func()
+ borderLabel func(tui.Window)
borderLabelLen int
- borderLabelPos int
- previewLabel func()
+ borderLabelOpts labelOpts
+ previewLabel func(tui.Window)
previewLabelLen int
- previewLabelPos int
+ previewLabelOpts labelOpts
pointer string
pointerLen int
pointerEmpty string
@@ -551,9 +551,9 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
unicode: opts.Unicode,
borderShape: opts.BorderShape,
borderLabel: nil,
- borderLabelPos: opts.LabelPos,
+ borderLabelOpts: opts.BorderLabel,
previewLabel: nil,
- previewLabelPos: opts.PLabelPos,
+ previewLabelOpts: opts.PreviewLabel,
cleanExit: opts.ClearOnExit,
paused: opts.Phony,
strong: strongAttr,
@@ -597,12 +597,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
// Pre-calculated empty pointer and marker signs
t.pointerEmpty = strings.Repeat(" ", t.pointerLen)
t.markerEmpty = strings.Repeat(" ", t.markerLen)
- if len(opts.Label) > 0 {
- t.borderLabel, t.borderLabelLen = t.parseBorderLabel(opts.Label)
- }
- if len(opts.PLabel) > 0 {
- t.previewLabel, t.previewLabelLen = t.parseBorderLabel(opts.PLabel)
- }
+ t.borderLabel, t.borderLabelLen = t.parseBorderLabel(opts.BorderLabel.label)
+ t.previewLabel, t.previewLabelLen = t.parseBorderLabel(opts.PreviewLabel.label)
return &t
}
@@ -633,20 +629,23 @@ func (t *Terminal) MaxFitAndPad(opts *Options) (int, int) {
return fit, padHeight
}
-func (t *Terminal) parseBorderLabel(borderLabel string) (func(), int) {
+func (t *Terminal) parseBorderLabel(borderLabel string) (func(tui.Window), int) {
+ if len(borderLabel) == 0 {
+ return nil, 0
+ }
text, colors, _ := extractColor(borderLabel, nil, nil)
runes := []rune(text)
item := &Item{text: util.RunesToChars(runes), colors: colors}
result := Result{item: item}
var offsets []colorOffset
- borderLabelFn := func() {
+ borderLabelFn := func(window tui.Window) {
if offsets == nil {
// tui.Col* are not initialized until renderer.Init()
offsets = result.colorOffsets(nil, t.theme, tui.ColBorderLabel, tui.ColBorderLabel, false)
}
- text, _ := t.trimRight(runes, t.border.Width())
- t.printColoredString(t.border, text, offsets, tui.ColBorderLabel)
+ text, _ := t.trimRight(runes, window.Width())
+ t.printColoredString(window, text, offsets, tui.ColBorderLabel)
}
borderLabelLen := runewidth.StringWidth(text)
return borderLabelFn, borderLabelLen
@@ -1052,7 +1051,7 @@ func (t *Terminal) resizeWindows() {
}
// Print border label
- printLabel := func(window tui.Window, render func(), pos int, length int, borderShape tui.BorderShape) {
+ printLabel := func(window tui.Window, render func(tui.Window), opts labelOpts, length int, borderShape tui.BorderShape) {
if window == nil || render == nil {
return
}
@@ -1060,23 +1059,23 @@ func (t *Terminal) resizeWindows() {
switch borderShape {
case tui.BorderHorizontal, tui.BorderTop, tui.BorderBottom, tui.BorderRounded, tui.BorderSharp:
var col int
- if pos == 0 {
+ if opts.column == 0 {
col = util.Max(0, (window.Width()-length)/2)
- } else if pos < 0 {
- col = util.Max(0, window.Width()+pos+1-length)
+ } else if opts.column < 0 {
+ col = util.Max(0, window.Width()+opts.column+1-length)
} else {
- col = util.Min(pos-1, window.Width()-length)
+ col = util.Min(opts.column-1, window.Width()-length)
}
row := 0
- if borderShape == tui.BorderBottom {
+ if borderShape == tui.BorderBottom || opts.bottom {
row = window.Height() - 1
}
window.Move(row, col)
- render()
+ render(window)
}
}
- printLabel(t.border, t.borderLabel, t.borderLabelPos, t.borderLabelLen, t.borderShape)
- printLabel(t.pborder, t.previewLabel, t.previewLabelPos, t.previewLabelLen, t.previewOpts.border)
+ printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape)
+ printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.previewOpts.border)
for i := 0; i < t.window.Height(); i++ {
t.window.MoveAndClear(i, 0)