|
|
|
@ -4,7 +4,7 @@ import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/junegunn/fzf/src/curses"
|
|
|
|
|
"github.com/junegunn/fzf/src/tui"
|
|
|
|
|
"github.com/junegunn/fzf/src/util"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
@ -133,48 +133,48 @@ func TestParseKeys(t *testing.T) {
|
|
|
|
|
if len(pairs) != 11 {
|
|
|
|
|
t.Error(11)
|
|
|
|
|
}
|
|
|
|
|
check(curses.CtrlZ, "ctrl-z")
|
|
|
|
|
check(curses.AltZ, "alt-z")
|
|
|
|
|
check(curses.F2, "f2")
|
|
|
|
|
check(curses.AltZ+'@', "@")
|
|
|
|
|
check(curses.AltA, "Alt-a")
|
|
|
|
|
check(curses.AltZ+'!', "!")
|
|
|
|
|
check(curses.CtrlA+'g'-'a', "ctrl-G")
|
|
|
|
|
check(curses.AltZ+'J', "J")
|
|
|
|
|
check(curses.AltZ+'g', "g")
|
|
|
|
|
check(curses.AltEnter, "ALT-enter")
|
|
|
|
|
check(curses.AltSpace, "alt-SPACE")
|
|
|
|
|
check(tui.CtrlZ, "ctrl-z")
|
|
|
|
|
check(tui.AltZ, "alt-z")
|
|
|
|
|
check(tui.F2, "f2")
|
|
|
|
|
check(tui.AltZ+'@', "@")
|
|
|
|
|
check(tui.AltA, "Alt-a")
|
|
|
|
|
check(tui.AltZ+'!', "!")
|
|
|
|
|
check(tui.CtrlA+'g'-'a', "ctrl-G")
|
|
|
|
|
check(tui.AltZ+'J', "J")
|
|
|
|
|
check(tui.AltZ+'g', "g")
|
|
|
|
|
check(tui.AltEnter, "ALT-enter")
|
|
|
|
|
check(tui.AltSpace, "alt-SPACE")
|
|
|
|
|
|
|
|
|
|
// Synonyms
|
|
|
|
|
pairs = parseKeyChords("enter,Return,space,tab,btab,esc,up,down,left,right", "")
|
|
|
|
|
if len(pairs) != 9 {
|
|
|
|
|
t.Error(9)
|
|
|
|
|
}
|
|
|
|
|
check(curses.CtrlM, "Return")
|
|
|
|
|
check(curses.AltZ+' ', "space")
|
|
|
|
|
check(curses.Tab, "tab")
|
|
|
|
|
check(curses.BTab, "btab")
|
|
|
|
|
check(curses.ESC, "esc")
|
|
|
|
|
check(curses.Up, "up")
|
|
|
|
|
check(curses.Down, "down")
|
|
|
|
|
check(curses.Left, "left")
|
|
|
|
|
check(curses.Right, "right")
|
|
|
|
|
check(tui.CtrlM, "Return")
|
|
|
|
|
check(tui.AltZ+' ', "space")
|
|
|
|
|
check(tui.Tab, "tab")
|
|
|
|
|
check(tui.BTab, "btab")
|
|
|
|
|
check(tui.ESC, "esc")
|
|
|
|
|
check(tui.Up, "up")
|
|
|
|
|
check(tui.Down, "down")
|
|
|
|
|
check(tui.Left, "left")
|
|
|
|
|
check(tui.Right, "right")
|
|
|
|
|
|
|
|
|
|
pairs = parseKeyChords("Tab,Ctrl-I,PgUp,page-up,pgdn,Page-Down,Home,End,Alt-BS,Alt-BSpace,shift-left,shift-right,btab,shift-tab,return,Enter,bspace", "")
|
|
|
|
|
if len(pairs) != 11 {
|
|
|
|
|
t.Error(11)
|
|
|
|
|
}
|
|
|
|
|
check(curses.Tab, "Ctrl-I")
|
|
|
|
|
check(curses.PgUp, "page-up")
|
|
|
|
|
check(curses.PgDn, "Page-Down")
|
|
|
|
|
check(curses.Home, "Home")
|
|
|
|
|
check(curses.End, "End")
|
|
|
|
|
check(curses.AltBS, "Alt-BSpace")
|
|
|
|
|
check(curses.SLeft, "shift-left")
|
|
|
|
|
check(curses.SRight, "shift-right")
|
|
|
|
|
check(curses.BTab, "shift-tab")
|
|
|
|
|
check(curses.CtrlM, "Enter")
|
|
|
|
|
check(curses.BSpace, "bspace")
|
|
|
|
|
check(tui.Tab, "Ctrl-I")
|
|
|
|
|
check(tui.PgUp, "page-up")
|
|
|
|
|
check(tui.PgDn, "Page-Down")
|
|
|
|
|
check(tui.Home, "Home")
|
|
|
|
|
check(tui.End, "End")
|
|
|
|
|
check(tui.AltBS, "Alt-BSpace")
|
|
|
|
|
check(tui.SLeft, "shift-left")
|
|
|
|
|
check(tui.SRight, "shift-right")
|
|
|
|
|
check(tui.BTab, "shift-tab")
|
|
|
|
|
check(tui.CtrlM, "Enter")
|
|
|
|
|
check(tui.BSpace, "bspace")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestParseKeysWithComma(t *testing.T) {
|
|
|
|
@ -191,36 +191,36 @@ func TestParseKeysWithComma(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
pairs := parseKeyChords(",", "")
|
|
|
|
|
checkN(len(pairs), 1)
|
|
|
|
|
check(pairs, curses.AltZ+',', ",")
|
|
|
|
|
check(pairs, tui.AltZ+',', ",")
|
|
|
|
|
|
|
|
|
|
pairs = parseKeyChords(",,a,b", "")
|
|
|
|
|
checkN(len(pairs), 3)
|
|
|
|
|
check(pairs, curses.AltZ+'a', "a")
|
|
|
|
|
check(pairs, curses.AltZ+'b', "b")
|
|
|
|
|
check(pairs, curses.AltZ+',', ",")
|
|
|
|
|
check(pairs, tui.AltZ+'a', "a")
|
|
|
|
|
check(pairs, tui.AltZ+'b', "b")
|
|
|
|
|
check(pairs, tui.AltZ+',', ",")
|
|
|
|
|
|
|
|
|
|
pairs = parseKeyChords("a,b,,", "")
|
|
|
|
|
checkN(len(pairs), 3)
|
|
|
|
|
check(pairs, curses.AltZ+'a', "a")
|
|
|
|
|
check(pairs, curses.AltZ+'b', "b")
|
|
|
|
|
check(pairs, curses.AltZ+',', ",")
|
|
|
|
|
check(pairs, tui.AltZ+'a', "a")
|
|
|
|
|
check(pairs, tui.AltZ+'b', "b")
|
|
|
|
|
check(pairs, tui.AltZ+',', ",")
|
|
|
|
|
|
|
|
|
|
pairs = parseKeyChords("a,,,b", "")
|
|
|
|
|
checkN(len(pairs), 3)
|
|
|
|
|
check(pairs, curses.AltZ+'a', "a")
|
|
|
|
|
check(pairs, curses.AltZ+'b', "b")
|
|
|
|
|
check(pairs, curses.AltZ+',', ",")
|
|
|
|
|
check(pairs, tui.AltZ+'a', "a")
|
|
|
|
|
check(pairs, tui.AltZ+'b', "b")
|
|
|
|
|
check(pairs, tui.AltZ+',', ",")
|
|
|
|
|
|
|
|
|
|
pairs = parseKeyChords("a,,,b,c", "")
|
|
|
|
|
checkN(len(pairs), 4)
|
|
|
|
|
check(pairs, curses.AltZ+'a', "a")
|
|
|
|
|
check(pairs, curses.AltZ+'b', "b")
|
|
|
|
|
check(pairs, curses.AltZ+'c', "c")
|
|
|
|
|
check(pairs, curses.AltZ+',', ",")
|
|
|
|
|
check(pairs, tui.AltZ+'a', "a")
|
|
|
|
|
check(pairs, tui.AltZ+'b', "b")
|
|
|
|
|
check(pairs, tui.AltZ+'c', "c")
|
|
|
|
|
check(pairs, tui.AltZ+',', ",")
|
|
|
|
|
|
|
|
|
|
pairs = parseKeyChords(",,,", "")
|
|
|
|
|
checkN(len(pairs), 1)
|
|
|
|
|
check(pairs, curses.AltZ+',', ",")
|
|
|
|
|
check(pairs, tui.AltZ+',', ",")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestBind(t *testing.T) {
|
|
|
|
@ -236,41 +236,41 @@ func TestBind(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
keymap := defaultKeymap()
|
|
|
|
|
execmap := make(map[int]string)
|
|
|
|
|
check(actBeginningOfLine, keymap[curses.CtrlA])
|
|
|
|
|
check(actBeginningOfLine, keymap[tui.CtrlA])
|
|
|
|
|
parseKeymap(keymap, execmap,
|
|
|
|
|
"ctrl-a:kill-line,ctrl-b:toggle-sort,c:page-up,alt-z:page-down,"+
|
|
|
|
|
"f1:execute(ls {}),f2:execute/echo {}, {}, {}/,f3:execute[echo '({})'],f4:execute;less {};,"+
|
|
|
|
|
"alt-a:execute@echo (,),[,],/,:,;,%,{}@,alt-b:execute;echo (,),[,],/,:,@,%,{};"+
|
|
|
|
|
",,:abort,::accept,X:execute:\nfoobar,Y:execute(baz)")
|
|
|
|
|
check(actKillLine, keymap[curses.CtrlA])
|
|
|
|
|
check(actToggleSort, keymap[curses.CtrlB])
|
|
|
|
|
check(actPageUp, keymap[curses.AltZ+'c'])
|
|
|
|
|
check(actAbort, keymap[curses.AltZ+','])
|
|
|
|
|
check(actAccept, keymap[curses.AltZ+':'])
|
|
|
|
|
check(actPageDown, keymap[curses.AltZ])
|
|
|
|
|
check(actExecute, keymap[curses.F1])
|
|
|
|
|
check(actExecute, keymap[curses.F2])
|
|
|
|
|
check(actExecute, keymap[curses.F3])
|
|
|
|
|
check(actExecute, keymap[curses.F4])
|
|
|
|
|
checkString("ls {}", execmap[curses.F1])
|
|
|
|
|
checkString("echo {}, {}, {}", execmap[curses.F2])
|
|
|
|
|
checkString("echo '({})'", execmap[curses.F3])
|
|
|
|
|
checkString("less {}", execmap[curses.F4])
|
|
|
|
|
checkString("echo (,),[,],/,:,;,%,{}", execmap[curses.AltA])
|
|
|
|
|
checkString("echo (,),[,],/,:,@,%,{}", execmap[curses.AltB])
|
|
|
|
|
checkString("\nfoobar,Y:execute(baz)", execmap[curses.AltZ+'X'])
|
|
|
|
|
check(actKillLine, keymap[tui.CtrlA])
|
|
|
|
|
check(actToggleSort, keymap[tui.CtrlB])
|
|
|
|
|
check(actPageUp, keymap[tui.AltZ+'c'])
|
|
|
|
|
check(actAbort, keymap[tui.AltZ+','])
|
|
|
|
|
check(actAccept, keymap[tui.AltZ+':'])
|
|
|
|
|
check(actPageDown, keymap[tui.AltZ])
|
|
|
|
|
check(actExecute, keymap[tui.F1])
|
|
|
|
|
check(actExecute, keymap[tui.F2])
|
|
|
|
|
check(actExecute, keymap[tui.F3])
|
|
|
|
|
check(actExecute, keymap[tui.F4])
|
|
|
|
|
checkString("ls {}", execmap[tui.F1])
|
|
|
|
|
checkString("echo {}, {}, {}", execmap[tui.F2])
|
|
|
|
|
checkString("echo '({})'", execmap[tui.F3])
|
|
|
|
|
checkString("less {}", execmap[tui.F4])
|
|
|
|
|
checkString("echo (,),[,],/,:,;,%,{}", execmap[tui.AltA])
|
|
|
|
|
checkString("echo (,),[,],/,:,@,%,{}", execmap[tui.AltB])
|
|
|
|
|
checkString("\nfoobar,Y:execute(baz)", execmap[tui.AltZ+'X'])
|
|
|
|
|
|
|
|
|
|
for idx, char := range []rune{'~', '!', '@', '#', '$', '%', '^', '&', '*', '|', ';', '/'} {
|
|
|
|
|
parseKeymap(keymap, execmap, fmt.Sprintf("%d:execute%cfoobar%c", idx%10, char, char))
|
|
|
|
|
checkString("foobar", execmap[curses.AltZ+int([]rune(fmt.Sprintf("%d", idx%10))[0])])
|
|
|
|
|
checkString("foobar", execmap[tui.AltZ+int([]rune(fmt.Sprintf("%d", idx%10))[0])])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parseKeymap(keymap, execmap, "f1:abort")
|
|
|
|
|
check(actAbort, keymap[curses.F1])
|
|
|
|
|
check(actAbort, keymap[tui.F1])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestColorSpec(t *testing.T) {
|
|
|
|
|
theme := curses.Dark256
|
|
|
|
|
theme := tui.Dark256
|
|
|
|
|
dark := parseTheme(theme, "dark")
|
|
|
|
|
if *dark != *theme {
|
|
|
|
|
t.Errorf("colors should be equivalent")
|
|
|
|
@ -283,7 +283,7 @@ func TestColorSpec(t *testing.T) {
|
|
|
|
|
if *light == *theme {
|
|
|
|
|
t.Errorf("should not be equivalent")
|
|
|
|
|
}
|
|
|
|
|
if *light != *curses.Light256 {
|
|
|
|
|
if *light != *tui.Light256 {
|
|
|
|
|
t.Errorf("colors should be equivalent")
|
|
|
|
|
}
|
|
|
|
|
if light == theme {
|
|
|
|
@ -294,23 +294,23 @@ func TestColorSpec(t *testing.T) {
|
|
|
|
|
if customized.Fg != 231 || customized.Bg != 232 {
|
|
|
|
|
t.Errorf("color not customized")
|
|
|
|
|
}
|
|
|
|
|
if *curses.Dark256 == *customized {
|
|
|
|
|
if *tui.Dark256 == *customized {
|
|
|
|
|
t.Errorf("colors should not be equivalent")
|
|
|
|
|
}
|
|
|
|
|
customized.Fg = curses.Dark256.Fg
|
|
|
|
|
customized.Bg = curses.Dark256.Bg
|
|
|
|
|
if *curses.Dark256 != *customized {
|
|
|
|
|
t.Errorf("colors should now be equivalent: %v, %v", curses.Dark256, customized)
|
|
|
|
|
customized.Fg = tui.Dark256.Fg
|
|
|
|
|
customized.Bg = tui.Dark256.Bg
|
|
|
|
|
if *tui.Dark256 != *customized {
|
|
|
|
|
t.Errorf("colors should now be equivalent: %v, %v", tui.Dark256, customized)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
customized = parseTheme(theme, "fg:231,dark,bg:232")
|
|
|
|
|
if customized.Fg != curses.Dark256.Fg || customized.Bg == curses.Dark256.Bg {
|
|
|
|
|
if customized.Fg != tui.Dark256.Fg || customized.Bg == tui.Dark256.Bg {
|
|
|
|
|
t.Errorf("color not customized")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestParseNilTheme(t *testing.T) {
|
|
|
|
|
var theme *curses.ColorTheme
|
|
|
|
|
var theme *tui.ColorTheme
|
|
|
|
|
newTheme := parseTheme(theme, "prompt:12")
|
|
|
|
|
if newTheme != nil {
|
|
|
|
|
t.Errorf("color is disabled. keep it that way.")
|
|
|
|
@ -330,21 +330,21 @@ func TestDefaultCtrlNP(t *testing.T) {
|
|
|
|
|
t.Error()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
check([]string{}, curses.CtrlN, actDown)
|
|
|
|
|
check([]string{}, curses.CtrlP, actUp)
|
|
|
|
|
check([]string{}, tui.CtrlN, actDown)
|
|
|
|
|
check([]string{}, tui.CtrlP, actUp)
|
|
|
|
|
|
|
|
|
|
check([]string{"--bind=ctrl-n:accept"}, curses.CtrlN, actAccept)
|
|
|
|
|
check([]string{"--bind=ctrl-p:accept"}, curses.CtrlP, actAccept)
|
|
|
|
|
check([]string{"--bind=ctrl-n:accept"}, tui.CtrlN, actAccept)
|
|
|
|
|
check([]string{"--bind=ctrl-p:accept"}, tui.CtrlP, actAccept)
|
|
|
|
|
|
|
|
|
|
hist := "--history=/tmp/fzf-history"
|
|
|
|
|
check([]string{hist}, curses.CtrlN, actNextHistory)
|
|
|
|
|
check([]string{hist}, curses.CtrlP, actPreviousHistory)
|
|
|
|
|
check([]string{hist}, tui.CtrlN, actNextHistory)
|
|
|
|
|
check([]string{hist}, tui.CtrlP, actPreviousHistory)
|
|
|
|
|
|
|
|
|
|
check([]string{hist, "--bind=ctrl-n:accept"}, curses.CtrlN, actAccept)
|
|
|
|
|
check([]string{hist, "--bind=ctrl-n:accept"}, curses.CtrlP, actPreviousHistory)
|
|
|
|
|
check([]string{hist, "--bind=ctrl-n:accept"}, tui.CtrlN, actAccept)
|
|
|
|
|
check([]string{hist, "--bind=ctrl-n:accept"}, tui.CtrlP, actPreviousHistory)
|
|
|
|
|
|
|
|
|
|
check([]string{hist, "--bind=ctrl-p:accept"}, curses.CtrlN, actNextHistory)
|
|
|
|
|
check([]string{hist, "--bind=ctrl-p:accept"}, curses.CtrlP, actAccept)
|
|
|
|
|
check([]string{hist, "--bind=ctrl-p:accept"}, tui.CtrlN, actNextHistory)
|
|
|
|
|
check([]string{hist, "--bind=ctrl-p:accept"}, tui.CtrlP, actAccept)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func optsFor(words ...string) *Options {
|
|
|
|
|