Insert User Function Definitions -- for Notepad++

Scripting and setups with Notepad++ and AutoHotkey.
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Insert User Function Definitions -- for Notepad++

Post by boiler » 02 Apr 2017, 10:57

For those like me who find it difficult to remember the parameters and default values of your custom functions in your larger scripts, this simple tool allows you to insert their names and definitions with one click on the Notepad++ Function List.

Usage
  • Right-click when hovering over a function name in the Notepad++ Function List (and tooltip appears) >> Inserts the function name and parameter definition into your script. Added benefit: also saves you from having to type the function name.
  • Control & Right-click >> Inserts a comment block into your script that contains the function definitions from your #Include files so that they will be added to the Function List pane (after saving your file), which allows you to auto-insert their definitions by right-clicking on them also. Does not add function definitions that have no parameters.
Implementation
  1. If you haven't done so already, add AHK support for Notepad++'s Function List feature per ahkDustVorteX (et al). Note that it has been updated later in the thread to handle certain cases correctly and to add support for classes, and the updates have not yet been incorporated into the first post of the thread. Kudos to everyone in that thread for their work on this very useful feature.
  2. Run the script below.

    Code: Select all

    #If WinActive("ahk_exe notepad++.exe") && WinExist("ahk_class tooltips_class32") && IsControlUnderMouse("SysTreeView322")
    RButton::
    	ControlGetText, FuncDef,, ahk_class tooltips_class32
    	ClipSave := ClipboardAll
    	Clipboard := RTrim(FuncDef, " {`t`n`r")
    	Send, ^v
    	Clipboard := ClipSave
    return
    
    #If WinActive("ahk_exe notepad++.exe")
    ^RButton::
    	WinGetTitle, NppTitle, A
    	NppTitle := LTrim(NppTitle, "*")
    	StringTrimRight, ScriptFullPath, NppTitle, 12
    	SplitPath, NppTitle,, ScriptDir
    	FileRead, ScriptText, %ScriptFullPath%
    	OutText := "/*	-----  Function definitions from #Include files  -----`n"
    	Loop, Parse, ScriptText, `n, `r
    	{
    		if (SubStr(Trim(A_LoopField), 1, 8) = "#Include")
    		{
    			RegExMatch(A_LoopField, "i)#Include,*\s*\K[^;]+", IncFilePath)
    			IncFilePath := Trim(IncFilePath)
    			SplitPath, IncFilePath,,,,, IncDrive
    			OutText .= GetFuncDefs((IncDrive ? IncFilePath : ScriptDir "\" IncFilePath))
    		}
    	}
    	OutText .= "*/`n"
    	ClipSave := ClipboardAll
    	Clipboard := OutText
    	Send, ^v
    	Clipboard := ClipSave
    return
    
    #if
    
    IsControlUnderMouse(refCtrl)
    {
    	MouseGetPos,,,, ctrl
    	return ctrl = refCtrl
    }
    
    GetFuncDefs(scriptPath) ; does not include those with a definition of "()" (no parameters)
    {
    	defs := ""
    	FileRead, rawScript, %scriptPath%
    	
    	; remove comment blocks:
    	cleanScript := "`n" ; start with `n so RegEx can know a func def is preceded by one even if first line
    	blockStart := 0
    	Loop, Parse, rawScript, `n, `r
    	{
    		if blockStart
    		{
    			if (SubStr(LTrim(A_LoopField), 1, 2) = "*/")
    				blockStart := 0
    		}
    		else
    		{
    			if (SubStr(LTrim(A_LoopField), 1, 2) = "/*")
    				blockStart := 1
    			else
    				cleanScript .= A_LoopField "`n"
    		}
    	}
    	
    	; get function definitions:
    	startPos := 1
    	Loop
    	{
    		; original: if (foundPos := RegExMatch(cleanScript, "\n\s*\K[\w#@$]+\([^\n;]+\)(?=\s*(;[^n]*)*\n*{)", match, startPos))
    		if (foundPos := RegExMatch(cleanScript, "U)\n\s*\K[ \t]*(?!(if\(|while\(|for\())([\w#!^+&<>*~$])+\d*\([^)]+\)([\s]|(/\*.*?\*)/|((?<=[\s]);[^\r\n]*?$))*?[\s]*\n*(?=\{)", match, startPos))
    		{
    			defs .= Trim(RegExReplace(match, "\s*\n\s*$")) " {`n"
    			startPos := InStr(cleanScript, "`n",, foundPos) ; start at next line
    		}
    	} until !foundPos
    	
    	return defs
    }
Known Issue:
If the function definition is so short that it is not wider than the Function List pane, it will not display a tooltip and can't be inserted by this tool. I don't find this to be a problem since functions with parameters (especially multiple ones) will be long enough to display a tooltip.

EDIT: Incorporated a modified version Nightwolf85's RegEx to allow it to find multi-line function definitions.
Last edited by boiler on 03 Apr 2017, 21:27, edited 2 times in total.

Nightwolf85
Posts: 302
Joined: 05 Feb 2017, 00:03

Re: Insert User Function Definitions -- for Notepad++

Post by Nightwolf85 » 03 Apr 2017, 07:10

Hello, I'm one of the people who has been working on the Function Parser for Notepad++ in the thread you linked.

If you would like, this is the RegEx I use to find function definitions, it could probably be improved on still for efficiency, but it might save people a step if they have those multi-line function definitions.
^[ \t]*(?!(if\(|while\(|for\())([\w#!^+&<>*~$])+\d*\([^)]*\)([\s]|(/\*.*?\*)/|((?<=[\s]);[^\r\n]*?$))*?[\s]*\{

If you want it to not find functions with no parameters I believe you just need to change a * to a + like:
^[ \t]*(?!(if\(|while\(|for\())([\w#!^+&<>*~$])+\d*\([^)]+\)([\s]|(/\*.*?\*)/|((?<=[\s]);[^\r\n]*?$))*?[\s]*\{

I like your tool, and you were right it makes finding functions in comment blocks helpful.

User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Insert User Function Definitions -- for Notepad++

Post by boiler » 03 Apr 2017, 08:23

Thanks. In fact, I was impressed with your contributions on that parser, and I did briefly try to implement your RegEx here, but I didn't get it to work immediately. I thought it might be the difference between how the Notepad++ parser steps through a script's text and how the loop in my script does it. But perhaps I just made some mistake in implementing it. I was planning on revisiting it to try to make it work. Were you able to successfully use it in this case?

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Insert User Function Definitions -- for Notepad++

Post by Helgef » 03 Apr 2017, 09:39

The ^RButton:: functionallity is super useful and super quick, great job! :clap:
I made a script with #Includes of all my user-lib functions :)
Run this, paste in npp, and hit ^RButton to get a list of all functions in your user-lib.

Code: Select all

ExitApp ; Save your clipboard before running this if needed.
Loop, Files, %A_MyDocuments%\AutoHotkey\Lib\*.ahk
	str.= "#Include " . A_LoopFileFullPath . "`n" 
clipboard:=str
The tooltip limitation unfortunatley somewhat ruins the potential greatness of the RButton functionallity, it seems non-trivial to get the selection by other means though. :cry:

And while Nightwolf85 is here, thank you (and op) very much for your work in the other thread, those regex makes me nauseous :salute:

Great tool, thanks for sharing.

User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Insert User Function Definitions -- for Notepad++

Post by boiler » 03 Apr 2017, 10:29

Glad you like it.

Nice script for adding the library functions. I thought about making the script automatically search there too, but I was thinking that since library functions are a more permanent group of functions, it might be good to add those definitions to your hotstrings script (which I use regularly and is so helpful) so they're treated more like built-in functions. But that's all personal preference, and using your script to add them and have them used with this script requires less work, so it makes sense.

Yes, I agree that it would be nice to be able to use the RButton with even short function names/definitions. One option is to drag the pane width and make it very narrow so they all have tooltips, but then you don't see much of their names. I'll see if I can figure out some other way to grab them, but it doesn't look like it would be easy.

Nightwolf85
Posts: 302
Joined: 05 Feb 2017, 00:03

Re: Insert User Function Definitions -- for Notepad++

Post by Nightwolf85 » 03 Apr 2017, 11:58

boiler wrote:Thanks. In fact, I was impressed with your contributions on that parser, and I did briefly try to implement your RegEx here, but I didn't get it to work immediately. I thought it might be the difference between how the Notepad++ parser steps through a script's text and how the loop in my script does it. But perhaps I just made some mistake in implementing it. I was planning on revisiting it to try to make it work. Were you able to successfully use it in this case?
I've noticed that the function parser uses . matches newlines option. Other than that I don't think it does anything different, but I don't know for sure.
https://autohotkey.com/docs/misc/RegEx- ... .htm#opt_s

User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: Insert User Function Definitions -- for Notepad++

Post by boiler » 03 Apr 2017, 21:34

Nightwolf85 - I incorporated a version of your RegEx which I just had to modify a bit to get the output into the form my script was expecting, so now it works. Thanks for that. That change along with a small modification to another line makes it work for multi-line function definitions. The first post is edited to include that.

When right-clicking on one of those functions in the list that has a multi-line definition, it now inserts it as a continuous line rather than broken up into separate lines. Not sure why that's different than how it was, but that should be fine. It might be the better way to go anyway.

Post Reply

Return to “Notepad++”