Hightlight text in both views

  • I would like that when I select and highlight a word in the left view it should automatically highlight the same word in the right view. This works almost for files that are cloned over two views where Notepad++ will highlight words in the other view when you are viewing the same lines as in the view where the word is selected. But for two different files there is no highlight at all.

    So, would be great if this could be fixed, thanks! :)

  • @Jonas-Andersson

    But for two different files there is no highlight at all.
    Yes, because the cloned one you mentioned is basically the same document from npps point of view even if displayed in another view.
    If you want, a python script can do what you want to achieve.


  • I had the need for such behavior myself yesterday. Thus, I would like to see a Pythonscript that could set/clear colored highlight of the currently selected (blocked) text.

  • @Scott-Sumner said:

    Thus, I would like to see a Pythonscript that could set/clear colored highlight of the currently selected (blocked) text.

    That should have been: Thus, I would like to see a Pythonscript that could set/clear colored highlight of the currently selected (blocked) text across all currently open files.

  • Hi Scott,

    I would like to see a Pythonscript that could set/clear colored highlight of the currently selected (blocked) text across all currently open files.

    me too ;-)

    If it is only view1 and 2 it should be pretty straight forward but all opened files … hmm …
    as I can’t color docs which aren’t visible I either would need to open them one by one or
    … maybe better using buffer activated callback and then do coloring … I will give it a try.


  • Hi Scott,

    here my first try.

    import re                                                                                       # needed if whole word should be searched
    _g = globals()                                                                                  # get global variables
    if not _g.get('AUTO_SELECT_IS_RUNNING'):                                                        # if variable not defined yet,
        AUTO_SELECT_IS_RUNNING = False                                                              # define it
    if not _g.get('COLORED_DOCS_LIST'):                                                             # -"-
        COLORED_DOCS_LIST = []                                                                      # -"-
    SELECTED_TEXT = None                                                                            # variable to hold our selection
    JUMP_TO_FIRST_OCCURANCE = True                                                                  # set to false if jump should be avoided
    CURRENT_DOCUMENT = None                                                                         # document which initiates the coloring
    # -----------------------------------------------------------------------------                 
    def track_document(buffer_id):                                                                  # track which documents get colored
        global COLORED_DOCS_LIST                                                                    # by using the global document list 
        if not buffer_id in COLORED_DOCS_LIST:                                                      # if current doc isn't in list yet
            COLORED_DOCS_LIST.append(buffer_id)                                                     # add it
    # -----------------------------------------------------------------------------         
    def toggle_view():                                                                              # function used when both views visible
        current_doc_index_main_view = notepad.getCurrentDocIndex(0)                                 # get current doc index of view 1 and
        current_doc_index_second_view = notepad.getCurrentDocIndex(1)                               # current doc index of view 2
        if notepad.getCurrentView() == 0:                                                           # if main view is active
            notepad.activateIndex(1, current_doc_index_second_view)                                 # activate second view with current open doc
        else:                                                                                       # else
            notepad.activateIndex(0, current_doc_index_main_view)                                   # the other view ...
    # -----------------------------------------------------------------------------                 
    def clear_indicator():                                                                          # clearing indicators by
        text_end_position = editor.getLength()                                                      # getting the document text length
        editor.setIndicatorCurrent(8)                                                               # setting the inidcator id
        editor.indicatorClearRange(0, text_end_position)                                            # and calling the clearing function
    # -----------------------------------------------------------------------------                  
    def colorize():                                                                                 # coloring the selected text by
        clear_indicator()                                                                           # first clearing old marks
        matches = []                                                                                # initializing match list
        # editor.research('\\b{0}\\b'.format(SELECTED_TEXT), lambda m: matches.append(m.span(0)))            # (use this if whold word should be searched only)
        editor.research('{0}'.format(SELECTED_TEXT), lambda m: matches.append(m.span(0)),re.IGNORECASE)      # search document for selected text and append it to list
        editor.indicSetStyle(8,INDICATORSTYLE.ROUNDBOX)                                             # set the indicator properties like roundbox
        editor.indicSetFore(8,(117,217,117))                                                        # foreground color
        editor.indicSetAlpha(8,55)                                                                  # alpha setting
        editor.indicSetOutlineAlpha(8,255)                                                          # outline setting and
        editor.indicSetUnder(8,True)                                                                # if it should be colored under text
        for match in matches:                                                                       # for each found match
            editor.setIndicatorCurrent(8)                                                           # set the indicator and
            editor.indicatorFillRange(match[0], match[1] - match[0])                                # color the match
        not_original_doc = notepad.getCurrentBufferID() != CURRENT_DOCUMENT                         # is the current doc the doc which initiated the coloring?
        if JUMP_TO_FIRST_OCCURANCE and len(matches) > 0 and not_original_doc:                       # if we should jump, do have matches and doc is different then
            first_visible_line = editor.getFirstVisibleLine()                                       # get the first visible line and
            line_from_position = editor.lineFromPosition(matches[0][0])                             # get the line from the match position
            delta = (line_from_position - 1 - first_visible_line)                                   # build a delta out of it
            editor.lineScroll(0, delta)                                                             # and scroll to it
    # -----------------------------------------------------------------------------                  
    def prepare_and_run():                                                                          # stuff which needs to be done prior to the coloring
        global CURRENT_DOCUMENT                                                                     # 
        CURRENT_DOCUMENT = notepad.getCurrentBufferID()                                             # set current doc to global var
        global SELECTED_TEXT                                                                        # 
        SELECTED_TEXT = editor.getSelText()                                                         # set selection to global var
        colorize()                                                                                  # and color current doc
        both_views_visible = True if editor1 and editor2 else False                                 # are both views visible?
        if both_views_visible:                                                                      # if so
            toggle_view()                                                                           # switch to other view
    # -----------------------------------------------------------------------------                  
    def callback_MARGINCLICK(args):                                                                 # callback gets called when clicking bookmark margin
        prepare_and_run()                                                                           # function self explanatory, isn't it
    # -----------------------------------------------------------------------------                  
    def callback_DOUBLECLICK(args):                                                                 # callback gets called when user double clicks
        prepare_and_run()                                                                           # deja vu
    # -----------------------------------------------------------------------------                  
    def callback_BUFFERACTIVATED(args):                                                             # callback gets called when doc gets switched
        if AUTO_SELECT_IS_RUNNING:                                                                  # when sript is in running state
            colorize()                                                                              # call colorize
            track_document(args['bufferID'])                                                        # and track which document was colored
        else:                                                                                       # otherwise it is in stopped state and
            global COLORED_DOCS_LIST                                                                # therefore we need to clear colored docs
            if args['bufferID'] in COLORED_DOCS_LIST:                                               # by checking if current id is in the list
                clear_indicator()                                                                   # if so call clearing function and
                COLORED_DOCS_LIST.remove(args['bufferID'])                                          # remove id from list
            if len(COLORED_DOCS_LIST) == 0:                                                         # if list of colored docs is empty
                notepad.clearCallbacks([NOTIFICATION.BUFFERACTIVATED])                              # callback isn't needed anymore, clear it.
    # ----------------------------------------------------------------------------- 
    def main():                                                                                     # main function to handle start/stop behavior
        global AUTO_SELECT_IS_RUNNING                                                               # assining to global variable
        if AUTO_SELECT_IS_RUNNING:                                                                  # if script is currently running
            AUTO_SELECT_IS_RUNNING = False                                                          # this call should stop it, so set flag to False
            editor.clearCallbacks([SCINTILLANOTIFICATION.DOUBLECLICK])                              # clear callbacks
            editor.clearCallbacks([SCINTILLANOTIFICATION.MARGINCLICK])                              # -"-
            clear_indicator()                                                                       # and start clearing indicator marks
        else:                                                                                       # else
            AUTO_SELECT_IS_RUNNING = True                                                           # set the flag to true and
            editor.callback(callback_DOUBLECLICK, [SCINTILLANOTIFICATION.DOUBLECLICK])              # register needed callbacks
            editor.callback(callback_MARGINCLICK, [SCINTILLANOTIFICATION.MARGINCLICK])              # -"-
            notepad.callback(callback_BUFFERACTIVATED, [NOTIFICATION.BUFFERACTIVATED])              # -"-     
    # ----------------------------------------------------------------------------- 
    main()                                                                                          # main entry


  • @Claudia-Frank said:

    main() # main entry

    That is pretty cool indeed! Thanks for doing that. Hopefully others find it useful as well.

  • @Scott-Sumner

    Hi Scott, thank you very much.

    For those who haven’t much experience with python I should give a little information
    how it can be used. Basically there a two things one need to know.

    1. First run of the script activates it, second run stops it (which clears the coloring), next run activates it again and so on…

    2. Either by double clicking a word or by selecting text and then clicking into the column between
      numbers and folding symbol (the bookmark area) will color the selection.

    That’s it - have fun.


  • Thank for the script I will give it a try when back from holiday, though still would be nice if it could be a native feature.

  • @Scott-Sumner

    Hi Scott,

    while using the script I came across a few glitches which has been solved in this version.
    Maybe you or others find the changes useful.
    Main change from usage point of view is the deletion of the margin click callback to unselect the matches,
    instead double click the searched word again. Rest of the changes are for performance and minor bug fixes.
    As always, first run starts the script, next run stops it.

    Btw. comments have been deleted as there is a new policy in place that only post with up to 16384 are accepted.


        import re
        _g = globals()
        if not _g.get('AUTO_SELECT_IS_RUNNING'):
            AUTO_SELECT_IS_RUNNING = False
        if not _g.get('COLORED_DOCS_LIST'):
            COLORED_DOCS_LIST = {}
        SELECTED_TEXT = None
        # -----------------------------------------------------------------------------
        def track_document(buffer_id):
            global COLORED_DOCS_LIST
            if SELECTED_TEXT == '':
                if COLORED_DOCS_LIST.has_key(buffer_id):
                COLORED_DOCS_LIST[buffer_id] = SELECTED_TEXT
        # -----------------------------------------------------------------------------
        def toggle_view():
            current_doc_index_main_view = notepad.getCurrentDocIndex(0)
            current_doc_index_second_view = notepad.getCurrentDocIndex(1)
            if notepad.getCurrentView() == 0:
                notepad.activateIndex(1, current_doc_index_second_view)
                notepad.activateIndex(0, current_doc_index_main_view)
        # -----------------------------------------------------------------------------
        def clear_indicator():
            text_end_position = editor.getLength()
            editor.indicatorClearRange(0, text_end_position)
        # -----------------------------------------------------------------------------
        def colorize():
            matches = []
            if SELECTED_TEXT == '':
            # editor.research('\\b{0}\\b'.format(SELECTED_TEXT), lambda m: matches.append(m.span(0)))
            editor.research('{0}'.format(SELECTED_TEXT), lambda m: matches.append(m.span(0)),re.IGNORECASE)
            if len(matches) == 0:
            for match in matches:
                editor.indicatorFillRange(match[0], match[1] - match[0])
            not_original_doc = notepad.getCurrentBufferID() != CURRENT_DOCUMENT
            if JUMP_TO_FIRST_OCCURANCE and len(matches) > 0 and not_original_doc:
                first_visible_line = editor.getFirstVisibleLine()
                line_from_position = editor.lineFromPosition(matches[0][0])
                delta = (line_from_position - 1 - first_visible_line)
                editor.lineScroll(0, delta)
        # -----------------------------------------------------------------------------
        def prepare_and_run():
            global CURRENT_DOCUMENT
            global PREVIOUS_SELECTED_TEXT
            global SELECTED_TEXT
            CURRENT_DOCUMENT = notepad.getCurrentBufferID()
            SELECTED_TEXT = editor.getSelText()
                SELECTED_TEXT = ''
            if not SELECTED_TEXT.isspace():
                both_views_visible = True if editor1 and editor2 else False
                if both_views_visible:
        # -----------------------------------------------------------------------------
        def callback_DOUBLECLICK(args):
        # -----------------------------------------------------------------------------
        def callback_BUFFERACTIVATED(args):
            global COLORED_DOCS_LIST
            if AUTO_SELECT_IS_RUNNING:
                _selected_text = COLORED_DOCS_LIST.get(args['bufferID'], None)
                if _selected_text == SELECTED_TEXT:
                if COLORED_DOCS_LIST.has_key(args['bufferID']):
                if len(COLORED_DOCS_LIST) == 0:
        # -----------------------------------------------------------------------------
        def main():
            global AUTO_SELECT_IS_RUNNING
            if AUTO_SELECT_IS_RUNNING:
                AUTO_SELECT_IS_RUNNING = False
                AUTO_SELECT_IS_RUNNING = True
                editor.callback(callback_DOUBLECLICK, [SCINTILLANOTIFICATION.DOUBLECLICK])
                notepad.callback(callback_BUFFERACTIVATED, [NOTIFICATION.BUFFERACTIVATED])
        # -----------------------------------------------------------------------------

  • I will take a look at it; thanks as always for your tremendous support.

Log in to reply