diff --git a/display/display.go b/display/display.go index 17178e4..8c1bf5c 100644 --- a/display/display.go +++ b/display/display.go @@ -30,9 +30,10 @@ var termH int var bottomBar = cview.NewInputField() var originalText []byte -var searchBar = cview.NewInputField() var tagsRegex = regexp.MustCompile(`\[[a-zA-Z0-9_,;: \-\."#]+[^\[]*\]`) +var searchMode = false var searchString = "" +var bottomBarText = "" var matches = 0 var curMatch = 0 @@ -146,6 +147,11 @@ func Init(version, commit, builtBy string) { // Reset func to set the bottomBar back to what it was before // Use for errors. reset := func() { + if searchMode { + tabs[tab].mode = tabModeDone + searchMode = false + bottomBar.SetText(bottomBarText) + } bottomBar.SetLabel("") tabs[tab].applyAll() App.SetFocus(tabs[tab].view) @@ -154,6 +160,68 @@ func Init(version, commit, builtBy string) { //nolint:exhaustive switch key { case tcell.KeyEnter: + + if searchMode { + // Escape the search string to not find regexp symbols + searchString = regexp.QuoteMeta(bottomBar.GetText()) + + if strings.TrimSpace(searchString) == "" { + // Ignore + reset() + return + } + + if tabs[tab].mode != tabModeSearch { + originalText = tabs[curTab].view.GetBytes(false) + } + tabs[tab].mode = tabModeSearch + + // find all positions of the search string + searchRegex := regexp.MustCompile(searchString) + searchIdx := searchRegex.FindAllIndex(originalText, -1) + + // find all positions of tags + tagsIdx := tagsRegex.FindAllIndex(originalText, -1) + + text := make([]byte, 0) + matches = 0 + lastMatch := 0 + var isMatch bool + + // loops through all occurrences and check if they + // discard if they lie within tags. + // []byte text is build from the original text buffer + // with the actual search strings replaced by tagged regions + // to highlight. + for i, match := range searchIdx { + isMatch = true + for _, tag := range tagsIdx { + if match[0] >= tag[0] && match[1] <= tag[1] { + isMatch = false + break + } + } + + if isMatch { + matches++ + text = append(text, originalText[lastMatch:match[0]]...) + replacement := []byte(fmt.Sprint(`["search-`, i, `"]`, searchString, `[""]`)) + text = append(text, replacement...) + lastMatch = match[0] + len(searchString) + } + } + text = append(text, originalText[lastMatch:]...) + + tabs[curTab].view.SetBytes(text) + + curMatch = 0 + tabs[curTab].view.Highlight(fmt.Sprint("search-", "0")) + tabs[curTab].view.ScrollToHighlight() + App.SetFocus(tabs[tab].view) + + return + } + // Figure out whether it's a URL, link number, or search // And send out a request @@ -260,87 +328,6 @@ func Init(version, commit, builtBy string) { // Other potential keys are Tab and Backtab, they are ignored }) - searchBar.SetDoneFunc(func(key tcell.Key) { - tab := curTab - - reset := func() { - searchBar.SetLabel("") - tabs[tab].applyAll() - App.SetFocus(tabs[tab].view) - layout.RemoveItem(searchBar) - tabs[tab].mode = tabModeDone - } - - //nolint:exhaustive - switch key { - case tcell.KeyEnter: - // Figure out whether it's a URL, link number, or search - // And send out a request - - // Escape the search string to not find regexp symbols - searchString = regexp.QuoteMeta(searchBar.GetText()) - - if strings.TrimSpace(searchString) == "" { - // Ignore - reset() - return - } - - if tabs[tab].mode != tabModeSearch { - originalText = tabs[curTab].view.GetBytes(false) - } - tabs[tab].mode = tabModeSearch - - // find all positions of the search string - searchRegex := regexp.MustCompile(searchString) - searchIdx := searchRegex.FindAllIndex(originalText, -1) - - // find all positions of tags - tagsIdx := tagsRegex.FindAllIndex(originalText, -1) - - text := []byte("") - matches = 0 - lastMatch := 0 - var isMatch bool - - // loops through all occurrences and check if they - // discard if they lie within tags. - // []byte text is build from the original text buffer - // with the actual search strings replaced by tagged regions - // to highlight. - for i, match := range searchIdx { - isMatch = true - for _, tag := range tagsIdx { - if match[0] >= tag[0] && match[1] <= tag[1] { - isMatch = false - break - } - } - - if isMatch { - matches++ - text = append(text, originalText[lastMatch:match[0]]...) - replacement := []byte(fmt.Sprint("[\"search-", i, "\"]", searchString, "[\"\"]")) - text = append(text, replacement...) - lastMatch = match[0] + len(searchString) - } - } - text = append(text, originalText[lastMatch:]...) - - tabs[curTab].view.SetBytes(text) - - curMatch = 0 - tabs[curTab].view.Highlight(fmt.Sprint("search-", "0")) - tabs[curTab].view.ScrollToHighlight() - App.SetFocus(tabs[tab].view) - - case tcell.KeyEsc: - // Set back to what it was - reset() - return - } - // Other potential keys are Tab and Backtab, they are ignored - }) // Render the default new tab content ONCE and store it for later // This code is repeated in Reload() @@ -414,7 +401,9 @@ func Init(version, commit, builtBy string) { if event.Key() == tcell.KeyEsc { tabs[curTab].mode = tabModeDone tabs[curTab].view.SetBytes(originalText) - layout.RemoveItem(searchBar) + searchMode = false + bottomBar.SetText(bottomBarText) + bottomBar.SetLabel("") return nil } } @@ -439,10 +428,11 @@ func Init(version, commit, builtBy string) { App.SetFocus(bottomBar) return nil case config.CmdSearch: - layout.AddItem(searchBar, 2, 1, false) - searchBar.SetLabel("") - searchBar.SetText("") - App.SetFocus(searchBar) + bottomBar.SetLabel("[::b]Search: [::-]") + bottomBarText = bottomBar.GetText() + bottomBar.SetText("") + searchMode = true + App.SetFocus(bottomBar) return nil case config.CmdEdit: // Letter e allows to edit current URL