Community

    • Login
    • Search
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    [vi simulator] how to highlight a word

    Plugin Development
    5
    55
    57556
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • bycn82 bbbb
      bycn82 bbbb last edited by

      I am trying to enhance my visimulator plugin, when I am searching the text with “/abc” or “?abc”, I want to highlight the matched words. i want to the effect to be exactly same as highlighting when double clicking on the word.

      Currently I only noticed SCI_COLOURISE. any advice?

      Regards,

      1 Reply Last reply Reply Quote 0
      • dail
        dail last edited by

        SCI_COLOURISE is to have the lexer (e.g. C++, HTML, JavaScript, etc) re-parse and determine styles.

        What you would want are indicators. This is what N++ uses for its smart highlighting. They are fairly easy to use and give you a wide range of options. Keep in mind Notepad++ uses a handful of indicators itself so make sure not to accidentally reuse ones already in use.

        1 Reply Last reply Reply Quote 0
        • bycn82 bbbb
          bycn82 bbbb last edited by

          I just find a way to highlight a word, but I met another issue.

          After I highlight a word, and I notice it did not automatically clear when I double click on another word.

          1 Reply Last reply Reply Quote 0
          • dail
            dail last edited by

            There’s nothing “automatic” about it, you have to manually handle everything. See: SCI_INDICATORCLEARRANGE

            1 Reply Last reply Reply Quote 0
            • bycn82 bbbb
              bycn82 bbbb last edited by

              I thought it will be cleaned automatically if I use the same indicator as the one used when double clicked

              1 Reply Last reply Reply Quote 0
              • dail
                dail last edited by

                I guess in theory if you use the same indicator number then it should be cleared but I can’t say for certain. What indicator number are you using? Maybe provide an example/code of what you are trying to do?

                1 Reply Last reply Reply Quote 0
                • bycn82 bbbb
                  bycn82 bbbb last edited by

                  SendMessage(nppData._scintillaMainHandle, SCI_INDICSETFORE,INDICATOR_CURRENT, 0x00FF00); // green #00d000 SendMessage(nppData._scintillaMainHandle, SCI_INDICSETALPHA, INDICATOR_CURRENT, 100); SendMessage(nppData._scintillaMainHandle, SCI_INDICSETSTYLE,INDICATOR_CURRENT, INDIC_ROUNDBOX); SendMessage(nppData._scintillaMainHandle, SCI_SETINDICATORCURRENT, INDICATOR_CURRENT, 0); SendMessage(nppData._scintillaMainHandle, SCI_INDICATORFILLRANGE,5, 7);

                  and I tried to set the value of indicator_current to 31 and 27. and hoping it will be automatically cleaned when double clicked on an word.

                  1 Reply Last reply Reply Quote 0
                  • dail
                    dail last edited by

                    Notepad++ uses 29 for its smart highlighting.

                    1 Reply Last reply Reply Quote 0
                    • bycn82 bbbb
                      bycn82 bbbb last edited by

                      Is it possible to invoke the npp’s methods?
                      I was thinking why I need to reinvent the wheel.

                      e.g. How can I call the find function? I did not find any sample about it, is it possible?

                      1 Reply Last reply Reply Quote 0
                      • dail
                        dail last edited by

                        Is it possible to invoke the npp’s methods?

                        In some cases yes but in this case no.

                        I was thinking why I need to reinvent the wheel.

                        Luckily it is a small wheel.

                        Here is the Notepad++ code that does the smarthighlighting. Unfortunately it isn’t as simple as copy/paste.

                        If you want to see a “leaner” version of how to do something similar to smarthighlighting take at this Lua code. This isn’t perfect but works under alot of circumstances. You can even incorporate some of the things Notepad++ is doing as well. I understand you are writing it in C but most of the lines of Lua translates into a single line of C.

                        For example something like:

                        editor.FirstVisibleLine
                        

                        Is equivalent to:

                        SendMessage(nppData._scintillaMainHandle, SCI_GETFIRSTVISIBLELINE, 0, 0);
                        

                        The one caveat being editor:findtext() which you can take a look at SCI_FINDTEXT

                        Scott Sumner 1 Reply Last reply Reply Quote 0
                        • bycn82 bbbb
                          bycn82 bbbb last edited by

                          Anyway! I will just use the Ctrl+F3.
                          Don’t have much time to work on a editor plugin.

                          I use command line for most of time.

                          1 Reply Last reply Reply Quote 0
                          • Scott Sumner
                            Scott Sumner @dail last edited by

                            @dail said:

                            smarthighlighting take at this Lua code

                            Hi dail, I took a look at the code found at the link you provided, and although I don’t use Luascript with Notepad++ I think I can follow the logic well-enough. Knowing Pythonscript and how the callback mechanism works there, it appears your intent in this code is to fire it off every time an “update UI” event is generated. The problem is (and again I’m thinking of my Pythonscript familiarity) I think that the code itself will cause more of those “update UI” events to be generated, thus spiraling somewhat out of control (at least while the caret is on a “word”), calling your callback many many times. Am I missing something here?

                            dail 1 Reply Last reply Reply Quote 1
                            • dail
                              dail @Scott Sumner last edited by

                              Hi @Scott-Sumner

                              That is actually a really good question. I’ve always gone under the assumption that it doesn’t fire off another “updateUI” event.

                              Looking at the Scintilla documentation for SCN_UPDATEUI states:

                              Either the text or styling of the document has changed or the selection range or scroll position has changed.

                              Note: “style” is separate from “indicators”

                              There are separate notifications when indicators have changes (i.e. SCN_MODIFIED). If you take a look at the Notepad++ source code you will also see that it does the “highlighting” during the SCN_UPDATEUI event. See this line of code

                              So it appears that doing this is safe.

                              Scott Sumner 1 Reply Last reply Reply Quote 1
                              • Scott Sumner
                                Scott Sumner @dail last edited by

                                @dail

                                So for some fun I ported the code to Pythonscript on my lunch break. Due to limited time, I left out the callback stuff, and am just putting the caret on a word and running the script and seeing all occurrences in the currently visible window of the editor tab become highlighted. However, I have another script that tells me which callbacks are happening (I run that first). When I invoke the “highlight” script, I see MODIFIED callbacks occur with SC_PERFORMED_USER | SC_MOD_CHANGEINDICATOR flags set (which seems correct), but I also see UPDATEUI callbacks occurring as well, after the MODIFIED ones. Thus this leads me back to suspecting that it would just generate something of a big callback loop if actually set up as part of a UPDATEUI callback; I’ll try that out soon.

                                Claudia Frank 1 Reply Last reply Reply Quote 0
                                • Claudia Frank
                                  Claudia Frank @Scott Sumner last edited by

                                  @Scott-Sumner

                                  Hi Scott,

                                  dail is correct, as long as you take care that your callback function doesn’t generate ui updates it is save to use.
                                  I’m using it in my updated regextester script for some weeks now without a problem.

                                  Cheers
                                  Claudia

                                  1 Reply Last reply Reply Quote 0
                                  • Scott Sumner
                                    Scott Sumner last edited by

                                    So last night I actually tried it out with it installed as an update-ui callback. After installation, putting the caret inside a word results in the FIRST occurrence of that word flashing rapidly. It seems like what I feared would happen is actually happening–something in itself is triggering multiple re-calling of the callback, and it is clearing and setting the indicator over and over.

                                    Maybe there is something wrong with my Pythonscript port of this code; it is short enough so I have included it below. Perhaps someone can see a deficiency? I see dail used “return False” a few places in the original code; I never heard of a callback returning a boolean; however I included it in the port (along with some “else” placements which would permit removing the return statements without affecting functionality).

                                    Anyway, here’s the code:

                                    INDICATOR_TO_USE = 12
                                    editor1.indicSetStyle(INDICATOR_TO_USE, INDICATORSTYLE.ROUNDBOX)
                                    editor2.indicSetStyle(INDICATOR_TO_USE, INDICATORSTYLE.ROUNDBOX)
                                    editor1.indicSetAlpha(INDICATOR_TO_USE, 55)
                                    editor2.indicSetAlpha(INDICATOR_TO_USE, 55)
                                    editor1.indicSetOutlineAlpha(INDICATOR_TO_USE, 255)
                                    editor2.indicSetOutlineAlpha(INDICATOR_TO_USE, 255)
                                    
                                    def callback_sci_UPDATEUI(args):
                                    
                                    	def getRangeOnScreen():
                                    		firstLine = editor.getFirstVisibleLine()
                                    		lastLine = firstLine + editor.linesOnScreen()
                                    		startPos = editor.positionFromLine(firstLine)
                                    		endPos = editor.getLineEndPosition(lastLine)
                                    		return (startPos, endPos)
                                    
                                    	def clearIndicatorOnScreen():
                                    		(s, e) = getRangeOnScreen()
                                    		editor.indicatorClearRange(s, e - s)
                                    
                                    	editor.setIndicatorCurrent(INDICATOR_TO_USE)
                                    
                                    	if not editor.getSelectionEmpty():
                                    		clearIndicatorOnScreen()
                                    		return False
                                    	else:
                                    		startWord = editor.wordStartPosition(editor.getCurrentPos(), True)
                                    		endWord = editor.wordEndPosition(startWord, True)
                                    
                                    		if startWord == endWord:
                                    			clearIndicatorOnScreen()
                                    			return False
                                    		else:
                                    			word = editor.getTextRange(startWord, endWord)
                                    
                                    			clearIndicatorOnScreen()
                                    
                                    			(startPos, endPos) = getRangeOnScreen()
                                    			temp = editor.findText(FINDOPTION.WHOLEWORD | FINDOPTION.MATCHCASE, startPos, endPos, word)
                                    			while temp != None:
                                    				(s, e) = temp
                                    				editor.indicatorFillRange(s, e - s)
                                    				temp = editor.findText(FINDOPTION.WHOLEWORD | FINDOPTION.MATCHCASE, e, endPos, word)
                                    
                                    editor.callback(callback_sci_UPDATEUI, [SCINTILLANOTIFICATION.UPDATEUI])
                                    
                                    1 Reply Last reply Reply Quote 0
                                    • dail
                                      dail last edited by

                                      This is some interesting results. If I get some time I will play around with it as well with Lua. It is odd you are getting this behavior. The example Lua I posted I’ve been using for months just fine. It might be worth looking a bit more into the Notepad++ “smarthilighter” since it does pretty much the same thing but works fine.

                                      I see dail used “return False” a few places in the original code

                                      This is purely a LuaScript thing. (It doesn’t actually do anything but I recommend returning false from a LuaScript callback for forwards-compatibility reasons).

                                      There is one other caveat to keep in mind. PythonScript callbacks are asynchronous (whereas LuaScript callbacks are purely synchronous). Not sure if this is affecting anything but definitely worth keeping in mind.

                                      1 Reply Last reply Reply Quote 0
                                      • Scott Sumner
                                        Scott Sumner last edited by

                                        The Pythonscript docs say that I can use editor.callbackSync() to make it synchronous, but then it goes on to say that if I do that, I can’t call editor.findText(), which this script uses. :(

                                        Claudia Frank 1 Reply Last reply Reply Quote 0
                                        • Claudia Frank
                                          Claudia Frank @Scott Sumner last edited by Claudia Frank

                                          Hello Scott,

                                          you are right, using asynchronous callback leads to the update flickering.
                                          I’m not quite sure why this happens.
                                          I’m using the synchronous callback together with the research function and this
                                          seems to work well. Your code would look like

                                          INDICATOR_TO_USE = 12
                                          editor1.indicSetStyle(INDICATOR_TO_USE, INDICATORSTYLE.ROUNDBOX)
                                          editor2.indicSetStyle(INDICATOR_TO_USE, INDICATORSTYLE.ROUNDBOX)
                                          editor1.indicSetAlpha(INDICATOR_TO_USE, 55)
                                          editor2.indicSetAlpha(INDICATOR_TO_USE, 55)
                                          editor1.indicSetOutlineAlpha(INDICATOR_TO_USE, 255)
                                          editor2.indicSetOutlineAlpha(INDICATOR_TO_USE, 255)
                                          
                                          import re
                                          
                                          def callback_sci_UPDATEUI(args):
                                              print 'callback_sci_UPDATEUI'
                                              
                                              def match_found(m):
                                                  editor.setIndicatorCurrent(INDICATOR_TO_USE)
                                                  editor.indicatorFillRange(m.span(0)[0], m.span(0)[1] - m.span(0)[0])
                                              
                                              def getRangeOnScreen():
                                                  print 'getRangeOnScreen'
                                                  firstLine = editor.getFirstVisibleLine()
                                                  lastLine = firstLine + editor.linesOnScreen()
                                                  startPos = editor.positionFromLine(firstLine)
                                                  endPos = editor.getLineEndPosition(lastLine)
                                                  return (startPos, endPos)
                                          
                                              def clearIndicatorOnScreen():
                                                  print 'clearIndicatorOnScreen'
                                                  (s, e) = getRangeOnScreen()
                                                  editor.indicatorClearRange(s, e - s)
                                          
                                              editor.setIndicatorCurrent(INDICATOR_TO_USE)
                                          
                                              if not editor.getSelectionEmpty():
                                                  clearIndicatorOnScreen()
                                                  return False
                                              else:
                                                  startWord = editor.wordStartPosition(editor.getCurrentPos(), True)
                                                  endWord = editor.wordEndPosition(startWord, True)
                                          
                                                  if startWord == endWord:
                                                      clearIndicatorOnScreen()
                                                      return False
                                                  else:
                                                      word = editor.getTextRange(startWord, endWord)
                                                      print 'word:{}'.format(word)
                                                      clearIndicatorOnScreen()
                                          
                                                      (startPos, endPos) = getRangeOnScreen()
                                                      # temp = editor.findText(FINDOPTION.WHOLEWORD | FINDOPTION.MATCHCASE, startPos, endPos, word)
                                                      editor.research(word, match_found, re.IGNORECASE) 
                                                      # while temp != None:
                                                          # (s, e) = temp
                                                          # editor.indicatorFillRange(s, e - s)
                                                          # temp = editor.findText(FINDOPTION.WHOLEWORD | FINDOPTION.MATCHCASE, e, endPos, word)
                                          
                                          editor.callbackSync(callback_sci_UPDATEUI, [SCINTILLANOTIFICATION.UPDATEUI])
                                          

                                          I know you could have done this yourself but thought …

                                          Cheers
                                          Claudia

                                          1 Reply Last reply Reply Quote 1
                                          • dail
                                            dail last edited by

                                            I’m not familiar enough with the internal Scintilla code but I think it is making sure it doesn’t get stuck in one of these types of loops. I added a bit of extra code to my plugin to log exactly when notifications are getting received. It shows when it enters and leaves the notifications. As shown below, it enters the SCN_UPDATEUI, at which point it calls my Lua callback which adds 3 indicators, thus the 3 SCN_MODIFIED pairs, then leaves the SCN_UPDATEUI notification.

                                            ->SCN_UPDATEUI
                                            ->SCN_MODIFIED
                                            <-SCN_MODIFIED
                                            ->SCN_MODIFIED
                                            <-SCN_MODIFIED
                                            ->SCN_MODIFIED
                                            <-SCN_MODIFIED
                                            <-SCN_UPDATEUI
                                            

                                            I would say between this and the fact that @Claudia-Frank successfully used the synchronous callbacks, means that your code was receiving these notifications out of order due to the asynchronous callbacks (which is a problem I ran into with the PythonScript a while ago).

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Copyright © 2014 NodeBB Forums | Contributors