Merge pull request #168 from curusarn/drop_arrow_key_bindings

Drop arrow key bindings
pull/169/head
Šimon Let 4 years ago committed by GitHub
commit 5161c03874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      README.md
  2. 4
      cmd/config/main.go
  3. 2
      cmd/control/cmd/debug.go
  4. 85
      cmd/control/cmd/enable.go
  5. 2
      cmd/control/cmd/root.go
  6. 13
      cmd/control/cmd/status.go
  7. 4
      cmd/control/status/status.go
  8. 2
      conf/config.toml
  9. 68
      scripts/reshctl.sh
  10. 8
      scripts/shellrc.sh
  11. 93
      scripts/widgets.sh

@ -107,17 +107,6 @@ You can install `jq` using your favourite package manager or you can use other J
*Recorded metadata will be reduced to only include useful information in the future.* *Recorded metadata will be reduced to only include useful information in the future.*
## Data sanitization and analysis
In order to be able to develop a good history tool I will need to get some insight into real life shell and shell history usage patterns.
Running `reshctl sanitize` creates a sanitized version of recorded history.
In sanitized history, all sensitive information is replaced with its SHA256 hashes.
If you tried sanitizing your history and you think the result is not sanitized enough then please create an issue or message me.
If you would consider supporting my research/thesis by sending me a sanitized version of your history then please give me some contact info using this form: https://forms.gle/227SoyJ5c2iteKt98
## Known issues ## Known issues
### Q: I use bash on macOS and resh doesn't work ### Q: I use bash on macOS and resh doesn't work

@ -34,10 +34,6 @@ func main() {
*configKey = strings.ToLower(*configKey) *configKey = strings.ToLower(*configKey)
switch *configKey { switch *configKey {
case "bindarrowkeysbash":
printBoolNormalized(config.BindArrowKeysBash)
case "bindarrowkeyszsh":
printBoolNormalized(config.BindArrowKeysZsh)
case "bindcontrolr": case "bindcontrolr":
printBoolNormalized(config.BindControlR) printBoolNormalized(config.BindControlR)
case "port": case "port":

@ -43,8 +43,6 @@ var debugOutputCmd = &cobra.Command{
"collect_last_run_out.txt", "collect_last_run_out.txt",
"postcollect_last_run_out.txt", "postcollect_last_run_out.txt",
"session_init_last_run_out.txt", "session_init_last_run_out.txt",
"arrow_up_last_run_out.txt",
"arrow_down_last_run_out.txt",
} }
usr, _ := user.Current() usr, _ := user.Current()
dir := usr.HomeDir dir := usr.HomeDir

@ -19,20 +19,6 @@ var enableCmd = &cobra.Command{
Short: "enable RESH features (bindings)", Short: "enable RESH features (bindings)",
} }
var enableArrowKeyBindingsCmd = &cobra.Command{
Use: "arrow_key_bindings",
Short: "enable bindings for arrow keys (up/down)",
Long: "Enable bindings for arrow keys (up/down)\n" +
"Note that this only affects sessions of the same shell.\n" +
"(e.g. running this in zsh will only enable the keybinding in zsh)",
Run: func(cmd *cobra.Command, args []string) {
exitCode = enableDisableArrowKeyBindingsGlobally(true)
if exitCode == status.Success {
exitCode = status.EnableArrowKeyBindings
}
},
}
var enableControlRBindingCmd = &cobra.Command{ var enableControlRBindingCmd = &cobra.Command{
Use: "ctrl_r_binding", Use: "ctrl_r_binding",
Short: "enable RESH-CLI binding for Ctrl+R", Short: "enable RESH-CLI binding for Ctrl+R",
@ -51,20 +37,6 @@ var disableCmd = &cobra.Command{
Short: "disable RESH features (bindings)", Short: "disable RESH features (bindings)",
} }
var disableArrowKeyBindingsCmd = &cobra.Command{
Use: "arrow_key_bindings",
Short: "disable bindings for arrow keys (up/down)",
Long: "Disable bindings for arrow keys (up/down)\n" +
"Note that this only affects sessions of the same shell.\n" +
"(e.g. running this in zsh will only enable the keybinding in zsh)",
Run: func(cmd *cobra.Command, args []string) {
exitCode = enableDisableArrowKeyBindingsGlobally(false)
if exitCode == status.Success {
exitCode = status.DisableArrowKeyBindings
}
},
}
var disableControlRBindingCmd = &cobra.Command{ var disableControlRBindingCmd = &cobra.Command{
Use: "ctrl_r_binding", Use: "ctrl_r_binding",
Short: "disable RESH-CLI binding for Ctrl+R", Short: "disable RESH-CLI binding for Ctrl+R",
@ -76,63 +48,6 @@ var disableControlRBindingCmd = &cobra.Command{
}, },
} }
func enableDisableArrowKeyBindingsGlobally(value bool) status.Code {
usr, _ := user.Current()
dir := usr.HomeDir
configPath := filepath.Join(dir, ".config/resh.toml")
var config cfg.Config
if _, err := toml.DecodeFile(configPath, &config); err != nil {
fmt.Println("Error reading config", err)
return status.Fail
}
shell, found := os.LookupEnv("__RESH_ctl_shell")
// shell env variable must be set and must be equal to either bash or zsh
if found == false || (shell != "bash" && shell != "zsh") {
fmt.Println("Error while determining a shell you are using - your RESH instalation is probably broken. Please reinstall RESH - exiting!")
fmt.Println("found=", found, "shell=", shell)
return status.Fail
}
if shell == "bash" {
err := setConfigBindArrowKey(configPath, &config, &config.BindArrowKeysBash, shell, value)
if err != nil {
return status.Fail
}
} else if shell == "zsh" {
err := setConfigBindArrowKey(configPath, &config, &config.BindArrowKeysZsh, shell, value)
if err != nil {
return status.Fail
}
} else {
fmt.Println("FATAL ERROR while determining a shell you are using - your RESH instalation is probably broken. Please reinstall RESH - exiting!")
}
return status.Success
}
// I don't like the interface this function has - passing both config structure and a part of it feels wrong
// It's ugly and could lead to future errors
func setConfigBindArrowKey(configPath string, config *cfg.Config, configField *bool, shell string, value bool) error {
if *configField != value {
*configField = value
f, err := os.Create(configPath)
if err != nil {
fmt.Println("Error: Failed to create/open file:", configPath, "; error:", err)
return err
}
defer f.Close()
if err := toml.NewEncoder(f).Encode(config); err != nil {
fmt.Println("Error: Failed to encode and write the config values to hdd. error:", err)
return err
}
}
if value {
fmt.Println("RESH arrow key bindings: ENABLED (in " + shell + ")")
} else {
fmt.Println("RESH arrow key bindings: DISABLED (in " + shell + ")")
}
return nil
}
func enableDisableControlRBindingGlobally(value bool) status.Code { func enableDisableControlRBindingGlobally(value bool) status.Code {
usr, _ := user.Current() usr, _ := user.Current()
dir := usr.HomeDir dir := usr.HomeDir

@ -42,11 +42,9 @@ func Execute(ver, com string) status.Code {
} }
rootCmd.AddCommand(enableCmd) rootCmd.AddCommand(enableCmd)
enableCmd.AddCommand(enableArrowKeyBindingsCmd)
enableCmd.AddCommand(enableControlRBindingCmd) enableCmd.AddCommand(enableControlRBindingCmd)
rootCmd.AddCommand(disableCmd) rootCmd.AddCommand(disableCmd)
disableCmd.AddCommand(disableArrowKeyBindingsCmd)
disableCmd.AddCommand(disableControlRBindingCmd) disableCmd.AddCommand(disableControlRBindingCmd)
rootCmd.AddCommand(completionCmd) rootCmd.AddCommand(completionCmd)

@ -48,19 +48,6 @@ var statusCmd = &cobra.Command{
fmt.Println(" * Please RESTART this terminal window") fmt.Println(" * Please RESTART this terminal window")
} }
fmt.Println()
fmt.Println("Arrow key bindings ...")
if config.BindArrowKeysBash {
fmt.Println(" * bash future sessions: ENABLED (not recommended)")
} else {
fmt.Println(" * bash future sessions: DISABLED (recommended)")
}
if config.BindArrowKeysZsh {
fmt.Println(" * zsh future sessions: ENABLED (recommended)")
} else {
fmt.Println(" * zsh future sessions: DISABLED (not recommended)")
}
exitCode = status.ReshStatus exitCode = status.ReshStatus
}, },
} }

@ -11,13 +11,9 @@ const (
// EnableResh exit code - tells reshctl() wrapper to enable resh // EnableResh exit code - tells reshctl() wrapper to enable resh
// EnableResh = 30 // EnableResh = 30
// EnableArrowKeyBindings exit code - tells reshctl() wrapper to enable arrow key bindings
EnableArrowKeyBindings = 31
// EnableControlRBinding exit code - tells reshctl() wrapper to enable control R binding // EnableControlRBinding exit code - tells reshctl() wrapper to enable control R binding
EnableControlRBinding = 32 EnableControlRBinding = 32
// DisableArrowKeyBindings exit code - tells reshctl() wrapper to disable arrow key bindings
DisableArrowKeyBindings = 41
// DisableControlRBinding exit code - tells reshctl() wrapper to disable control R binding // DisableControlRBinding exit code - tells reshctl() wrapper to disable control R binding
DisableControlRBinding = 42 DisableControlRBinding = 42
// ReloadRcFiles exit code - tells reshctl() wrapper to reload shellrc resh file // ReloadRcFiles exit code - tells reshctl() wrapper to reload shellrc resh file

@ -2,6 +2,4 @@ port = 2627
sesswatchPeriodSeconds = 120 sesswatchPeriodSeconds = 120
sesshistInitHistorySize = 1000 sesshistInitHistorySize = 1000
debug = false debug = false
bindArrowKeysBash = false
bindArrowKeysZsh = false
bindControlR = true bindControlR = true

@ -4,27 +4,6 @@
# shellcheck source=widgets.sh # shellcheck source=widgets.sh
. ~/.resh/widgets.sh . ~/.resh/widgets.sh
__resh_bind_arrows() {
if [ "${__RESH_arrow_keys_bind_enabled-0}" != 0 ]; then
echo "RESH arrow key bindings are already enabled!"
return 1
fi
bindfunc --revert '\eOA' __resh_widget_arrow_up_compat
__RESH_bindfunc_revert_arrow_up_bind=$_bindfunc_revert
bindfunc --revert '\e[A' __resh_widget_arrow_up_compat
__RESH_bindfunc_revert_arrow_up_bind_vim=$_bindfunc_revert
bindfunc --vim-cmd --revert 'k' __resh_widget_arrow_up_compat
__RESH_bindfunc_revert_k_bind_vim=$_bindfunc_revert
bindfunc --revert '\eOB' __resh_widget_arrow_down_compat
__RESH_bindfunc_revert_arrow_down_bind=$_bindfunc_revert
bindfunc --revert '\e[B' __resh_widget_arrow_down_compat
__RESH_bindfunc_revert_arrow_down_bind_vim=$_bindfunc_revert
bindfunc --vim-cmd --revert 'j' __resh_widget_arrow_down_compat
__RESH_bindfunc_revert_j_bind_vim=$_bindfunc_revert
__RESH_arrow_keys_bind_enabled=1
return 0
}
__resh_nop() { __resh_nop() {
# does nothing # does nothing
true true
@ -53,34 +32,6 @@ __resh_bind_control_R() {
return 0 return 0
} }
__resh_unbind_arrows() {
if [ "${__RESH_arrow_keys_bind_enabled-0}" != 1 ]; then
echo "RESH arrow key bindings are already disabled!"
return 1
fi
if [ -z "${__RESH_bindfunc_revert_arrow_up_bind+x}" ]; then
echo "Warn: Couldn't revert arrow UP binding because 'revert command' is empty."
else
eval "$__RESH_bindfunc_revert_arrow_up_bind"
[ -z "${__RESH_bindfunc_revert_arrow_up_bind_vim+x}" ] || eval "$__RESH_bindfunc_revert_arrow_up_bind_vim"
[ -z "${__RESH_bindfunc_revert_k_bind_vim+x}" ] || eval "$__RESH_bindfunc_revert_k_bind_vim"
echo "RESH arrow up binding successfully disabled"
__RESH_arrow_keys_bind_enabled=0
fi
if [ -z "${__RESH_bindfunc_revert_arrow_down_bind+x}" ]; then
echo "Warn: Couldn't revert arrow DOWN binding because 'revert command' is empty."
else
eval "$__RESH_bindfunc_revert_arrow_down_bind"
[ -z "${__RESH_bindfunc_revert_arrow_down_bind_vim+x}" ] || eval "$__RESH_bindfunc_revert_arrow_down_bind_vim"
[ -z "${__RESH_bindfunc_revert_j_bind_vim+x}" ] || eval "$__RESH_bindfunc_revert_j_bind_vim"
echo "RESH arrow down binding successfully disabled"
__RESH_arrow_keys_bind_enabled=0
fi
return 0
}
__resh_unbind_control_R() { __resh_unbind_control_R() {
if [ "${__RESH_control_R_bind_enabled-0}" != 1 ]; then if [ "${__RESH_control_R_bind_enabled-0}" != 1 ]; then
echo "RESH SEARCH app Ctrl+R binding is already disabled!" echo "RESH SEARCH app Ctrl+R binding is already disabled!"
@ -96,12 +47,10 @@ __resh_unbind_control_R() {
} }
__resh_bind_all() { __resh_bind_all() {
__resh_bind_arrows
__resh_bind_control_R __resh_bind_control_R
} }
__resh_unbind_all() { __resh_unbind_all() {
__resh_unbind_arrows
__resh_unbind_control_R __resh_unbind_control_R
} }
@ -151,11 +100,6 @@ reshctl() {
# __resh_bind_all # __resh_bind_all
# return 0 # return 0
# ;; # ;;
31)
# enable arrow keys
__resh_bind_arrows
return 0
;;
32) 32)
# enable control R # enable control R
__resh_bind_control_R __resh_bind_control_R
@ -167,11 +111,6 @@ reshctl() {
# __resh_unbind_all # __resh_unbind_all
# return 0 # return 0
# ;; # ;;
41)
# disable arrow keys
__resh_unbind_arrows
return 0
;;
42) 42)
# disable control R # disable control R
__resh_unbind_control_R __resh_unbind_control_R
@ -190,15 +129,10 @@ reshctl() {
;; ;;
52) 52)
# show status # show status
if [ "${__RESH_arrow_keys_bind_enabled-0}" != 0 ]; then
echo ' * this session: ENABLED'
else
echo ' * this session: DISABLED'
fi
echo echo
echo 'Control R binding ...' echo 'Control R binding ...'
if [ "$(resh-config --key BindControlR)" = true ]; then if [ "$(resh-config --key BindControlR)" = true ]; then
echo ' * future sessions: ENABLED (experimental)' echo ' * future sessions: ENABLED'
else else
echo ' * future sessions: DISABLED' echo ' * future sessions: DISABLED'
fi fi

@ -90,14 +90,6 @@ if [ -z "${__RESH_INIT_DONE+x}" ]; then
__resh_reset_variables __resh_reset_variables
if [ "$__RESH_SHELL" = bash ] ; then
[ "$(resh-config --key BindArrowKeysBash)" = true ] && __resh_bind_arrows
elif [ "$__RESH_SHELL" = zsh ] ; then
[ "$(resh-config --key BindArrowKeysZsh)" = true ] && __resh_bind_arrows
else
echo "RESH error: unknown shell (init)"
echo "$__RESH_SHELL"
fi
[ "$(resh-config --key BindControlR)" = true ] && __resh_bind_control_R [ "$(resh-config --key BindControlR)" = true ] && __resh_bind_control_R
__RESH_INIT_DONE=1 __RESH_INIT_DONE=1

@ -2,91 +2,6 @@
# shellcheck source=hooks.sh # shellcheck source=hooks.sh
. ~/.resh/hooks.sh . ~/.resh/hooks.sh
__resh_helper_arrow_pre() {
# this is a very bad workaround
# force bash-preexec to run repeatedly because otherwise premature run of bash-preexec overshadows the next poper run
# I honestly think that it's impossible to make widgets work in bash without hacks like this
# shellcheck disable=2034
__bp_preexec_interactive_mode="on"
# set recall strategy
__RESH_HIST_RECALL_STRATEGY="bash_recent - history-search-{backward,forward}"
# set prefix
__RESH_PREFIX=${BUFFER:0:$CURSOR}
# cursor not at the end of the line => end "NO_PREFIX_MODE"
[ "$CURSOR" -ne "${#BUFFER}" ] && __RESH_HIST_NO_PREFIX_MODE=0
# if user moved the cursor or made edits (to prefix) from last recall action
# => restart histno AND deactivate "NO_PREFIX_MODE" AND clear end of recall list histno
[ "$__RESH_PREFIX" != "$__RESH_HIST_PREV_PREFIX" ] && __RESH_HISTNO=0 && __RESH_HIST_NO_PREFIX_MODE=0 && __RESH_HISTNO_MAX=""
# "NO_PREFIX_MODE" => set prefix to empty string
[ "$__RESH_HIST_NO_PREFIX_MODE" -eq 1 ] && __RESH_PREFIX=""
# histno == 0 => save current line
[ "$__RESH_HISTNO" -eq 0 ] && __RESH_HISTNO_ZERO_LINE=$BUFFER
}
__resh_helper_arrow_post() {
# cursor at the beginning of the line => activate "NO_PREFIX_MODE"
[ "$CURSOR" -eq 0 ] && __RESH_HIST_NO_PREFIX_MODE=1
# "NO_PREFIX_MODE" => move cursor to the end of the line
[ "$__RESH_HIST_NO_PREFIX_MODE" -eq 1 ] && CURSOR=${#BUFFER}
# save current prefix so we can spot when user moves cursor or edits (the prefix part of) the line
__RESH_HIST_PREV_PREFIX=${BUFFER:0:$CURSOR}
# recorded to history
__RESH_HIST_PREV_LINE=${BUFFER}
}
__resh_widget_arrow_up() {
# run helper function
__resh_helper_arrow_pre
# append curent recall action
__RESH_HIST_RECALL_ACTIONS="$__RESH_HIST_RECALL_ACTIONS|||arrow_up:$__RESH_PREFIX"
# increment histno
__RESH_HISTNO=$((__RESH_HISTNO+1))
if [ "${#__RESH_HISTNO_MAX}" -gt 0 ] && [ "${__RESH_HISTNO}" -gt "${__RESH_HISTNO_MAX}" ]; then
# end of the recall list -> don't recall, do nothing
# fix histno
__RESH_HISTNO=$((__RESH_HISTNO-1))
elif [ "$__RESH_HISTNO" -eq 0 ]; then
# back at histno == 0 => restore original line
BUFFER=$__RESH_HISTNO_ZERO_LINE
else
# run recall
local NEW_BUFFER
local status_code
NEW_BUFFER="$(__resh_collect --recall --prefix-search "$__RESH_PREFIX" 2>| ~/.resh/arrow_up_last_run_out.txt)"
status_code=$?
# revert histno change on error
# shellcheck disable=SC2015
if [ "${status_code}" -eq 0 ]; then
BUFFER=$NEW_BUFFER
else
__RESH_HISTNO=$((__RESH_HISTNO-1))
__RESH_HISTNO_MAX=$__RESH_HISTNO
fi
fi
# run post helper
__resh_helper_arrow_post
}
__resh_widget_arrow_down() {
# run helper function
__resh_helper_arrow_pre
# append curent recall action
__RESH_HIST_RECALL_ACTIONS="$__RESH_HIST_RECALL_ACTIONS|||arrow_down:$__RESH_PREFIX"
# increment histno
__RESH_HISTNO=$((__RESH_HISTNO-1))
# prevent HISTNO from getting negative (for now)
[ "$__RESH_HISTNO" -lt 0 ] && __RESH_HISTNO=0
# back at histno == 0 => restore original line
if [ "$__RESH_HISTNO" -eq 0 ]; then
BUFFER=$__RESH_HISTNO_ZERO_LINE
else
# run recall
local NEW_BUFFER
NEW_BUFFER="$(__resh_collect --recall --prefix-search "$__RESH_PREFIX" 2>| ~/.resh/arrow_down_last_run_out.txt)"
# IF new buffer in non-empty THEN use the new buffer ELSE revert histno change
# shellcheck disable=SC2015
[ "${#NEW_BUFFER}" -gt 0 ] && BUFFER=$NEW_BUFFER || (( __RESH_HISTNO++ ))
fi
__resh_helper_arrow_post
}
__resh_widget_control_R() { __resh_widget_control_R() {
# this is a very bad workaround # this is a very bad workaround
# force bash-preexec to run repeatedly because otherwise premature run of bash-preexec overshadows the next poper run # force bash-preexec to run repeatedly because otherwise premature run of bash-preexec overshadows the next poper run
@ -129,14 +44,6 @@ __resh_widget_control_R() {
__RESH_HIST_PREV_LINE=${BUFFER} __RESH_HIST_PREV_LINE=${BUFFER}
} }
__resh_widget_arrow_up_compat() {
__bindfunc_compat_wrapper __resh_widget_arrow_up
}
__resh_widget_arrow_down_compat() {
__bindfunc_compat_wrapper __resh_widget_arrow_down
}
__resh_widget_control_R_compat() { __resh_widget_control_R_compat() {
__bindfunc_compat_wrapper __resh_widget_control_R __bindfunc_compat_wrapper __resh_widget_control_R
} }

Loading…
Cancel
Save