Function List for Perl



  • I just did a new install of Notepad++ 7.8.9 on a new installation of Windows 10. It appears to have the same functionList.xml file in both the app folder and %appdata% folder, but when I open a Perl source file and select to view the Function List from the menu, the function list panel appears with the Perl file name at the top, but no functions listed. Is there a step I’m missing to display the subs within the program I’m editing?

    Thanks!



  • @Vinnie-M ,

    I apparently hadn’t done much Perl since upgrading to 7.8.9, but I can confirm some odditity:efe630fa-20d9-436c-96ac-f0ed725beb4d-image.png

    Looks like it is mistakenly requiring parenthesis to recognize it as a sub, which isn’t true in Perl.

    I think @MAPJe71, our resident Function List expert, may have to de-lurk for this one, and see if he has ideas for what’s going wrong.

    In the meantime, as I have a chance, I’ll start exploring past versions, and see where the regression started.



  • @PeterJones
    Ah, good catch. Thanks for letting me know what’s happening. If I get time later, I’ll see if I can decipher the functionList.xml file to see if it has customizable regexes that can be modified to remove the parens.



  • @Vinnie-M , @MAPJe71 ,

    I stand corrected. This isn’t a recent change. Apparently, either I had previously modified my Perl function list parser, and have since lost the changes, or I just use a preponderance of subs with arguments. Because I just tested back each major version to v7.5.9, and they all have the same issue. So when I’ve seen it working, it must’ve only been with parenthesized subs.

    Now I’m vaguely remembering a bug submission similar to this (and that the developer won’t update the default function list parser config file until they can figure out how to regression test). I’ll see if I can dig up an already-fixed-perl section, and/or documentation for the bug.

    @Vinnie-M just said,

    I’ll see if I can decipher the functionList.xml file to see if it has customizable regexes that can be modified to remove the parens.

    It does have modifiable regex. See @MAPJe71’s FAQ for details: https://community.notepad-plus-plus.org/topic/19480/faq-desk-function-list-basics



  • Wow. According to blame, the Perl section of functionList.xml hasn’t been modified in 4 years. And the before and after both appear to require parenthesized lists.

    The only perl-specific functionList issues I could find were mostly regarding a change between v7.5.1 and 7.5.3 which @MAPJe71 fixed in PR 2964 years ago, and at that time it worked with non-parenthesized subs. I also found issue #4384 which is still open but inactive for 2 years, probably because the issue was really vague (“doesn’t work” didn’t give the developer much to go on).

    Oh, there it is: issue #4265 . The same person also submitted PR #4266 to fix it, but that’s been open since Mar 2018.



  • This is what I have active as Funtion List PERL parser:

    			<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    			|   http://www.perlmonks.org/?node_id=1139708
    			|   http://stackoverflow.com/questions/29243989/configuring-notepad-function-list-for-perl
    			\-->
    			<parser
    				displayName="PERL - Practical Extraction and Reporting Language"
    				id         ="perl_syntax"
    				commentExpr="(?x)                                               # free-spacing (see `RegEx - Pattern Modifiers`)
    							(?m-s:\x23.*$)                                      # Single Line Comment
    						|	(?s:__END__.*\Z)                                    # Discard up till end-of-text
    					"
    			>
    				<classRange
    					mainExpr    ="(?x)                                          # free-spacing (see `RegEx - Pattern Modifiers`)
    							(?m)                                                # ^ and $ match at line-breaks
    							(?'PACKAGE_HEADER'
    								^                                               # NO leading white-space at start-of-line
    								(?-i:package\b)
    							)
    							(?s:.*?)                                            # whatever,
    							(?=                                                 # ...up till
    								\s*                                             # ...optional leading white-space of
    								(?:
    									(?&amp;PACKAGE_HEADER)                      # ...next header
    								|	\Z                                          # ...or end-of-text
    								)
    							)
    						"
    				>
    					<className>
    						<nameExpr expr="(?x)                                    # free-spacing (see `RegEx - Pattern Modifiers`)
    								\s
    								\K                                              # discard text matched so far
    								[^;]+
    							"
    						/>
    					</className>
    					<function
    						mainExpr="(?x)                                          # free-spacing (see `RegEx - Pattern Modifiers`)
    								(?m)
    								^\h*
    								sub
    								\s+
    								\w+
    								(?:\s*\([^()]*\))?
    								\s*\{                                           # start of function body
    							"
    					>
    						<functionName>
    							<funcNameExpr expr="(?x)                            # free-spacing (see `RegEx - Pattern Modifiers`)
    									(sub\s+)?
    									\K                                          # discard text matched so far
    									\w+
    								"
    							/>
    						</functionName>
    					</function>
    				</classRange>
    				<function
    					mainExpr="(?x)                                              # free-spacing (see `RegEx - Pattern Modifiers`)
    							(?m)
    							^\h*
    							sub
    							\s+
    							\w+
    							(?:\s*\([^()]*\))?
    							\s*\{                                               # start of function body
    						"
    				>
    					<functionName>
    						<nameExpr expr="(?x)                                    # free-spacing (see `RegEx - Pattern Modifiers`)
    								(?:sub\s+)?
    								\K                                              # discard text matched so far
    								\w+
    							"
    						/>
    					</functionName>
    				</function>
    			</parser>
    


  • @PeterJones
    @Vinnie-M

    As long as this topic came up, I’ll share my customized Perl function list parser.

    			<!-- ======================================================== [ PERL ] -->
    			<!-- PERL - Practical Extraction and Reporting Language                -->
    
    			<parser
                    displayName="PERL"
                    id="perl_function"
    				commentExpr="(?x)                                               # Utilize inline comments (see `RegEx - Pattern Modifiers`)
    								(?m-s:\x23.*$)                                  # Single Line Comment
    							"
                >
    				<classRange mainExpr="(?&lt;=^package).*?(?=\npackage|\Z)">
    					<className>
    						<nameExpr expr="\s\K[^;]+"/>
    					</className>
    					<function mainExpr="(?:^[\s]*(?&lt;!#)[\s]*sub[\s]+[\w]+[\s]*\(?[^\)\(]*?\)?[\n\s]*\{)|(?:^[\s]*(?&lt;!#)[\s]*\=head1[\s]+[\w]+[\s]*[\n\s]*)">
    						<functionName>
    							<funcNameExpr expr="((sub[\s]+)|(\=head1[\s]+))?\K[\w]+"/>
    						</functionName>
    					</function>
    				</classRange>
    				<function mainExpr="(?:^[\s]*(?&lt;!#)[\s]*sub[\s]+[\w]+[\s]*\(?[^\)\(]*?\)?[\n\s]*\{)|(?:^[\s]*(?&lt;!#)[\s]*\=head1[\s]+[\w]+[\s]*[\n\s]*)">
    					<functionName>
    						<nameExpr expr="(?:(?:sub[\s]+)|(?:\=head1[\s]+))?\K[\w]+"/>
    					</functionName>
    				</function>
    			</parser>
    

    My parser handles Perl “classes” (packages) in code, and grabs the top level POD headings as well - thought that’d be nice.

    Cheers.





  • I ended up modifying functionList.xml to remove the parens requirement in the regex in the function section and it seems to have worked:

    <function
    	mainExpr="(?x)                                              # Utilize inline comments (see `RegEx - Pattern Modifiers`)
    		sub
    		\s+
    		[A-Za-z_]\w*
    		\s*\{                                               # start of class body
    	"
    >
    
    


  • @Vinnie-M , @MAPJe71 , @Michael-Vincent ,

    Thanks for sharing.

    It took me a while to get @MAPJe71’s to work, because his id=“perl_syntax” whereas the standard functionList.xml is expecting id=“perl_function”.

    The two examples with class/package info work for all but my admittedly non-standard ManualPackage::Function syntax (and I don’t really expect the default parser to accept that; it’s a rare use case, from what I’ve seen).

    An interesting thing about the suggestion from yuzhy8701 in his PR #4266 was that he included optional attributes, not just optional prototypes. But he didn’t apparently include the package handling.

    I had commented on issue #4266 just before everyone chimed in. Do you think we should go with yuzhy8701’s solution in the PR, with optional for prototype and attribute, but no package awareness? Or should it get merged with one or both of the package-aware suggestions in this thread, and get re-submitted? If we submit a committee-based PR, would it be able to just edit the existing PR, or should a new PR be submitted and we request that #4266 get closed and replaced with a new PR?



  • I haven’t had a chance to “live with it” yet, but I took @MAPJe71’s and added yuzhy8701’s attributes/prototypes

    I also allowed (\w*::)* in the function name, to handle that rare-but-valid syntax. (I decided it didn’t need a separate hierarchy, because if you’re doing it in that format, you probably aren’t thinking of it as “belonging” to a class.)

    e710e890-fb34-46e3-a56f-e790a0f7a868-image.png

    			<!-- ======================================================== [ PERL ] -->
    			<!-- PERL - Practical Extraction and Reporting Language                -->
    
    			<parser
                    displayName="Perl"
                    id="perl_function"
    				commentExpr="(?x)                                               # free-spacing (see `RegEx - Pattern Modifiers`)
    							(?m-s:\x23.*$)                                      # Single Line Comment
    						|	(?s:__(?:END|DATA)__.*\Z)                           # Discard up till end-of-text
    					"
    			>
    				<classRange
    					mainExpr    ="(?x)                                          # free-spacing (see `RegEx - Pattern Modifiers`)
    							(?m)                                                # ^ and $ match at line-breaks
    							(?'PACKAGE_HEADER'
    								^                                               # NO leading white-space at start-of-line
    								(?-i:package\b)
    							)
    							(?s:.*?)                                            # whatever,
    							(?=                                                 # ...up till
    								\s*                                             # ...optional leading white-space of
    								(?:
    									(?&amp;PACKAGE_HEADER)                      # ...next header
    								|	\Z                                          # ...or end-of-text
    								)
    							)
    						"
    				>
    					<className>
    						<nameExpr expr="(?x)                                    # free-spacing (see `RegEx - Pattern Modifiers`)
    								\s
    								\K                                              # discard text matched so far
    								[^;]+
    							"
    						/>
    					</className>
    					<function
    						mainExpr="(?x)                                          # free-spacing (see `RegEx - Pattern Modifiers`)
    								(?m)
    								^\h*
    								sub
    								\s+
    								(?:\w+\:\:)*									# optional prefix::package::names::
    								\w+
    								(?:\s*\([^()]*\))?                                    # prototype or signature
    								(?:\s*\:\s*[^{]+)?                                    # attributes
    								\s*\{                                           # start of function body
    							"
    					>
    						<functionName>
    							<funcNameExpr expr="(?x)                            # free-spacing (see `RegEx - Pattern Modifiers`)
    									(sub\s+)?
    									\K                                          # discard text matched so far
    									(?:\w+\:\:)*									# optional prefix::package::names::
    									\w+
    								"
    							/>
    						</functionName>
    					</function>
    				</classRange>
    				<function
    					mainExpr="(?x)                                              # free-spacing (see `RegEx - Pattern Modifiers`)
    							(?m)
    							^\h*
    							sub
    							\s+
    							(?:\w+\:\:)*									# optional prefix::package::names::
    							\w+
    							(?:\s*\([^()]*\))?                                    # prototype or signature
    						  	(?:\s*\:\s*[^{]+)?                                    # attributes
    							\s*\{                                               # start of function body
    						"
    				>
    					<functionName>
    						<nameExpr expr="(?x)                                    # free-spacing (see `RegEx - Pattern Modifiers`)
    								(?:sub\s+)?
    								\K                                              # discard text matched so far
    								(?:\w+\:\:)*									# optional prefix::package::names::
    								\w+
    							"
    						/>
    					</functionName>
    				</function>
    			</parser>
    
    

Log in to reply