From ae3180f91994cd6129dbb80144cda4b1abeb6ec0 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 17 Jan 2015 04:55:29 +0900 Subject: [PATCH] Fix CTRL-Y key binding With tmux-based test cases --- .travis.yml | 19 ++- Rakefile | 7 +- src/Makefile | 6 +- src/terminal.go | 3 +- test/test_go.rb | 184 +++++++++++++++++++++++++++++ test/{test_fzf.rb => test_ruby.rb} | 2 +- 6 files changed, 209 insertions(+), 12 deletions(-) create mode 100644 test/test_go.rb rename test/{test_fzf.rb => test_ruby.rb} (99%) diff --git a/.travis.yml b/.travis.yml index 7633c4f8..38961904 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,19 @@ language: ruby -sudo: false rvm: - - "1.8.7" - - "1.9.3" - - "2.0.0" - "2.1.1" -install: gem install curses minitest +before_script: | + sudo apt-get install -y tmux libncurses-dev lib32ncurses5-dev + export GOROOT=~/go1.4 + export GOPATH=~/go + + mkdir -p ~/go/src/github.com/junegunn + ln -s $(pwd) ~/go/src/github.com/junegunn/fzf + + curl https://storage.googleapis.com/golang/go1.4.linux-amd64.tar.gz | tar -xz + mv go $GOROOT + cd $GOROOT/src && GOARCH=386 ./make.bash + + cd ~/go/src/github.com/junegunn/fzf/src && make install && cd .. && + yes | ./install && tmux diff --git a/Rakefile b/Rakefile index 933a0391..5bc903d3 100644 --- a/Rakefile +++ b/Rakefile @@ -2,8 +2,11 @@ require "bundler/gem_tasks" require 'rake/testtask' Rake::TestTask.new(:test) do |test| - test.pattern = 'test/**/test_*.rb' - test.verbose = true + test.pattern = 'test/test_go.rb' +end + +Rake::TestTask.new(:testall) do |test| + test.pattern = 'test/test_*.rb' end task :default => :test diff --git a/src/Makefile b/src/Makefile index 4610e586..eda04040 100644 --- a/src/Makefile +++ b/src/Makefile @@ -22,7 +22,7 @@ VERSION = $(shell fzf/$(BINARY64) --version) RELEASE32 = fzf-$(VERSION)-$(GOOS)_386 RELEASE64 = fzf-$(VERSION)-$(GOOS)_amd64 -all: test release +all: release release: build cd fzf && \ @@ -30,13 +30,13 @@ release: build cp $(BINARY64) $(RELEASE64) && tar -czf $(RELEASE64).tgz $(RELEASE64) && \ rm $(RELEASE32) $(RELEASE64) -build: fzf/$(BINARY32) fzf/$(BINARY64) +build: test fzf/$(BINARY32) fzf/$(BINARY64) test: go get go test -v ./... -install: $(BINDIR)/fzf +install: build $(BINDIR)/fzf uninstall: rm -f $(BINDIR)/fzf $(BINDIR)/$(BINARY64) diff --git a/src/terminal.go b/src/terminal.go index 44796cec..abd70690 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -515,7 +515,8 @@ func (t *Terminal) Loop() { t.rubout("[^[:alnum:]][[:alnum:]]") } case C.CtrlY: - t.input = append(append(t.input[:t.cx], t.yanked...), t.input[t.cx:]...) + suffix := copySlice(t.input[t.cx:]) + t.input = append(append(t.input[:t.cx], t.yanked...), suffix...) t.cx += len(t.yanked) case C.Del: t.delChar() diff --git a/test/test_go.rb b/test/test_go.rb new file mode 100644 index 00000000..de8fac7d --- /dev/null +++ b/test/test_go.rb @@ -0,0 +1,184 @@ +#!/usr/bin/env ruby +# encoding: utf-8 + +require 'minitest/autorun' + +class Tmux + TEMPNAME = '/tmp/fzf-test.txt' + + attr_reader :win + + def initialize shell = 'bash' + @win = go("new-window -P -F '#I' 'bash --rcfile ~/.fzf.#{shell}'").first + end + + def self.current + `tmux display-message -p '#I'`.split($/).first + end + + def self.select id + system "tmux select-window -t #{id}" + end + + def closed? + !go("list-window -F '#I'").include?(win) + end + + def close timeout = 1 + send_keys 'C-c', 'C-u', 'C-d' + wait(timeout) { closed? } + end + + def kill + go("kill-window -t #{win} 2> /dev/null") + end + + def send_keys *args + args = args.map { |a| %{"#{a}"} }.join ' ' + go("send-keys -t #{win} #{args}") + end + + def capture + go("capture-pane -t #{win} \\; save-buffer #{TEMPNAME}") + raise "Window not found" if $?.exitstatus != 0 + File.read(TEMPNAME).split($/) + end + + def until timeout = 1 + wait(timeout) { yield capture } + end + +private + def wait timeout = 1 + waited = 0 + until yield + waited += 0.1 + sleep 0.1 + raise "timeout" if waited > timeout + end + end + + def go *args + %x[tmux #{args.join ' '}].split($/) + end +end + +class TestGoFZF < MiniTest::Unit::TestCase + attr_reader :tmux + + def tempname + '/tmp/output' + end + + def setup + ENV.delete 'FZF_DEFAULT_OPTS' + ENV.delete 'FZF_DEFAULT_COMMAND' + @prev = Tmux.current + @tmux = Tmux.new + File.unlink tempname rescue nil + end + + def teardown + @tmux.kill + Tmux.select @prev + end + + def test_vanilla + tmux.send_keys "seq 1 100000 | fzf > #{tempname}", :Enter + tmux.until { |lines| lines.last =~ /^>/ && lines[-2] =~ /^ 100000/ } + lines = tmux.capture + assert_equal ' 2', lines[-4] + assert_equal '> 1', lines[-3] + assert_equal ' 100000/100000', lines[-2] + assert_equal '>', lines[-1] + + # Testing basic key bindings + tmux.send_keys '99', 'C-a', '1', 'C-f', '3', 'C-b', 'C-h', 'C-u', 'C-e', 'C-y', 'C-k', 'Tab', 'BTab' + tmux.until { |lines| lines.last == '> 391' } + lines = tmux.capture + assert_equal '> 1391', lines[-4] + assert_equal ' 391', lines[-3] + assert_equal ' 856/100000', lines[-2] + assert_equal '> 391', lines[-1] + + tmux.send_keys :Enter + tmux.close + assert_equal '1391', File.read(tempname).chomp + end + + def test_fzf_default_command + tmux.send_keys "FZF_DEFAULT_COMMAND='echo hello' fzf > #{tempname}", :Enter + tmux.until { |lines| lines.last =~ /^>/ } + + tmux.send_keys :Enter + tmux.close + assert_equal 'hello', File.read(tempname).chomp + end + + def test_fzf_prompt + tmux.send_keys "fzf -q 'foo bar foo-bar'", :Enter + tmux.until { |lines| lines.last =~ /foo-bar/ } + + # CTRL-A + tmux.send_keys "C-A", "(" + tmux.until { |lines| lines.last == '> (foo bar foo-bar' } + + # META-F + tmux.send_keys :Escape, :f, ")" + tmux.until { |lines| lines.last == '> (foo) bar foo-bar' } + + # CTRL-B + tmux.send_keys "C-B", "var" + tmux.until { |lines| lines.last == '> (foovar) bar foo-bar' } + + # Left, CTRL-D + tmux.send_keys :Left, :Left, "C-D" + tmux.until { |lines| lines.last == '> (foovr) bar foo-bar' } + + # META-BS + tmux.send_keys :Escape, :BSpace + tmux.until { |lines| lines.last == '> (r) bar foo-bar' } + + # CTRL-Y + tmux.send_keys "C-Y", "C-Y" + tmux.until { |lines| lines.last == '> (foovfoovr) bar foo-bar' } + + # META-B + tmux.send_keys :Escape, :b, :Space, :Space + tmux.until { |lines| lines.last == '> ( foovfoovr) bar foo-bar' } + + # CTRL-F / Right + tmux.send_keys 'C-F', :Right, '/' + tmux.until { |lines| lines.last == '> ( fo/ovfoovr) bar foo-bar' } + + # CTRL-H / BS + tmux.send_keys 'C-H', :BSpace + tmux.until { |lines| lines.last == '> ( fovfoovr) bar foo-bar' } + + # CTRL-E + tmux.send_keys "C-E", 'baz' + tmux.until { |lines| lines.last == '> ( fovfoovr) bar foo-barbaz' } + + # CTRL-U + tmux.send_keys "C-U" + tmux.until { |lines| lines.last == '>' } + + # CTRL-Y + tmux.send_keys "C-Y" + tmux.until { |lines| lines.last == '> ( fovfoovr) bar foo-barbaz' } + + # CTRL-W + tmux.send_keys "C-W", "bar-foo" + tmux.until { |lines| lines.last == '> ( fovfoovr) bar bar-foo' } + + # META-D + tmux.send_keys :Escape, :b, :Escape, :b, :Escape, :d, "C-A", "C-Y" + tmux.until { |lines| lines.last == '> bar( fovfoovr) bar -foo' } + + # CTRL-M + tmux.send_keys "C-M" + tmux.until { |lines| lines.last !~ /^>/ } + tmux.close + end +end + diff --git a/test/test_fzf.rb b/test/test_ruby.rb similarity index 99% rename from test/test_fzf.rb rename to test/test_ruby.rb index e11f2c55..674ed3be 100644 --- a/test/test_fzf.rb +++ b/test/test_ruby.rb @@ -54,7 +54,7 @@ class MockTTY end end -class TestFZF < MiniTest::Unit::TestCase +class TestRubyFZF < MiniTest::Unit::TestCase def setup ENV.delete 'FZF_DEFAULT_SORT' ENV.delete 'FZF_DEFAULT_OPTS'