• Login
Community
  • Login

Python Script - Fold levels/flags

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
4 Posts 2 Posters 1.6k Views
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.
  • A
    Alguem Meugla
    last edited by Apr 22, 2018, 10:47 PM

    I don’t understand what “editor.getFoldLevel(line)” with a line number as argument will return. With one line number it always returns 9218, with another line number it always changes between 9217<->1025 when I restart notepad++.
    I have searched about this, but I don’t understand it because:
    9218 (dec) = 0010 0100 0000 0010 (bin)
    9217 (dec) = 0010 0100 0000 0001 (bin)
    1025 (dec) = 0000 0100 0000 0001 (bin)
    and the table here only goes up to 128 power.
    I would like to know what those flags mean, how they are calculated/what defines them, specially about that only bit that changes between 9217 and 1025.

    Additionally, there is a FOLDLEVEL.HEADERFLAG that always seems to return “Npp.FOLDLEVEL.HEADERFLAG” when used directly in the console, or “HEADERFLAG” when used in the console as “str(FOLDLEVEL.HEADERFLAG)”.
    I also would like to know more about this function, what it is supposed to return, and what is a Headerflag. The only thing I found about it was this , which means nothing to me.

    Thank you anyone who would like to give a hand.

    1 Reply Last reply Reply Quote 0
    • D
      dail
      last edited by dail Apr 24, 2018, 1:33 PM Apr 23, 2018, 2:02 PM

      The folding of Scintilla can be a little difficult to understand at first, but luckily the documentation you pointed to on the Scintilla page is adequate.

      So some of this is pretty much repeating what the documentation says, but has some examples using LuaScript. I know you asked specifically about PythonScript but you seem to understand enough that translating between LuaScript and PythonScript shouldn’t be hard as most of the stuff is a one to one mapping. Plus the concepts are exactly the same.

      Fold Levels

      Let’s take for example this C++ code:

      int main(void) {
      	// comment
      
      	if (3 > 10) {
      		printf("nope")
      	}
      	return 0;
      }
      

      Within Notepad++ it looks like this as its fold levels.

      Using editor.getFoldLevel(line) provides information about the line’s folding which includes:

      • The fold level number (in the above example the printf() call is within the 2nd fold level)
      • The fold level header flag…which indicates if it is a fold point (i.e. the boxes that can be folded)
      • The fold level white flag…in all honesty I’m not sure what this does and think it is applicable to certain languages. For now this can be ignored.

      According to the documentation:

      The fold level is a number in the range 0 to SC_FOLDLEVELNUMBERMASK (0x0FFF).

      Which is easy to do, just take the returned value from editor.getFoldLevel(line) and bitwise AND it with SC_FOLDLEVELNUMBERMASK. In PythonScript it would look to be FOLDLEVEL.NUMBERMASK. The documentation also states:

      However, the initial fold level is set to SC_FOLDLEVELBASE (0x400) to allow unsigned arithmetic on folding levels.

      So you need to subtract SC_FOLDLEVELBASE from what you just “AND’ed” off. This will give you the fold number of the line.

      To get the header flag you need to take the fold level and bitwise AND it with SC_FOLDLEVELHEADERFLAG (which this is the highest bit you are seeing in your values you posted above).

      So…a bit of LuaScript to demonstrate what I’ve just described:

      -- Iterate over each line
      for i = 0, editor.LineCount - 1 do
      	-- Get the fold level of the line
      	local foldLevel = editor.FoldLevel[i]
      	
      	-- Calculate the fold number
      	local foldNumber = (foldLevel & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE
      	
      	-- Get the header flag
      	local headerFlag = (foldLevel & SC_FOLDLEVELHEADERFLAG) == SC_FOLDLEVELHEADERFLAG
      
      	print(string.format("Line %d, has a fold level of %d", i + 1, foldNumber))
      	if headerFlag then
      		print("\tand it is a fold point")
      	end
      end
      

      Will output:

          Line 1, has a fold level of 0
          	and it is a fold point
          Line 2, has a fold level of 1
          Line 3, has a fold level of 1
          Line 4, has a fold level of 1
          	and it is a fold point
          Line 5, has a fold level of 2
          Line 6, has a fold level of 2
          Line 7, has a fold level of 1
          Line 8, has a fold level of 1
      

      Once you have this information you can do things like select all the words within the same fold level (great for renaming local variables) or select all the text of a fold level (great for extracting code within a if or for statement and creating a separate function from it).


      A couple of the things you specifically mentioned:

      it always changes between 9217<->1025 when I restart notepad++.

      If the text is the same, then these shouldn’t change at all. Maybe now you know a bit more how the fold level works, you can figure out why this might be different.

      Additionally, there is a FOLDLEVEL.HEADERFLAG that always seems to return “Npp.FOLDLEVEL.HEADERFLAG” when used directly in the console, or “HEADERFLAG” when used in the console as “str(FOLDLEVEL.HEADERFLAG)”.

      These values are all constants so they will always be the same.

      Fold flags

      This is separate from everything described above. This is how the folding is drawn and does not apply per line but rather the entire document. With N++ the default is to draw a line below the text when it is folded. Such as:

      You can do things like set the fold flags to draw above and below the folded lines (again using LuaScript):

      editor.FoldFlags = SC_FOLDFLAG_LINEAFTER_CONTRACTED | SC_FOLDFLAG_LINEBEFORE_CONTRACTED
      

      Then the folding will look like this:

      1 Reply Last reply Reply Quote 8
      • A
        Alguem Meugla
        last edited by Apr 24, 2018, 6:53 PM

        Nice post :), thank you, now I understand it!

        Looks like notepad sometimes thinks that the line has a folding box, and other times it thinks it doesn’t, thus the 9217<->1025 change in fold level. The script I’m looking at (from here , which bugs sometimes and I’m trying to debug) is set to run when the document loads and I think that the fold levels are loading yet or something, because I put a few debug lines there telling me the values of the variables

        print "FOLDLEVEL.HEADERFLAG: " + str(int(FOLDLEVEL.HEADERFLAG))
        print "editor.getFoldLevel(" + str(_line) + "): " + str(editor.getFoldLevel(_line))
        print "editor.getFoldLevel(" + str(_line) + ") & FOLDLEVEL.HEADERFLAG: " + str(editor.getFoldLevel(_line) & FOLDLEVEL.HEADERFLAG)
        

        and the output was like this:

        FOLDLEVEL.HEADERFLAG: 8192
        editor.getFoldLevel(54): 1025
        editor.getFoldLevel(54) & FOLDLEVEL.HEADERFLAG: 8192
        

        which should be

        >>> 8192 & 1025
        0
        

        Weird, maybe it had changed from 1025 to 9217 between the two script lines, or something. I will leave the debug code, and next time something doesn’t work I will look at it better. (somehow it is working fine now)

        Do line numbers and fold levels stay the same after hiding some code?

        About the FOLDLEVEL.HEADERFLAG now I know it’s just a constant and I can look at it in the console using “int(FOLDLEVEL.HEADERFLAG)” :)

        1 Reply Last reply Reply Quote 0
        • D
          dail
          last edited by Apr 25, 2018, 11:52 AM

          Do line numbers and fold levels stay the same after hiding some code?

          Yes. There are other various API calls provided by Scintilla than can tell you things like if the line is actually folded, or to manually fold/unfold the line and children of that line.

          1 Reply Last reply Reply Quote 1
          4 out of 4
          • First post
            4/4
            Last post
          The Community of users of the Notepad++ text editor.
          Powered by NodeBB | Contributors