Reset fish_bind_mode when changing fish_key_bindings

Also avoid resetting bindings if fish_key_bindings is "modified" without
actually changing.

Fixes #1638.
This commit is contained in:
Kevin Ballard 2014-09-18 15:45:07 -07:00
parent 174f5ba99a
commit 0a32d96b27
9 changed files with 107 additions and 20 deletions

View file

@ -205,6 +205,14 @@ function __fish_config_interactive -d "Initializations that should be performed
# Reload key bindings when binding variable change # Reload key bindings when binding variable change
function __fish_reload_key_bindings -d "Reload key bindings when binding variable change" --on-variable fish_key_bindings function __fish_reload_key_bindings -d "Reload key bindings when binding variable change" --on-variable fish_key_bindings
# do nothing if the key bindings didn't actually change
# This could be because the variable was set to the existing value
# or because it was a local variable
if test "$fish_key_bindings" = "$__fish_active_key_bindings"
return
end
set -g __fish_active_key_bindings "$fish_key_bindings"
set -g fish_bind_mode default
# Do something nasty to avoid two forks # Do something nasty to avoid two forks
if test "$fish_key_bindings" = fish_default_key_bindings if test "$fish_key_bindings" = fish_default_key_bindings
fish_default_key_bindings fish_default_key_bindings

43
tests/bind.expect Normal file
View file

@ -0,0 +1,43 @@
# vim: set filetype=expect:
spawn $fish
expect_prompt
# test switching key bindings
# this should leave the mode in the appropriate state
send_line "set -g fish_key_bindings fish_vi_key_bindings"
expect_prompt
send_line -h "echo fail\033ddiecho success"
expect_prompt -re {\r\nsuccess\r\n} {
puts "success"
} -nounmatched -re {\r\nfail} {
puts stderr "fail"
} unmatched {
puts stderr "Couldn't find expected output 'success'"
}
# try again without the human typing
send_line "echo fail\033ddiecho success"
expect_prompt -re {\r\nsuccess\r\n} {
puts "success"
} -nounmatched -re {\r\nfail} {
puts stderr "fail"
} unmatched {
puts stderr "Couldn't find expected output 'success'"
}
# still in insert mode, switch back to regular key bindings
send_line "set -g fish_key_bindings fish_default_key_bindings"
expect_prompt
send_line "echo success"
expect_prompt -re {\r\nsuccess\r\n} {
puts "success"
} unmatched {
puts stderr "Couldn't find expected output 'success'"
} timeout {
set msg ""
append msg "Timeout after setting fish_key_bindings to fish_default_key_bindings\n" \
"\$fish_bind_mode is most likely still set to 'insert'"
abort $msg
}

0
tests/bind.expect.err Normal file
View file

3
tests/bind.expect.out Normal file
View file

@ -0,0 +1,3 @@
success
success
success

1
tests/bind.expect.status Normal file
View file

@ -0,0 +1 @@
0

View file

@ -1,13 +1,16 @@
# vim: set filetype=fish sw=4 ts=4 et: # vim: set filetype=fish sw=4 ts=4 et:
set -g prompt_counter 1 # source the non-interactive config
source $XDG_CONFIG_HOME/../tmp.config/fish/config.fish
set -g prompt_counter 0
set -g prompt_counter_incr 0 set -g prompt_counter_incr 0
function fish_prompt function fish_prompt
echo "prompt $prompt_counter>"
if test $prompt_counter_incr -eq 1 if test $prompt_counter_incr -eq 1
set -g prompt_counter (expr $prompt_counter + 1) set -g prompt_counter (expr $prompt_counter + 1)
set -g prompt_counter_incr 0 set -g prompt_counter_incr 0
end end
echo "prompt $prompt_counter>"
end end
function fish_prompt_event --on-event fish_prompt function fish_prompt_event --on-event fish_prompt
set -g prompt_counter_incr 1 set -g prompt_counter_incr 1

View file

@ -42,17 +42,24 @@ proc log_debug string {
set prompt_counter 1 set prompt_counter 1
# expect_prompt takes an argument list like `expect` does. # expect_prompt takes an argument list like `expect` does.
# It supports a special pattern "unmatched" that is run if no # It supports a special pattern "unmatched" that is run if no
# other provided patterns match. # other provided patterns match, and a special flag "-nounmatched"
# that marks the following pattern as not being tracked for
# "unmatched" handling.
# If multiple patterns are provided, they may all match. Each pattern
# is matched at most once. The matching only ends once the prompt is
# found.
proc expect_prompt {args} { proc expect_prompt {args} {
global prompt_counter global prompt_counter
upvar expect_out expect_out upvar expect_out expect_out
set prompt_pat [list -re "(?:\\r\\n?|^)prompt $prompt_counter>(?:$|\r)"] set prompt_pat [list -re "(?:\\r\\n?|^)prompt $prompt_counter>(?:$|\\r)"]
if {[llength $args] == 1 && [string match "\n*" $args]} { if {[llength $args] == 1 && [string match "\n*" $args]} {
set args [join $args] set args [join $args]
} }
set prompt_action "" set prompt_action ""
set expargs {} set expargs {}
upvar expect_out up_expect_out set nounmatched no
set matchidx 0
set matched(any) no
set state "firstarg" set state "firstarg"
foreach arg $args { foreach arg $args {
switch $state { switch $state {
@ -63,14 +70,17 @@ proc expect_prompt {args} {
"action" { "action" {
lappend expargs [subst -nocommands { lappend expargs [subst -nocommands {
log_debug "matched extra pattern to expect_prompt: [quote \$expect_out(0,string)]" log_debug "matched extra pattern to expect_prompt: [quote \$expect_out(0,string)]"
if {\$matched} { if {!\$matched($matchidx)} {
exp_continue set matched($matchidx) yes
} if {!$nounmatched} { set matched(any) yes }
set matched yes
uplevel 1 {$arg} uplevel 1 {$arg}
}
exp_continue exp_continue
}] }]
set matched($matchidx) no
incr matchidx
set state "firstarg" set state "firstarg"
set nounmatched no
} }
"firstarg" - "firstarg" -
"arg" { "arg" {
@ -78,8 +88,8 @@ proc expect_prompt {args} {
set state "unmatched" set state "unmatched"
continue continue
} }
lappend expargs $arg set keep yes
switch $arg { switch -glob -- $arg {
-gl - -gl -
-re - -re -
-ex { -ex {
@ -89,6 +99,20 @@ proc expect_prompt {args} {
-timeout { -timeout {
set state "flagarg" set state "flagarg"
} }
-nounmatched {
set keep no
set nounmatched yes
set state "arg"
}
-* {
error "BUG: unknown expect flag in expect_prompt"
}
default {
set state "pat"
}
}
if {$keep} {
lappend expargs $arg
} }
} }
"flagarg" { "flagarg" {
@ -96,9 +120,11 @@ proc expect_prompt {args} {
set state "arg" set state "arg"
} }
"unmatched" { "unmatched" {
set state "firstarg"
if {$prompt_action ne ""} continue if {$prompt_action ne ""} continue
set prompt_action [subst -nocommands { set prompt_action [subst -nocommands {
if {!\$matched} { if {!\$matched(any)} {
log_debug "triggered unmatched action in expect_prompt"
uplevel 1 {$arg} uplevel 1 {$arg}
} }
}] }]
@ -114,7 +140,6 @@ proc expect_prompt {args} {
log_info "expecting prompt $prompt_counter" log_info "expecting prompt $prompt_counter"
} }
set expargs [concat $prompt_pat [list $prompt_action] $expargs] set expargs [concat $prompt_pat [list $prompt_action] $expargs]
set matched no
expect {*}$expargs expect {*}$expargs
incr prompt_counter incr prompt_counter
} }
@ -128,6 +153,7 @@ proc trace_expect {cmd args} {
switch [lindex $args end] { switch [lindex $args end] {
enter { enter {
log_debug "entering expect" log_debug "entering expect"
log_debug "command: $cmd"
uplevel {set expect_out(buffer) {}} uplevel {set expect_out(buffer) {}}
} }
leave { leave {
@ -160,7 +186,7 @@ proc trace_spawn {cmd args} {
} }
leave { leave {
log_debug "[quote $cmd]: code [lindex $args 0], result [lindex $args 1]" log_debug "[quote $cmd]: code [lindex $args 0], result [lindex $args 1]"
expect_before { expect_after {
timeout { timeout {
expect "*" { expect "*" {
log_debug "timeout; buffer=[quote $expect_out(buffer)]" log_debug "timeout; buffer=[quote $expect_out(buffer)]"
@ -216,7 +242,6 @@ proc print_var_contents name {
# match on the results # match on the results
set pat {\r\n@GUARD:$guard@\r\n(.*)\r\n@/GUARD:$guard@\r\n} set pat {\r\n@GUARD:$guard@\r\n(.*)\r\n@/GUARD:$guard@\r\n}
set matched false
expect_prompt -re [subst -nocommands -nobackslashes $pat] { expect_prompt -re [subst -nocommands -nobackslashes $pat] {
log_info "get_var_contents: result: [quote $expect_out(1,string)]" log_info "get_var_contents: result: [quote $expect_out(1,string)]"
puts $expect_out(1,string) puts $expect_out(1,string)

View file

@ -15,20 +15,21 @@ for i in *.expect
begin begin
set -lx XDG_CONFIG_HOME $PWD/tmp.interactive.config set -lx XDG_CONFIG_HOME $PWD/tmp.interactive.config
set -lx TERM dumb set -lx TERM dumb
expect -n -c 'source interactive.expect.rc' -f $i >tmp.out ^tmp.err expect -n -c 'source interactive.expect.rc' -f $i >$i.tmp.out ^$i.tmp.err
end end
set -l tmp_status $status set -l tmp_status $status
set res ok set res ok
if not diff tmp.out $i.out >/dev/null mv -f interactive.tmp.log $i.tmp.log
if not diff $i.tmp.out $i.out >/dev/null
set res fail set res fail
echo "Output differs for file $i. Diff follows:" echo "Output differs for file $i. Diff follows:"
diff -u tmp.out $i.out diff -u $i.tmp.out $i.out
end end
if not diff tmp.err $i.err >/dev/null if not diff $i.tmp.err $i.err >/dev/null
set res fail set res fail
echo "Error output differs for file $i. Diff follows:" echo "Error output differs for file $i. Diff follows:"
diff -u tmp.err $i.err diff -u $i.tmp.err $i.err
end end
if test $tmp_status != (cat $i.status) if test $tmp_status != (cat $i.status)
@ -38,6 +39,8 @@ for i in *.expect
if test $res = ok if test $res = ok
echo "File $i tested ok" echo "File $i tested ok"
# clean up tmp files
rm -f $i.tmp.{err,out,log}
else else
echo "File $i failed tests" echo "File $i failed tests"
end end

View file

@ -1 +1,2 @@
File bind.expect tested ok
File read.expect tested ok File read.expect tested ok