diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 1db540e..9db47ca 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -32,7 +32,16 @@ var version string // commit from git set during build var commit string +// special constant recognized by RESH wrappers +const exitCodeExecute = 111 + func main() { + output, exitCode := runReshCli() + fmt.Print(output) + os.Exit(exitCode) +} + +func runReshCli() (string, int) { usr, _ := user.Current() dir := usr.HomeDir configPath := filepath.Join(dir, "/.config/resh.toml") @@ -57,6 +66,7 @@ func main() { sessionID := flag.String("sessionID", "", "resh generated session id") pwd := flag.String("pwd", "", "present working directory") + query := flag.String("query", "", "search query") flag.Parse() if *sessionID == "" { @@ -111,13 +121,16 @@ func main() { if err := g.SetKeybinding("", gocui.KeyEnter, gocui.ModNone, layout.SelectExecute); err != nil { log.Panicln(err) } + if err := g.SetKeybinding("", gocui.KeyArrowRight, gocui.ModNone, layout.SelectPaste); err != nil { + log.Panicln(err) + } - layout.UpdateData("") + layout.UpdateData(*query) err = g.MainLoop() if err != nil && gocui.IsQuit(err) == false { log.Panicln(err) } - layout.Output() + return layout.s.output, layout.s.exitCode } func leftCutPadString(str string, newLen int) string { @@ -370,7 +383,8 @@ type state struct { data []item highlightedItem int - outputBuffer string + output string + exitCode int } type manager struct { @@ -381,19 +395,23 @@ type manager struct { s *state } -func (m manager) Output() { +func (m manager) SelectExecute(g *gocui.Gui, v *gocui.View) error { m.s.lock.Lock() defer m.s.lock.Unlock() - if len(m.s.outputBuffer) > 0 { - fmt.Print(m.s.outputBuffer) + if m.s.highlightedItem < len(m.s.data) { + m.s.output = m.s.data[m.s.highlightedItem].cmdLine + m.s.exitCode = exitCodeExecute + return gocui.ErrQuit } + return nil } -func (m manager) SelectExecute(g *gocui.Gui, v *gocui.View) error { +func (m manager) SelectPaste(g *gocui.Gui, v *gocui.View) error { m.s.lock.Lock() defer m.s.lock.Unlock() if m.s.highlightedItem < len(m.s.data) { - m.s.outputBuffer = m.s.data[m.s.highlightedItem].cmdLine + "\n" + m.s.output = m.s.data[m.s.highlightedItem].cmdLine + m.s.exitCode = 0 // success return gocui.ErrQuit } return nil diff --git a/cmd/control/cmd/disable.go b/cmd/control/cmd/disable.go deleted file mode 100644 index f661585..0000000 --- a/cmd/control/cmd/disable.go +++ /dev/null @@ -1,30 +0,0 @@ -package cmd - -import ( - "github.com/curusarn/resh/cmd/control/status" - "github.com/spf13/cobra" -) - -var disableCmd = &cobra.Command{ - Use: "disable", - Short: "disable RESH features (arrow key bindings)", -} - -var disableArrowKeyBindingsCmd = &cobra.Command{ - Use: "arrow_key_bindings", - Short: "disable bindings for arrow keys (up/down) FOR THIS SHELL SESSION", - Run: func(cmd *cobra.Command, args []string) { - exitCode = status.DisableArrowKeyBindings - }, -} - -var disableArrowKeyBindingsGlobalCmd = &cobra.Command{ - Use: "arrow_key_bindings_global", - Short: "disable bindings for arrow keys (up/down) FOR FUTURE SHELL SESSIONS", - Long: "Disable bindings for arrow keys (up/down) FOR FUTURE SHELL SESSIONS.\n" + - "Note that this only affects sessions of the same shell.\n" + - "(e.g. running this in zsh will only affect future zsh sessions)", - Run: func(cmd *cobra.Command, args []string) { - exitCode = enableDisableArrowKeyBindingsGlobally(false) - }, -} diff --git a/cmd/control/cmd/enable.go b/cmd/control/cmd/enable.go index f2913a4..e341993 100644 --- a/cmd/control/cmd/enable.go +++ b/cmd/control/cmd/enable.go @@ -12,9 +12,11 @@ import ( "github.com/spf13/cobra" ) +// Enable commands + var enableCmd = &cobra.Command{ Use: "enable", - Short: "enable RESH features (arrow key bindings)", + Short: "enable RESH features (bindings)", } var enableArrowKeyBindingsCmd = &cobra.Command{ @@ -36,6 +38,64 @@ var enableArrowKeyBindingsGlobalCmd = &cobra.Command{ }, } +var enableControlRBindingCmd = &cobra.Command{ + Use: "ctrl_r_binding", + Short: "enable binding for control+R FOR THIS SHELL SESSION", + Run: func(cmd *cobra.Command, args []string) { + exitCode = status.EnableControlRBinding + }, +} + +var enableControlRBindingGlobalCmd = &cobra.Command{ + Use: "ctrl_r_binding_global", + Short: "enable bindings for control+R FOR FUTURE SHELL SESSIONS", + Run: func(cmd *cobra.Command, args []string) { + exitCode = enableDisableArrowKeyBindingsGlobally(true) + }, +} + +// Disable commands + +var disableCmd = &cobra.Command{ + Use: "disable", + Short: "disable RESH features (bindings)", +} + +var disableArrowKeyBindingsCmd = &cobra.Command{ + Use: "arrow_key_bindings", + Short: "disable bindings for arrow keys (up/down) FOR THIS SHELL SESSION", + Run: func(cmd *cobra.Command, args []string) { + exitCode = status.DisableArrowKeyBindings + }, +} + +var disableArrowKeyBindingsGlobalCmd = &cobra.Command{ + Use: "arrow_key_bindings_global", + Short: "disable bindings for arrow keys (up/down) FOR FUTURE SHELL SESSIONS", + Long: "Disable bindings for arrow keys (up/down) FOR FUTURE SHELL SESSIONS.\n" + + "Note that this only affects sessions of the same shell.\n" + + "(e.g. running this in zsh will only affect future zsh sessions)", + Run: func(cmd *cobra.Command, args []string) { + exitCode = enableDisableControlRBindingGlobally(false) + }, +} + +var disableControlRBindingCmd = &cobra.Command{ + Use: "ctrl_r_binding", + Short: "disable binding for control+R FOR THIS SHELL SESSION", + Run: func(cmd *cobra.Command, args []string) { + exitCode = status.DisableControlRBinding + }, +} + +var disableControlRBindingGlobalCmd = &cobra.Command{ + Use: "ctrl_r_binding_global", + Short: "disable bindings for control+R FOR FUTURE SHELL SESSIONS", + Run: func(cmd *cobra.Command, args []string) { + exitCode = enableDisableControlRBindingGlobally(false) + }, +} + func enableDisableArrowKeyBindingsGlobally(value bool) status.Code { usr, _ := user.Current() dir := usr.HomeDir @@ -105,3 +165,47 @@ func setConfigBindArrowKey(configPath string, config *cfg.Config, configField *b } return nil } + +func enableDisableControlRBindingGlobally(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 + } + if config.BindControlR == value { + if value { + fmt.Println("The RESH control+R binding is ALREADY GLOBALLY ENABLED for all future shell sessions - nothing to do - exiting.") + } else { + fmt.Println("The RESH control+R binding is ALREADY GLOBALLY DISABLED for all future shell sessions - nothing to do - exiting.") + } + return status.Fail + } + if value { + fmt.Println("ENABLING the RESH arrow key bindings GLOBALLY ...") + } else { + fmt.Println("DISABLING the RESH arrow key bindings GLOBALLY ...") + } + config.BindControlR = value + + f, err := os.Create(configPath) + if err != nil { + fmt.Println("Error: Failed to create/open file:", configPath, "; error:", err) + return status.Fail + } + 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 status.Fail + } + if value { + fmt.Println("SUCCESSFULLY ENABLED the RESH arrow key bindings GLOBALLY " + + "- every new shell session will start with enabled RESH CLI control+R binding!") + } else { + fmt.Println("SUCCESSFULLY DISABLED the RESH arrow key bindings GLOBALLY " + + "- every new shell session will start with your orignal control+R key binding!") + } + return status.Success +} diff --git a/cmd/control/cmd/root.go b/cmd/control/cmd/root.go index 6ea0407..b3eea27 100644 --- a/cmd/control/cmd/root.go +++ b/cmd/control/cmd/root.go @@ -41,13 +41,17 @@ func Execute(ver, com string) status.Code { // log.SetFlags(log.LstdFlags | log.Lmicroseconds) } - rootCmd.AddCommand(disableCmd) - disableCmd.AddCommand(disableArrowKeyBindingsCmd) - disableCmd.AddCommand(disableArrowKeyBindingsGlobalCmd) - rootCmd.AddCommand(enableCmd) enableCmd.AddCommand(enableArrowKeyBindingsCmd) enableCmd.AddCommand(enableArrowKeyBindingsGlobalCmd) + enableCmd.AddCommand(enableControlRBindingCmd) + enableCmd.AddCommand(enableControlRBindingGlobalCmd) + + rootCmd.AddCommand(disableCmd) + disableCmd.AddCommand(disableArrowKeyBindingsCmd) + disableCmd.AddCommand(disableArrowKeyBindingsGlobalCmd) + disableCmd.AddCommand(disableControlRBindingCmd) + disableCmd.AddCommand(disableControlRBindingGlobalCmd) rootCmd.AddCommand(completionCmd) completionCmd.AddCommand(completionBashCmd) diff --git a/cmd/control/status/status.go b/cmd/control/status/status.go index d39adb4..c83e2df 100644 --- a/cmd/control/status/status.go +++ b/cmd/control/status/status.go @@ -13,11 +13,15 @@ const ( // EnableArrowKeyBindings exit code - tells reshctl() wrapper to enable arrow key bindings EnableArrowKeyBindings = 101 + // EnableControlRBinding exit code - tells reshctl() wrapper to enable control R binding + EnableControlRBinding = 102 // DisableResh exit code - tells reshctl() wrapper to enable resh // DisableResh = 110 // DisableArrowKeyBindings exit code - tells reshctl() wrapper to disable arrow key bindings DisableArrowKeyBindings = 111 + // DisableControlRBinding exit code - tells reshctl() wrapper to disable control R binding + DisableControlRBinding = 112 // ReloadRcFiles exit code - tells reshctl() wrapper to reload shellrc resh file ReloadRcFiles = 200 // InspectSessionHistory exit code - tells reshctl() wrapper to take current sessionID and send /inspect request to daemon diff --git a/pkg/cfg/cfg.go b/pkg/cfg/cfg.go index 2cfdbc2..06cc44d 100644 --- a/pkg/cfg/cfg.go +++ b/pkg/cfg/cfg.go @@ -8,4 +8,5 @@ type Config struct { Debug bool BindArrowKeysBash bool BindArrowKeysZsh bool + BindControlR bool } diff --git a/scripts/reshctl.sh b/scripts/reshctl.sh index 12ee683..7a0a6dc 100644 --- a/scripts/reshctl.sh +++ b/scripts/reshctl.sh @@ -26,8 +26,23 @@ __resh_bind_arrows() { } __resh_bind_control_R() { - # TODO - echo "bindfunc __resh_widget_control_R_compat" + if [ "${__RESH_control_R_bind_enabled-0}" != 0 ]; then + echo "Error: Can't enable control R binding because it is already enabled!" + return 1 + fi + bindfunc --revert '\C-r' __resh_widget_control_R_compat + __RESH_bindfunc_revert_control_R_bind=$_bindfunc_revert + __RESH_control_R_bind_enabled=1 + if [ -n "${BASH_VERSION-}" ]; then + echo "BASH is not currently not supported" + return 1 + # fuck bash + # TODO set \C-r bind to \impossible1 \impossible2 + # set \impossible1 to widget + # that's it - \impossible2 is set in the widget and revert function is still working + + true + fi return 0 } @@ -60,8 +75,15 @@ __resh_unbind_arrows() { } __resh_unbind_control_R() { - # TODO - echo "\ bindfunc __resh_widget_control_R_compat" + if [ "${__RESH_control_R_bind_enabled-0}" != 1 ]; then + echo "Error: Can't disable control R binding because it is not enabled!" + return 1 + fi + if [ -z "${__RESH_bindfunc_revert_control_R_bind+x}" ]; then + echo "Warn: Couldn't revert control R binding because 'revert command' is empty." + else + eval "$__RESH_bindfunc_revert_control_R_bind" + fi return 0 } @@ -78,6 +100,7 @@ __resh_unbind_all() { # wrapper for resh-cli # meant to be launched on ctrl+R resh() { + # TODO: rewrite this based on the widget if resh-cli --sessionID "$__RESH_SESSION_ID" --pwd "$PWD" > ~/.resh/cli_last_run_out.txt 2>&1; then # insert on cmdline cat ~/.resh/cli_last_run_out.txt @@ -118,6 +141,11 @@ reshctl() { __resh_bind_arrows return 0 ;; + 102) + # enable control R + __resh_bind_control_R + return 0 + ;; # disable # 110) # # disable all @@ -129,6 +157,11 @@ reshctl() { __resh_unbind_arrows return 0 ;; + 112) + # disable control R + __resh_unbind_control_R + return 0 + ;; 200) # reload rc files . ~/.resh/shellrc diff --git a/scripts/widgets.sh b/scripts/widgets.sh index ceba081..1d67513 100644 --- a/scripts/widgets.sh +++ b/scripts/widgets.sh @@ -88,10 +88,38 @@ __resh_widget_arrow_down() { __resh_helper_arrow_post } __resh_widget_control_R() { - local __RESH_PREFIX=${BUFFER:0:CURSOR} - __RESH_HIST_RECALL_ACTIONS="$__RESH_HIST_RECALL_ACTIONS;control_R:$__RESH_PREFIX" - # resh-collect --hstr - hstr + # local __RESH_PREFIX=${BUFFER:0:CURSOR} + # __RESH_HIST_RECALL_ACTIONS="$__RESH_HIST_RECALL_ACTIONS;control_R:$__RESH_PREFIX" + local PREVBUFFER=$BUFFER + __RESH_HIST_RECALL_ACTIONS="$__RESH_HIST_RECALL_ACTIONS;control_R:$BUFFER" + + local status_code + BUFFER=$(resh-cli --sessionID "$__RESH_SESSION_ID" --pwd "$PWD" --query "$BUFFER") + status_code=$? + if [ $status_code = 111 ]; then + # execute + if [ -n "${ZSH_VERSION-}" ]; then + # zsh + zle accept-line + elif [ -n "${BASH_VERSION-}" ]; then + echo "BASH is not currently not supported" + # bash + # TODO set chained keyseq to accept-line + true + fi + elif [ $status_code = 0 ]; then + if [ -n "${BASH_VERSION-}" ]; then + echo "BASH is not currently not supported" + # bash + # TODO set chained keyseq to nothing + true + fi + else + echo "$BUFFER" > ~/.resh/cli_last_run_out.txt + echo "# RESH cli failed - sorry for the inconvinience (error output was saved to ~/.resh/cli_last_run_out.txt)" + BUFFER="$PREVBUFFER" + fi + CURSOR=${#BUFFER} } __resh_widget_arrow_up_compat() {