From a7d367ed38b2e5035503e89f85c9dafe0f94bcd2 Mon Sep 17 00:00:00 2001 From: Simon Let Date: Mon, 20 Jan 2020 22:59:31 +0100 Subject: [PATCH] add full support for ctrl r in bash, search tweaks, fixes --- cmd/cli/main.go | 90 ++++++++++++++++++++++++++++++---------------- conf/config.toml | 2 +- scripts/reshctl.sh | 19 +++++++--- scripts/widgets.sh | 12 +++---- 4 files changed, 81 insertions(+), 42 deletions(-) diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 9db47ca..870f4c3 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -8,7 +8,6 @@ import ( "fmt" "io/ioutil" "log" - "math" "net/http" "os" "sort" @@ -60,7 +59,6 @@ func runReshCli() (string, int) { log.Fatal("Error reading config:", err) } if config.Debug { - // Debug = true log.SetFlags(log.LstdFlags | log.Lmicroseconds) } @@ -95,7 +93,8 @@ func runReshCli() (string, int) { st := state{ // lock sync.Mutex - fullRecords: resp.FullRecords, + fullRecords: resp.FullRecords, + initialQuery: *query, } layout := manager{ @@ -279,24 +278,33 @@ func properMatch(str, term, padChar string) bool { // newItemFromRecordForQuery creates new item from record based on given query // returns error if the query doesn't match the record -func newItemFromRecordForQuery(record records.EnrichedRecord, query query) (item, error) { +func newItemFromRecordForQuery(record records.EnrichedRecord, query query, debug bool) (item, error) { // TODO: use color to highlight matches + const hitScore = 1.0 + const hitScoreConsecutive = 0.1 const properMatchScore = 0.3 const actualPwdScore = 0.9 + const actualPwdScoreExtra = 0.2 hits := 0.0 + if record.ExitCode != 0 { + hits-- + } cmd := record.CmdLine pwdTilde := strings.Replace(record.Pwd, record.Home, "~", 1) pwdDisp := leftCutPadString(pwdTilde, 25) pwdRawDisp := leftCutPadString(record.Pwd, 25) var useRawPwd bool + var dirHit bool for _, term := range query.terms { - alreadyHit := false + termHit := false if strings.Contains(record.CmdLine, term) { - if alreadyHit == false { - hits++ + if termHit == false { + hits += hitScore + } else { + hits += hitScoreConsecutive } - alreadyHit = true + termHit = true if properMatch(cmd, term, " ") { hits += properMatchScore } @@ -304,36 +312,48 @@ func newItemFromRecordForQuery(record records.EnrichedRecord, query query) (item // NO continue } if strings.Contains(pwdTilde, term) { - if alreadyHit == false { - hits++ + if termHit == false { + hits += hitScore + } else { + hits += hitScoreConsecutive } - alreadyHit = true - if properMatch(pwdTilde, term, " ") { + termHit = true + if properMatch(pwdTilde, term, "/") { hits += properMatchScore } pwdDisp = strings.ReplaceAll(pwdDisp, term, highlightMatch(term)) - useRawPwd = false - continue // IMPORTANT - } - if strings.Contains(record.Pwd, term) { - if alreadyHit == false { - hits++ + pwdRawDisp = strings.ReplaceAll(pwdRawDisp, term, highlightMatch(term)) + dirHit = true + } else if strings.Contains(record.Pwd, term) { + if termHit == false { + hits += hitScore + } else { + hits += hitScoreConsecutive } - alreadyHit = true - if properMatch(pwdTilde, term, " ") { + termHit = true + if properMatch(pwdTilde, term, "/") { hits += properMatchScore } pwdRawDisp = strings.ReplaceAll(pwdRawDisp, term, highlightMatch(term)) + dirHit = true useRawPwd = true - continue // IMPORTANT } // if strings.Contains(record.GitOriginRemote, term) { // hits++ // } } // actual pwd matches + // only use if there was no directory match on any of the terms + // N terms can only produce: + // -> N matches against the command + // -> N matches against the directory + // -> 1 extra match for the actual directory match if record.Pwd == query.pwd { - hits += actualPwdScore + if dirHit { + hits += actualPwdScoreExtra + } else { + hits += actualPwdScore + } pwdDisp = highlightMatchAlternative(pwdDisp) // pwdRawDisp = highlightMatchAlternative(pwdRawDisp) useRawPwd = false @@ -348,8 +368,13 @@ func newItemFromRecordForQuery(record records.EnrichedRecord, query query) (item } else { display += pwdDisp } - hitsDisp := " " + rightCutPadString(strconv.Itoa(int(math.Floor(hits))), 2) - display += hitsDisp + if debug { + hitsStr := fmt.Sprintf("%.1f", hits) + hitsDisp := " " + hitsStr + " " + display += hitsDisp + } else { + display += " " + } // cmd := "<" + strings.ReplaceAll(record.CmdLine, "\n", ";") + ">" cmd = strings.ReplaceAll(cmd, "\n", ";") display += cmd @@ -383,6 +408,8 @@ type state struct { data []item highlightedItem int + initialQuery string + output string exitCode int } @@ -427,7 +454,7 @@ func (m manager) UpdateData(input string) { m.s.lock.Lock() defer m.s.lock.Unlock() for _, rec := range m.s.fullRecords { - itm, err := newItemFromRecordForQuery(rec, query) + itm, err := newItemFromRecordForQuery(rec, query, m.config.Debug) if err != nil { // records didn't match the query // log.Println(" * continue (no match)", rec.Pwd) @@ -482,8 +509,6 @@ func (m manager) Prev(g *gocui.Gui, v *gocui.View) error { return nil } -// you can have Layout with pointer reciever if you pass the layout function to the setmanger -// I dont think we need that tho func (m manager) Layout(g *gocui.Gui) error { var b byte maxX, maxY := g.Size() @@ -494,12 +519,19 @@ func (m manager) Layout(g *gocui.Gui) error { } v.Editable = true - // v.Editor = gocui.EditorFunc(m.editor.Edit) v.Editor = m v.Title = "resh cli" g.SetCurrentView("input") + m.s.lock.Lock() + defer m.s.lock.Unlock() + if len(m.s.initialQuery) > 0 { + v.WriteString(m.s.initialQuery) + v.SetCursor(len(m.s.initialQuery), 0) + m.s.initialQuery = "" + } + v, err = g.SetView("body", 0, 2, maxX-1, maxY, b) if err != nil && gocui.IsUnknownView(err) == false { log.Panicln(err.Error()) @@ -509,8 +541,6 @@ func (m manager) Layout(g *gocui.Gui) error { v.Clear() v.Rewind() - m.s.lock.Lock() - defer m.s.lock.Unlock() for i, itm := range m.s.data { if i == maxY { log.Println(maxY) diff --git a/conf/config.toml b/conf/config.toml index fb1b618..2e0adc2 100644 --- a/conf/config.toml +++ b/conf/config.toml @@ -1,7 +1,7 @@ port = 2627 sesswatchPeriodSeconds = 120 sesshistInitHistorySize = 1000 -debug = true +debug = false bindArrowKeysBash = false bindArrowKeysZsh = true bindControlR = false diff --git a/scripts/reshctl.sh b/scripts/reshctl.sh index 62bca40..794c478 100644 --- a/scripts/reshctl.sh +++ b/scripts/reshctl.sh @@ -25,6 +25,11 @@ __resh_bind_arrows() { return 0 } +__resh_nop() { + # does nothing + true +} + __resh_bind_control_R() { if [ "${__RESH_control_R_bind_enabled-0}" != 0 ]; then echo "Error: Can't enable control R binding because it is already enabled!" @@ -34,13 +39,15 @@ __resh_bind_control_R() { __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 + bind '"\C-r": "\u[31~\u[32~"' + bind -x '"\u[31~": __resh_widget_control_R_compat' + # execute + # bind '"\u[32~": accept-line' + + # just paste + # bind -x '"\u[32~": __resh_nop' true fi return 0 @@ -110,6 +117,8 @@ resh() { elif [ $status_code = 0 ]; then # paste echo "$buffer" + elif [ $status_code = 130 ]; then + true else echo "$buffer" > ~/.resh/cli_last_run_out.txt echo "resh-cli ERROR:" diff --git a/scripts/widgets.sh b/scripts/widgets.sh index 0c1b849..68a2266 100644 --- a/scripts/widgets.sh +++ b/scripts/widgets.sh @@ -102,18 +102,18 @@ __resh_widget_control_R() { # zsh zle accept-line elif [ -n "${BASH_VERSION-}" ]; then - echo "BASH is not currently not supported for control R binding - sorry" # bash - # TODO set chained keyseq to accept-line - true + # set chained keyseq to accept-line + bind '"\u[32~": accept-line' fi elif [ $status_code = 0 ]; then if [ -n "${BASH_VERSION-}" ]; then - echo "BASH is not currently not supported for control R binding - sorry" # bash - # TODO set chained keyseq to nothing - true + # set chained keyseq to nothing + bind -x '"\u[32~": __resh_nop' fi + elif [ $status_code = 130 ]; then + BUFFER="$PREVBUFFER" 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)"