I'm working on a tool which manipulates PB source code. It's manually invoked from the menu, and gets passed the %FILE and %TEMPFILE tokens.
I just wanted a confirmation on an issue, because documentation isn't too explicit about it.
If I've understood correctly, when configuring tools in PB IDE, the insertion of the parameter %TEMPFILE makes PB create a temporary file-copy of the current source code (ie: the one that has the focus and the cursor in it).
Instead, the %FILE will provide just the filename of the current code -- IF saved at least once (else it has no location on disk).
My question is about how to access the exact code as it is in the IDE, and I suspect that using %FILE is not safe because the file on disk might differ from what is actually in the IDE if the user didn't save changes before invoking the tool. On the other hand, it seems that %TEMPFILE enforces to create a snapshot of the code as-it-is-in-the-IDE (regardless of wheter it was saved at all).
So, to manipulate the source code I should use both these tokens: %TEMPFILE to acess a copy of the code as it is in the IDE, and %FILE as a reference to where to save the code after manipulation -- I've also set "Wait until tool quits" and "Reload Source after the tool has quit".
Is my approach/understanding correct? Am I missing out some important things?
Any tips or advise from anyone on the issue of tools that change the source code within PB IDE?
Thanks...
Question on using External Tools
Question on using External Tools
The PureBASIC Archives:
- GitHub Repo + Wiki + Website
- https://tajmone.github.io/purebasic-archives
- PB Sourcecode Highlighters for Websites and Documents
- Dräc OOP Tutorial reprint
- Pandoc2BBCode: Post on PB Forums from Markdown, ReST, Docx, and other formats…
Re: Question on using External Tools
Hi. There is a more advanced way to access IDE active code/file through scintilla component and environment variables, maybe you find it useful.
When I created similar topic time ago someone posted following example of PB IDE tool by @danilo. It is based on scintilla messages instead, so you even no need to specify command line arguments.
That tool searches all lines in opened file where text (selected in IDE editor at tool launch) is present.
I didn't come yet to modify it for my targets, but I guess it is possible also to replace whole IDE text this way. That looks better as for me than parsing files.
To test it compile it to exe and add to PB IDE tools with "Menu or shortcut" trigger and without any other params
Also here is list of IDE environment variables to be accessed using GetEnvironmentVariable() function.
When I created similar topic time ago someone posted following example of PB IDE tool by @danilo. It is based on scintilla messages instead, so you even no need to specify command line arguments.
That tool searches all lines in opened file where text (selected in IDE editor at tool launch) is present.
I didn't come yet to modify it for my targets, but I guess it is possible also to replace whole IDE text this way. That looks better as for me than parsing files.
To test it compile it to exe and add to PB IDE tools with "Menu or shortcut" trigger and without any other params
Code: Select all
;DESC: create a tool that underlines selected text and displays a list of matches
;INFO: danilo
CompilerIf #PB_Compiler_Unicode = 0
CompilerError "Compile with Unicode mode enabled"
CompilerEndIf
#INDIC_STRAIGHTBOX = 8
#INDIC_DASH = 9
#INDIC_DOTS = 10
#INDIC_SQUIGGLELOW = 11
#INDIC_DOTBOX = 12
#SCI_INDICSETALPHA = 2523
#SCI_INDICSETOUTLINEALPHA = 2558
#SCI_GOTOLINE =2024
;-----------------------------------
; SETUP
; #INDIC_PLAIN ; Underlined With a single, straight line.
; #INDIC_SQUIGGLE ; A squiggly underline. Requires 3 pixels of descender space.
; #INDIC_TT ; A line of small T shapes.
; #INDIC_DIAGONAL ; Diagonal hatching.
; #INDIC_STRIKE ; Strike out.
; #INDIC_HIDDEN ; An indicator With no visual effect.
; #INDIC_BOX ; A rectangle around the text.
;
; - the following styles don't work with Scintilla used by PB 4.60
; - maybe useful for future versions
;
; #INDIC_ROUNDBOX ; A rectangle with rounded corners around the text using translucent drawing
; ; with the interior usually more transparent than the border.
; ; You can use SCI_INDICSETALPHA And SCI_INDICSETOUTLINEALPHA to control the alpha transparency values.
; ; The default alpha values are 30 for fill colour and 50 for outline colour.
; #INDIC_STRAIGHTBOX ; A rectangle around the text using translucent drawing With the interior
; ; usually more transparent than the border.
; ; You can use SCI_INDICSETALPHA And SCI_INDICSETOUTLINEALPHA to control the alpha transparency values.
; ; The default alpha values are 30 for fill colour and 50 for outline colour.
; #INDIC_DASH ; A dashed underline.
; #INDIC_DOTS ; A dotted underline.
; #INDIC_SQUIGGLELOW ; Similar To INDIC_SQUIGGLE but only using 2 vertical pixels so will fit under small fonts.
; #INDIC_DOTBOX ; A dotted rectangle around the text using translucent drawing.
; ; Translucency alternates between the alpha and outline alpha settings with the top-left pixel
; ; using the alpha setting.
; ; SCI_INDICSETALPHA And SCI_INDICSETOUTLINEALPHA control the alpha transparency values.
; ; The default values are 30 For alpha And 50 For outline alpha.
; ; To avoid excessive memory allocation the maximum width of a dotted box is 4000 pixels.
; ; Not available For OS X Carbon.
style = #INDIC_STRAIGHTBOX
color = RGB($00,$FF,$FF)
InnerAlpha = 50
BorderAlpha = 200
totalcount=0
Structure iconlist
line$
text$
EndStructure
NewList linepos.iconlist()
#IGNORE_CASE = #True
;-----------------------------------
NewList positions.i()
NewList source.s()
Global Scintilla = Val( GetEnvironmentVariable("PB_TOOL_Scintilla") )
Global numBytes, utf8Buffer,sline$,sline.i
If Scintilla
SendMessageTimeout_(Scintilla,#SCI_GETSELECTIONSTART,0,0,#SMTO_ABORTIFHUNG,2000,@selectionStart)
SendMessageTimeout_(Scintilla,#SCI_GETSELECTIONEND ,0,0,#SMTO_ABORTIFHUNG,2000,@selectionEnd)
If selectionStart <> selectionEnd
word$=""
For i = selectionStart To selectionEnd-1
SendMessageTimeout_(Scintilla,#SCI_GETCHARAT,i,0,#SMTO_ABORTIFHUNG,2000,@result)
word$ + Chr(result)
Next i
Else
word$ = GetEnvironmentVariable("PB_TOOL_Word")
EndIf
SendMessageTimeout_(Scintilla,#SCI_SETINDICATORCURRENT ,9, 0 ,#SMTO_ABORTIFHUNG,2000,@result)
SendMessageTimeout_(Scintilla,#SCI_INDICSETSTYLE ,9, style ,#SMTO_ABORTIFHUNG,2000,@result)
SendMessageTimeout_(Scintilla,#SCI_INDICSETFORE ,9, color ,#SMTO_ABORTIFHUNG,2000,@result)
SendMessageTimeout_(Scintilla,#SCI_INDICSETALPHA ,9, InnerAlpha ,#SMTO_ABORTIFHUNG,2000,@result)
SendMessageTimeout_(Scintilla,#SCI_INDICSETOUTLINEALPHA ,9, BorderAlpha,#SMTO_ABORTIFHUNG,2000,@result)
SendMessageTimeout_(Scintilla,#SCI_INDICSETUNDER ,9, #False ,#SMTO_ABORTIFHUNG,2000,@result)
If word$
wordlen = Len(word$)
CompilerIf #IGNORE_CASE
word$ = LCase(word$)
CompilerEndIf
#SCI_GETCHARACTERPOINTER = 2520
SendMessageTimeout_(Scintilla,#SCI_SETREADONLY,1,0,#SMTO_ABORTIFHUNG,2000,@result)
SendMessageTimeout_(Scintilla,#SCI_GETCHARACTERPOINTER,0,0,#SMTO_ABORTIFHUNG,2000,@result)
If result
SendMessageTimeout_(Scintilla,#SCI_GETTEXTLENGTH,0,0,#SMTO_ABORTIFHUNG,2000,@length)
memory = AllocateMemory(length+2)
If Not memory
SendMessageTimeout_(Scintilla,#SCI_SETREADONLY,0,0,#SMTO_ABORTIFHUNG,2000,@result)
End
EndIf
GetWindowThreadProcessId_(Scintilla, @processId)
hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, #False, processId)
ReadProcessMemory_(hProcess,result,memory,length,0)
*p.Ascii = memory
length = memory + length
line=1
While *p < length And *p\a
If *p\a = 10 ; remove chr(10) + chr(13)
*p+1
If *p\a = 13 : *p+1 : EndIf
line+1
ElseIf *p\a = 13 ; remove chr(13) + chr(10)
*p+1
If *p\a = 10 : *p+1 : EndIf
line+1
Else ; read line
offset = *p - memory
text$ = ""
While *p\a And *p\a <> 10 And *p\a <> 13
text$ + Chr(*p\a)
*p+1
Wend
If text$
CompilerIf #IGNORE_CASE
text$ = LCase(text$)
CompilerEndIf
pos = 1
Repeat
pos = FindString(text$,word$,pos)
If pos
If AddElement(positions())
positions() = offset + pos - 1
EndIf
pos + wordlen
If AddElement(linepos())
linepos()\line$=Str(Line)+":"+Str(pos)
linepos()\text$=text$
EndIf
EndIf
Until pos = 0
EndIf
; line + 1
EndIf
Wend
EndIf
SendMessageTimeout_(Scintilla,#SCI_SETREADONLY,0,0,#SMTO_ABORTIFHUNG,2000,@result)
SendMessageTimeout_(Scintilla,#SCI_GETTEXTLENGTH ,0,0,#SMTO_ABORTIFHUNG,2000,@length)
PostMessage_(Scintilla,#SCI_INDICATORCLEARRANGE,0,length)
ForEach positions()
PostMessage_(Scintilla,#SCI_INDICATORFILLRANGE,positions(),wordlen)
Next
Else
SendMessageTimeout_(Scintilla,#SCI_GETTEXTLENGTH ,0,0,#SMTO_ABORTIFHUNG,2000,@length)
PostMessage_(Scintilla,#SCI_INDICATORCLEARRANGE,0,length)
EndIf
mainWnd = OpenWindow(#PB_Any, #PB_Any, #PB_Any, 425, 480, "Matches Found", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#PB_Any,10,10,200,25,"Total:"+Str(ListSize(positions())) )
wordlist = ListIconGadget(#PB_Any, 10, 40, 400, 400, "Line#", 75, #PB_ListIcon_GridLines )
AddGadgetColumn(wordlist, 1, "Text", 350)
ForEach linepos()
AddGadgetItem(wordlist, -1, linepos()\line$+Chr(10)+linepos()\text$)
Next
;PostMessage_(Scintilla,#SCI_GOTOLINE,0,210)
; SendMessageTimeout_(Scintilla,#SCI_GOTOLINE,210,0,#SMTO_ABORTIFHUNG,2000,@result)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
appQuit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case wordlist
Select EventType()
Case #PB_EventType_LeftClick
If GetGadgetState(wordlist) >= 0
sline$=GetGadgetItemText(wordlist, GetGadgetState(wordlist), 0)
sline$=Left(sline$,FindString(sline$,":")-1)
sline=Val(sline$)-1
; PostMessage_(Scintilla,#SCI_GOTOLINE,0,sline)
SendMessageTimeout_(Scintilla,#SCI_GOTOLINE,sline,0,#SMTO_ABORTIFHUNG,2000,@result)
; MessageRequester("SLCIT",sline$,#PB_MessageRequester_Ok )
SetForegroundWindow_(Scintilla)
EndIf
EndSelect
;myMsgBox(msg, mainWnd)
EndSelect
EndSelect
Until appQuit = 1
EndIf
Also here is list of IDE environment variables to be accessed using GetEnvironmentVariable() function.
Code: Select all
Tips for writing your own code processing tools
The IDE provides additional information for the tools in the form of environment variables. They can be easily read inside the tool with the commands of the Process library.
This is a list of provided variables. Note that those that provide information about the active source are not present for tools executed on IDE startup or end.
PB_TOOL_IDE - Full path and filename of the IDE
PB_TOOL_Compiler - Full path and filename of the Compiler
PB_TOOL_Preferences - Full path and filename of the IDE's Preference file
PB_TOOL_Project - Full path and filename of the currently open project (if any)
PB_TOOL_Language - Language currently used in the IDE
PB_TOOL_FileList - A list of all open files in the IDE, separated by Chr(10)
PB_TOOL_Debugger - These variables provide the settings from the Compiler Options
PB_TOOL_InlineASM window for the current source. They are set to "1" if the option
PB_TOOL_Unicode is enabled, and "0" if not.
PB_TOOL_Thread
PB_TOOL_XPSkin
PB_TOOL_OnError
PB_TOOL_SubSystem - content of the "Subsystem" field in the compiler options
PB_TOOL_Executable - same as the %COMPILEFILE token for the command-line
PB_TOOL_Cursor - same as the %CURSOR token for the command-line
PB_TOOL_Selection - same as the %SELECTION token for the command-line
PB_TOOL_Word - same as the %WORD token for the command-line
PB_TOOL_MainWindow - OS handle to the main IDE window
PB_TOOL_Scintilla - OS handle to the Scintilla editing component of the current source
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
Re: Question on using External Tools
You only need %TEMPFILE. Your tool should read this file and write its modifications back to the same file. If you have "Reload Source after the tool has quit" set, then the IDE will read back the contents of %TEMPFILE after the tool has quit and put the result back in the editor.
You should not modify the contents of the %FILE file! This file contains the state of the source code as the user last saved it. This could be much different from what is currently visible in the editor. If you overwrite this file, the user might lose data!
You should not modify the contents of the %FILE file! This file contains the state of the source code as the user last saved it. This could be much different from what is currently visible in the editor. If you overwrite this file, the user might lose data!
quidquid Latine dictum sit altum videtur
- netmaestro
- PureBasic Bullfrog
- Posts: 8433
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Re: Question on using External Tools
Could you please arrange to have this warning exactly as you wrote it placed in the help file at the appropriate place? Seriously, it needs to be there.freak wrote:You should not modify the contents of the %FILE file! This file contains the state of the source code as the user last saved it. This could be much different from what is currently visible in the editor. If you overwrite this file, the user might lose data!
BERESHEIT
Re: Question on using External Tools
Dear @Lunasole, thank so much for this code example --- it really gives a new light to my project! I did notice that in PB Help file it mentions two environment vars in relation to this topic: PB_TOOL_MainWindow and PB_TOOL_Scintilla, saying they are handles to the IDE, but without and example I couldn't really make much out of them. Now it makes a lot more sense.
@freak:
The Help files is a bit cryptic on this topic, I agree with @netmaestro that it's worth mentioning it in the docs.
Thanks a lot!
@freak:
Ah! I got that wrong, didn't realize the IDE would read back %TEMPFILE. I had a chance to expirement a bit, but I was taking the source from %TEMPFILE and the write the modified version to %FILE -- which then caused the IDE to warn that the source was changed and ask if I wanted to reload it.freak wrote:You only need %TEMPFILE. Your tool should read this file and write its modifications back to the same file. If you have "Reload Source after the tool has quit" set, then the IDE will read back the contents of %TEMPFILE after the tool has quit and put the result back in the editor.
You should not modify the contents of the %FILE file! This file contains the state of the source code as the user last saved it. This could be much different from what is currently visible in the editor. If you overwrite this file, the user might lose data!
The Help files is a bit cryptic on this topic, I agree with @netmaestro that it's worth mentioning it in the docs.
Thanks a lot!
The PureBASIC Archives:
- GitHub Repo + Wiki + Website
- https://tajmone.github.io/purebasic-archives
- PB Sourcecode Highlighters for Websites and Documents
- Dräc OOP Tutorial reprint
- Pandoc2BBCode: Post on PB Forums from Markdown, ReST, Docx, and other formats…
-
- Addict
- Posts: 4527
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: Question on using External Tools
+1netmaestro wrote:Could you please arrange to have this warning exactly as you wrote it placed in the help file at the appropriate place? Seriously, it needs to be there.freak wrote:You should not modify the contents of the %FILE file! This file contains the state of the source code as the user last saved it. This could be much different from what is currently visible in the editor. If you overwrite this file, the user might lose data!