summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2016-11-07 02:15:34 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2016-11-08 02:06:34 +0900
commit898d8d94c858774b02668c1490068cf086a1f9f0 (patch)
tree4229f5c2b63b228e8e1e2d1609c3ce587c819162
parent26895da96918f9b1956a04981c8af5f3e42fcbd8 (diff)
Fix issues in tcell renderer and Windows build
- Fix display of CJK wide characters - Fix horizontal offset of header lines - Add support for keys with ALT modifier, shift-tab, page-up and down - Fix util.ExecCommand to properly parse command-line arguments - Fix redraw on resize - Implement Pause/Resume for execute action - Remove runtime check of GOOS - Change exit status to 2 when tcell failed to start - TBD: Travis CI build for tcell renderer - Pending. tcell cannot reliably ingest keys from tmux send-keys
-rw-r--r--.travis.yml8
-rw-r--r--src/Makefile2
-rw-r--r--src/reader.go3
-rw-r--r--src/terminal.go7
-rw-r--r--src/tui/ncurses.go4
-rw-r--r--src/tui/tcell.go75
-rw-r--r--src/util/util_unix.go5
-rw-r--r--src/util/util_windows.go13
-rw-r--r--test/test_go.rb2
9 files changed, 91 insertions, 28 deletions
diff --git a/.travis.yml b/.travis.yml
index 597c1f6e..a1a6497d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,10 @@
language: ruby
-rvm:
-- 2.2.0
+matrix:
+ include:
+ - env: TAGS=
+ rvm: 2.2.0
+# - env: TAGS=tcell
+# rvm: 2.2.0
install:
- sudo apt-get update
diff --git a/src/Makefile b/src/Makefile
index edc77faf..15f4c736 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -52,7 +52,7 @@ android-build: $(SRCDIR)
rm -f $(RELEASEARM7)
test: deps
- SHELL=/bin/sh go test -v ./...
+ SHELL=/bin/sh go test -v -tags "$(TAGS)" ./...
install: $(BINDIR)/fzf
diff --git a/src/reader.go b/src/reader.go
index 15a0f44e..7e8e2e01 100644
--- a/src/reader.go
+++ b/src/reader.go
@@ -4,7 +4,6 @@ import (
"bufio"
"io"
"os"
- "runtime"
"github.com/junegunn/fzf/src/util"
)
@@ -44,7 +43,7 @@ func (r *Reader) feed(src io.Reader) {
if len(bytea) > 0 {
if err == nil {
// get rid of carriage return if under Windows:
- if runtime.GOOS == "windows" && byteaLen >= 2 && bytea[byteaLen-2] == byte('\r') {
+ if util.IsWindows() && byteaLen >= 2 && bytea[byteaLen-2] == byte('\r') {
bytea = bytea[:byteaLen-2]
} else {
bytea = bytea[:byteaLen-1]
diff --git a/src/terminal.go b/src/terminal.go
index 39c78239..6d1a1ab5 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -7,6 +7,7 @@ import (
"os/signal"
"regexp"
"sort"
+ "strconv"
"strings"
"sync"
"syscall"
@@ -919,6 +920,9 @@ func keyMatch(key int, event tui.Event) bool {
}
func quoteEntry(entry string) string {
+ if util.IsWindows() {
+ return strconv.Quote(strings.Replace(entry, "\"", "\\\"", -1))
+ }
return "'" + strings.Replace(entry, "'", "'\\''", -1) + "'"
}
@@ -982,6 +986,9 @@ func (t *Terminal) executeCommand(template string, items []*Item) {
cmd.Stderr = os.Stderr
tui.Pause()
cmd.Run()
+ if tui.Resume() {
+ t.printAll()
+ }
t.refresh()
}
diff --git a/src/tui/ncurses.go b/src/tui/ncurses.go
index 3f52f3f8..d55c1c87 100644
--- a/src/tui/ncurses.go
+++ b/src/tui/ncurses.go
@@ -138,6 +138,10 @@ func Pause() {
C.endwin()
}
+func Resume() bool {
+ return false
+}
+
func Close() {
C.endwin()
C.delscreen(_screen)
diff --git a/src/tui/tcell.go b/src/tui/tcell.go
index 591b366c..0bb06e95 100644
--- a/src/tui/tcell.go
+++ b/src/tui/tcell.go
@@ -13,6 +13,8 @@ import (
"github.com/gdamore/tcell"
"github.com/gdamore/tcell/encoding"
+
+ "github.com/junegunn/go-runewidth"
)
type ColorPair [2]Color
@@ -108,21 +110,32 @@ func (a Attr) Merge(b Attr) Attr {
var (
_screen tcell.Screen
+ _mouse bool
)
-func Init(theme *ColorTheme, black bool, mouse bool) {
- encoding.Register()
-
+func initScreen() {
s, e := tcell.NewScreen()
if e != nil {
fmt.Fprintf(os.Stderr, "%v\n", e)
- os.Exit(1)
+ os.Exit(2)
}
if e = s.Init(); e != nil {
fmt.Fprintf(os.Stderr, "%v\n", e)
- os.Exit(1)
+ os.Exit(2)
+ }
+ if _mouse {
+ s.EnableMouse()
+ } else {
+ s.DisableMouse()
}
_screen = s
+}
+
+func Init(theme *ColorTheme, black bool, mouse bool) {
+ encoding.Register()
+
+ _mouse = mouse
+ initScreen()
_color = theme != nil
if _color {
@@ -139,12 +152,6 @@ func Init(theme *ColorTheme, black bool, mouse bool) {
ColSelected = ColorPair{theme.Selected, theme.DarkBg}
ColHeader = ColorPair{theme.Header, theme.Bg}
ColBorder = ColorPair{theme.Border, theme.Bg}
-
- if mouse {
- _screen.EnableMouse()
- } else {
- _screen.DisableMouse()
- }
}
func MaxX() int {
@@ -162,6 +169,7 @@ func (w *Window) win() *WindowTcell {
}
func Clear() {
+ _screen.Sync()
_screen.Clear()
}
@@ -211,6 +219,7 @@ func GetChar() Event {
// process keyboard:
case *tcell.EventKey:
+ alt := (ev.Modifiers() & tcell.ModAlt) > 0
switch ev.Key() {
case tcell.KeyCtrlA:
return Event{CtrlA, 0, nil}
@@ -233,6 +242,9 @@ func GetChar() Event {
case tcell.KeyCtrlL:
return Event{CtrlL, 0, nil}
case tcell.KeyCtrlM:
+ if alt {
+ return Event{AltEnter, 0, nil}
+ }
return Event{CtrlM, 0, nil}
case tcell.KeyCtrlN:
return Event{CtrlN, 0, nil}
@@ -261,6 +273,9 @@ func GetChar() Event {
case tcell.KeyCtrlZ:
return Event{CtrlZ, 0, nil}
case tcell.KeyBackspace, tcell.KeyBackspace2:
+ if alt {
+ return Event{AltBS, 0, nil}
+ }
return Event{BSpace, 0, nil}
case tcell.KeyUp:
@@ -278,13 +293,15 @@ func GetChar() Event {
return Event{Del, 0, nil}
case tcell.KeyEnd:
return Event{End, 0, nil}
- /*case tcell.KeyPgUp:
+ case tcell.KeyPgUp:
return Event{PgUp, 0, nil}
- case tcell.KeyPgdn:
- return Event{PgDn, 0, nil}*/
+ case tcell.KeyPgDn:
+ return Event{PgDn, 0, nil}
case tcell.KeyTab:
return Event{Tab, 0, nil}
+ case tcell.KeyBacktab:
+ return Event{BTab, 0, nil}
case tcell.KeyF1:
return Event{F1, 0, nil}
@@ -313,7 +330,19 @@ func GetChar() Event {
// ev.Ch doesn't work for some reason for space:
case tcell.KeyRune:
- return Event{Rune, ev.Rune(), nil}
+ r := ev.Rune()
+ if alt {
+ switch r {
+ case ' ':
+ return Event{AltSpace, 0, nil}
+ case '/':
+ return Event{AltSlash, 0, nil}
+ }
+ if r >= 'a' && r <= 'z' {
+ return Event{AltA + int(r) - 'a', 0, nil}
+ }
+ }
+ return Event{Rune, r, nil}
case tcell.KeyEsc:
return Event{ESC, 0, nil}
@@ -325,7 +354,12 @@ func GetChar() Event {
}
func Pause() {
- // TODO
+ _screen.Fini()
+}
+
+func Resume() bool {
+ initScreen()
+ return true
}
func Close() {
@@ -391,11 +425,10 @@ func (w *Window) Move(y int, x int) {
func (w *Window) MoveAndClear(y int, x int) {
w.Move(y, x)
- r, _ := utf8.DecodeRuneInString(" ")
for i := w.win().LastX; i < w.Width; i++ {
- _screen.SetContent(i+w.Left, w.win().LastY+w.Top, r, nil, ColDefault.style())
+ _screen.SetContent(i+w.Left, w.win().LastY+w.Top, rune(' '), nil, ColDefault.style())
}
- w.win().LastX = 0
+ w.win().LastX = x
}
func (w *Window) Print(text string) {
@@ -439,7 +472,7 @@ func (w *Window) PrintString(text string, pair ColorPair, a Attr) {
if xPos < (w.Left+w.Width) && yPos < (w.Top+w.Height) {
_screen.SetContent(xPos, yPos, r, nil, style)
}
- lx++
+ lx += runewidth.RuneWidth(r)
}
}
w.win().LastX += lx
@@ -482,7 +515,7 @@ func (w *Window) FillString(text string, pair ColorPair, a Attr) bool {
}
_screen.SetContent(xPos, yPos, r, nil, style)
- lx++
+ lx += runewidth.RuneWidth(r)
}
}
w.win().LastX += lx
diff --git a/src/util/util_unix.go b/src/util/util_unix.go
index dcc5cb5e..29e0d30d 100644
--- a/src/util/util_unix.go
+++ b/src/util/util_unix.go
@@ -15,3 +15,8 @@ func ExecCommand(command string) *exec.Cmd {
}
return exec.Command(shell, "-c", command)
}
+
+// IsWindows returns true on Windows
+func IsWindows() bool {
+ return false
+}
diff --git a/src/util/util_windows.go b/src/util/util_windows.go
index a660f39e..3aa86606 100644
--- a/src/util/util_windows.go
+++ b/src/util/util_windows.go
@@ -5,6 +5,8 @@ package util
import (
"os"
"os/exec"
+
+ "github.com/junegunn/go-shellwords"
)
// ExecCommand executes the given command with $SHELL
@@ -13,5 +15,14 @@ func ExecCommand(command string) *exec.Cmd {
if len(shell) == 0 {
shell = "cmd"
}
- return exec.Command(shell, "/c", command)
+ args, _ := shellwords.Parse(command)
+ allArgs := make([]string, len(args)+1)
+ allArgs[0] = "/c"
+ copy(allArgs[1:], args)
+ return exec.Command(shell, allArgs...)
+}
+
+// IsWindows returns true on Windows
+func IsWindows() bool {
+ return true
}
diff --git a/test/test_go.rb b/test/test_go.rb
index f34d8b32..3fdfddd6 100644
--- a/test/test_go.rb
+++ b/test/test_go.rb
@@ -1058,7 +1058,7 @@ class TestGoFZF < TestBase
def test_invalid_term
lines = `TERM=xxx #{FZF}`
assert_equal 2, $?.exitstatus
- assert lines.include?('Invalid $TERM: xxx')
+ assert lines.include?('Invalid $TERM: xxx') || lines.include?('terminal entry not found')
end
def test_invalid_option