override fun textChanged()

in src/main/java/com/maddyhome/idea/vim/ui/ex/ExEntryPanel.kt [243:317]


    override fun textChanged(e: DocumentEvent) {
      try {
        val editor: Editor = ijEditor ?: return

        val labelText: String = myLabel.text // Either '/', '?' or ':'boolean searchCommand = false;

        var searchCommand = false
        var searchRange: LineRange? = null
        var separator = labelText[0]
        var searchText = text
        if (labelText == ":") {
          if (searchText.isEmpty()) return
          val command = getIncsearchCommand(searchText) ?: return
          searchCommand = true
          searchText = ""
          val argument = command.commandArgument
          if (argument.length > 1) {  // E.g. skip '/' in `:%s/`. `%` is range, `s` is command, `/` is argument
            separator = argument[0]
            searchText = argument.substring(1)
          }
          if (!searchText.isEmpty()) {
            searchRange = command.getLineRangeSafe(IjVimEditor(editor))
          }
          if (searchText.isEmpty() || searchRange == null) {
            // Reset back to the original search highlights after deleting a search from a substitution command.Or if
            // there is no search range (because the user entered an invalid range, e.g. mark not set).
            // E.g. Highlight `whatever`, type `:%s/foo` + highlight `foo`, delete back to `:%s/` and reset highlights
            // back to `whatever`
            VimPlugin.getSearch().resetIncsearchHighlights()
            resetCaretOffset(editor)
            return
          }
        }

        // Get a snapshot of the count for the in progress command, and coerce it to 1. This value will include all
        // count components - selecting register(s), operator and motions. E.g. `2"a3"b4"c5d6/` will return 720.
        // If we're showing highlights for an Ex command like `:s`, the command builder will be empty, but we'll still
        // get a valid value.
        val count1 = max(
          1, getInstance().keyHandlerState.editorCommandBuilder
            .calculateCount0Snapshot()
        )

        if (labelText == "/" || labelText == "?" || searchCommand) {
          val forwards = labelText != "?" // :s, :g, :v are treated as forwards
          val patternEnd: Int = injector.searchGroup.findEndOfPattern(searchText, separator, 0)
          val pattern = searchText.take(patternEnd)

          VimPlugin.getEditor().closeEditorSearchSession(editor)
          val matchOffset =
            updateIncsearchHighlights(
              editor, pattern, count1, forwards, caretOffset,
              searchRange
            )
          if (matchOffset != -1) {
            // Moving the caret will update the Visual selection, which is only valid while performing a search. We want
            // to remove the Visual selection when the incsearch is for a command, as this is always unrelated to the
            // current selection.
            // E.g. `V/foo` should update the selection to the location of the search result. But `V` followed by
            // `:<C-U>%s/foo` should remove the selection first.
            // We're actually in Command-line with Visual pending. Exiting Visual replaces this with just Command-line
            if (searchCommand) {
              IjVimEditor(editor).exitVisualMode()
            }
            IjVimCaret(editor.caretModel.primaryCaret).moveToOffset(matchOffset)
          } else {
            resetCaretOffset(editor)
          }
        }
      } catch (ex: Throwable) {
        // Make sure the exception doesn't leak out of the handler, because it can break the text entry field and
        // require the editor to be closed/reopened. The worst that will happen is no incsearch highlights
        logger.error("Error while trying to show incsearch highlights", ex)
      }
    }