Page 1 of 2

[Solved] How to change the cursor position within PB-IDE?

Posted: Fri Apr 12, 2019 3:34 pm
by Michael Vogel
Wrote a simple tool to list all procedure/macro names which could speed up navigation - but I would need a possibility to jump to a certain line within the active source code. What would be the easiest way (I'd like to avoid to send keys, like 'Ctrl+G', 'line number' and 'Enter' to the IDE)...

Code: Select all

; ProSeeker Tool	V1.0 by Michael Vogel
; -------------------------------------
; Commandline:	%COMPILEFILE\..\..\Pure\Tools\Tool ProSeeker.exe
; Arguments:		"%TEMPFILE"
; Shortcut:		Ctrl+Shift+P

; Define

	EnableExplicit

	#CharByteShift=	#PB_Compiler_Unicode
	#CharByte=		1<<#CharByteShift

	#LenMacro=   	5
	#LenProcedure=	9

	Structure NameList
		Name.s
		Info.s
		Line.i
	EndStructure

	Structure ComboboxInfo
		cbSize.l
		rcItem.RECT
		rcButton.RECT
		stateButton.l
		hwndCombo.i
		hwndItem.i
		hwndList.i
	EndStructure

	Structure ComboType
		pbnr.i
		pbid.i
		proc.i
		info.ComboboxInfo
	EndStructure

	Enumeration
		#StateIdle
		#StateAbort
		#StateExit
	EndEnumeration

	Enumeration
		#Window
		#Combo
		#Info
	EndEnumeration

	Enumeration
		#ModeProcedure
		#ModeMacro
	EndEnumeration

	Global *Combo.ComboType
	Global NewList Names.NameList()

	Global Line
	Global State


; EndDefine
Procedure GetName(*String.Character,Mode)

	Protected n,z
	Protected *Start
	Protected s.s

	Enumeration
		#Z_Idle
		#Z_Name
		#Z_Parameter
	EndEnumeration

	Repeat
		Select *String\c
		Case ' ',#TAB
			z=#True
			If n=0
				*Start=*String+#CharByte
			EndIf
		Case '('
			z<<1
			Break
		Case #Null,';','='
			Break
		Default
			If z : n+1 : EndIf
		EndSelect
		*String+#CharByte
	ForEver

	If z
		AddElement(Names())
		With Names()
			\Name=PeekS(*Start,n)
			\Line=Line
			\Info=" ["+Mid("ProcedureMacro",Mode*9+1,9)+"]"
			If z=#Z_Parameter
				s=StringField(PeekS(*String+#CharByte),1,")")
				If s
					\Info=Left(\Info,5)+"]: "+s
				EndIf
			EndIf
			\Info+", "+Str(Line)
			; Debug Str(\Line)+": "+\Name+" - "+\Parameter
		EndWith
	EndIf

EndProcedure
Procedure ScanProcedures(file.s)

	Protected z.i
	Protected s.s

	If ReadFile(0,file,#PB_File_SharedRead)
		While Eof(0)=0
			line+1
			s=ReadString(0)
			If s
				z=FindString(s,"procedure",1,#PB_String_NoCase)
				If z
					If (z<4 Or LCase(Mid(s,z-3,3))<>"end") And (LCase(Mid(s,z+#LenProcedure,1))<>"r")
						GetName(@s+(#LenProcedure+z-1)<<#CharByteShift,#ModeProcedure)
					EndIf
				EndIf
				z=FindString(s,"macro",1,#PB_String_NoCase)
				If z
					If (z<4 Or LCase(Mid(s,z-3,3))<>"end")
						GetName(@s+(#LenMacro+z-1)<<#CharByteShift,#ModeMacro)
						;Debug Str(line)+": "+s
					EndIf
				EndIf
			EndIf
		Wend
		CloseFile(0)

		If ListSize(Names())
			SortStructuredList(Names(),#PB_Sort_NoCase|#PB_Sort_Ascending,OffsetOf(NameList\Name),TypeOf(NameList\Name))
			; ResetList(Names())
			; While NextElement(Names())
			; 	With Names()
			; 		Debug Str(\Line)+": "+\Name+" - "+\Parameter
			; 	EndWith
			; Wend
			ProcedureReturn #True
		EndIf
	EndIf

	ProcedureReturn #Null

EndProcedure
Procedure.i ComboBoxEvents(hwnd,msg,wParam,lParam)

	Protected startpos,endpos
	Protected found
	Protected s.s

	If msg=#WM_CHAR
		Select wParam
		Case #CR
			State=#StateExit
			ProcedureReturn 0
		Case #ESC
			State=#StateAbort
			ProcedureReturn 0
		Default
			SendMessage_(hwnd,#EM_GETSEL,@startpos,0)
			s=Left(GetGadgetText(*Combo\pbnr),startpos)+Chr(wParam)
			found=SendMessage_(*Combo\pbid,#CB_FINDSTRING,-1,@s)
			If found>=#Null
				SetGadgetState(*Combo\pbnr,found)
				SendMessage_(hwnd,#EM_SETSEL,startpos+1,-1)
				SelectElement(Names(),found)
				SetGadgetText(#Info,Names()\Info)
				ProcedureReturn 0
			EndIf
		EndSelect

	EndIf

	ProcedureReturn CallWindowProc_(*Combo\proc,hwnd,msg,wParam,lParam)

EndProcedure
Procedure init()

	Protected id

	LoadFont(#Null,"Segoe UI",10)
	SetGadgetFont(#PB_Default, FontID(#Null))

	OpenWindow(#Window,210,210,320,50,"Procedure Seeker",#PB_Window_Invisible|#PB_Window_BorderLess);#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
	SetWindowColor(#Window,#Black)
	id=ComboBoxGadget(#Combo,1,23,318,26,#PB_ComboBox_Editable);|#CBS_SORT)
	;SendMessage_(id,#CB_SETCUEBANNER,0,@"Enter procedure name...")
	TextGadget(#Info,1,1,318,21," Search for procedures...")
	SetActiveGadget(#Combo)

	*Combo=AllocateMemory(SizeOf(ComboType))
	SendMessage_(id,#CB_SETMINVISIBLE, 15, 0)    ;ab 15 Einträge Scrollbalken

	With *Combo
		\info\cbSize=SizeOf(ComboboxInfo)
		GetComboBoxInfo_(id,\info)
		\pbid=id
		\pbnr=#Combo
		\proc=SetWindowLongPtr_(\info\hwndItem,#GWL_WNDPROC,@ComboBoxEvents())
	EndWith

	ResetList(Names())
	While NextElement(Names())
		SendMessage_(id,#CB_ADDSTRING,0,@Names()\Name)
	Wend

	StickyWindow(#Window,#True)
	HideWindow(#Window,#Null)

EndProcedure

: CompilerIf #PB_Compiler_Debugger :
: If ScanProcedures("C:\Program Files\System\Connect IQ\Information\Pure\Screeny.pb") :
: CompilerElse :

If CountProgramParameters()=1 And ScanProcedures(ProgramParameter())
	: CompilerEndIf :

	init()
	Repeat
		Select WaitWindowEvent()
		Case #PB_Event_CloseWindow
			State=#StateAbort

		Case #PB_Event_Gadget,#PB_Event_Menu
			If EventType()=#PB_EventType_Change
				Line=GetGadgetState(#Combo)
				If Line>=#Null
					SelectElement(Names(),Line)
					With Names()
						SetGadgetText(#Info,\Info)
					EndWith
				EndIf
			EndIf

		EndSelect
	Until State

	If State=#StateExit
		Line=GetGadgetState(#Combo)
		If Line>=#Null
			SelectElement(Names(),Line)
			; MessageRequester("Goto","Line "+Str(Names()\Line))
			Line=Val(GetEnvironmentVariable("PB_Tool_Scintilla"))
			If Line
				SendMessageTimeout_(Line,#SCI_GOTOLINE,Names()\Line-1,0,#SMTO_NORMAL,500,#Null)
			EndIf
		EndIf
	EndIf

EndIf

Re: How to change the cursor position within PB-IDE?

Posted: Fri Apr 12, 2019 3:58 pm
by #NULL
The IDE has a goto-line commandline parameter.

Code: Select all

filename.s = GetTemporaryDirectory() + "PB_EditorOutput.pb"

; <goto here>

Debug #PB_Compiler_Home

RunProgram(#PB_Compiler_Home + "compilers/purebasic", #DQUOTE$ + filename + #DQUOTE$ + " -l 3", GetTemporaryDirectory())
Not sure if this helps :) , on linux it doesn't work too well and there is no column parameter and i think it also depends on "[x] run only one instance", so FWIW.

Re: How to change the cursor position within PB-IDE?

Posted: Fri Apr 12, 2019 10:33 pm
by Michael Vogel
Thanks, I know, but I'd like to move the cursor within an active session - the external tool should control the IDE...
...In the give example above, the cursor should jump to the selected procedure when quitting the menu.

Re: How to change the cursor position within PB-IDE?

Posted: Fri Apr 12, 2019 11:14 pm
by skywalk
Yeah, I would love the same feature. Asked many times to enable too automation of file and cursor location to search for definitions of variables, procedures, macros, structures...

We need the same commands and the "Find in Files" tool.
There you can click on an item and the IDE jumps to that file and cursor position.

Re: How to change the cursor position within PB-IDE?

Posted: Sat Apr 13, 2019 2:44 am
by chi
Michael Vogel wrote:the external tool should control the IDE...
Create an external tool, get the hWnd with Val(GetEnvironmentVariable("PB_Tool_Scintilla")) and use SendMessageTimeout_() with:

Code: Select all

#SCI_GETCURRENTPOS
#SCI_GOTOPOS

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Sat Apr 13, 2019 6:22 am
by Michael Vogel
What a great Chi for my tool :P

Updated the first post, works fine now. Just call the tool from the IDE, choose the procedure and press 'Enter'...

...feel free to do some more tuning, like showing more information, adding mouse support (double click), poping up the window near the mouse cursor, etc.

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Mon Apr 15, 2019 12:43 pm
by gurj
@skywalk:
On the Tools menu, there is a process locator, which can also locate other content, code format:
;- your description

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Mon Apr 15, 2019 4:48 pm
by skywalk
What I was asking is how to go to a definition in another file, not necessarily opened in the IDE?
I don't understand the necessity of this tool if we already have the ProcedureBrowser?
This code works only in the current file tab.

Example: How to find a Procedure/Macro called within an If statement?

If MyProc() ;<-- I want to jump to this procedure?
;do something
EndIf
I can use [Ctrl]+LMDblClk if the source code is opened.
Or
Use Find in Files tool.

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Mon Apr 15, 2019 8:27 pm
by chi
skywalk wrote:What I was asking is how to go to a definition in another file, not necessarily opened in the IDE?

Example: How to find a Procedure/Macro called within an If statement?

If MyProc() ;<-- I want to jump to this procedure?
;do something
EndIf
I can use [Ctrl]+LMDblClk if the source code is opened.
Or
Use Find in Files tool.
in a nutshell:

Code: Select all

· create an IDE tool
· use argument "%FILE" to get the current source code (if you need it later)
· use GetEnvironmentVariable("PB_TOOL_FileList") to get all opened files in the IDE
· scan all files and prepare for search, also scan included files (Include, XInclude, ...)
· use GetEnvironmentVariable("PB_TOOL_Word") to get the current word under the cursor
· search all files for the word and save the position(s)
· open file, switch tab and jump to the position with #SCI_GOTOPOS

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Mon Apr 15, 2019 8:48 pm
by skywalk
Yes, freak mentioned a Tool workaround to switch tabs is by opening a file. The focus jumps to that newly opened file. But, what if the file is already open? I have to close it?

How does this happen?
"open file, switch tab and jump to the position with #SCI_GOTOPOS"

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Tue Apr 16, 2019 3:56 am
by chi
skywalk wrote:Yes, freak mentioned a Tool workaround to switch tabs is by opening a file. The focus jumps to that newly opened file. But, what if the file is already open? I have to close it?

How does this happen?
"open file, switch tab and jump to the position with #SCI_GOTOPOS"
No, you don't need to close it... If it's already open, it just switches to the tab!

Code: Select all

;IDE-Tool
fileList$ = GetEnvironmentVariable("PB_TOOL_FileList") ; get all opened files
file$ = StringField(fileList$, 1, Chr(10))             ; select the first file
RunProgram(Chr(34) + file$ + Chr(34))                  ; use RunProgram to switch to the file

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Tue Apr 16, 2019 11:47 pm
by chi
So, here is a little proof of concept... I was curious ;)

Compile and create a new entry under Tools/Configure Tools..., no Arguments needed. Only works with utf8 encoded files, though (and Windows only, duh). Like I said, PoC ^^

Code: Select all

EnableExplicit
UseCRC32Fingerprint()

Structure _TAB
  path$
  text$
  id.i
  hWnd.i
EndStructure
Global NewMap tab._TAB()

Procedure EnumChildProc(hWnd, lParam)
  Protected length = SendMessage_(hWnd, #WM_GETTEXTLENGTH, 0, 0) + 1
  Protected txt$ = Space(length)
  SendMessage_(hWnd, #WM_GETTEXT, length, @txt$)
  If Trim(txt$) <> ""
    If FindMapElement(tab(), StringFingerprint("?" + txt$ + Chr(13) + Chr(10), #PB_Cipher_CRC32, 0, #PB_Ascii))
      tab()\hWnd = hWnd
    EndIf
  EndIf
  ProcedureReturn #True
EndProcedure

OpenWindow(0, 0, 0, 370, 70, "TabPosJumper - Select TAB, POS and press GO...", #PB_Window_Tool|#PB_Window_SystemMenu|#PB_Window_ScreenCentered, Val(GetEnvironmentVariable("PB_TOOL_MainWindow")))

ComboBoxGadget(0, 10, 10, 270, 21)
SpinGadget(1, 290, 10, 70, 21, 0, 9999999, #PB_Spin_Numeric)
SetGadgetState(1, 0)
ButtonGadget(2, 290, 40, 70, 21, "GO")
ProgressBarGadget(3, 10, 41, 270, 19, 0, 999)
RedrawWindow_(WindowID(0), 0, 0, #RDW_UPDATENOW)

Define fileList$ = GetEnvironmentVariable("PB_TOOL_FileList")
Define i, path$, text$, line$, count = CountString(fileList$, Chr(10)) + 1
Define progress = 1000.0 / count

For i = 1 To count
  path$ = StringField(fileList$, i, Chr(10))
  
  text$ = ""
  If ReadFile(0, path$)
    While Eof(0) = 0
      line$ = ReadString(0)
      If Left(line$, 13) = "; IDE Options"
        Break
      EndIf
      text$ + line$ + Chr(13) + Chr(10)
    Wend
    CloseFile(0)
  EndIf
  
  tab(StringFingerprint(text$, #PB_Cipher_CRC32, 256, #PB_Ascii))
  tab()\path$ = path$
  tab()\text$ = text$
  tab()\id = i
  
  AddGadgetItem(0, 0, Space(1) + GetFilePart(path$))
  SetGadgetItemData(0, 0, @tab())
  
  SetGadgetState(3, progress * i)
Next

EnumChildWindows_(GetAncestor_(Val(GetEnvironmentVariable("PB_Tool_Scintilla")), #GA_PARENT), @EnumChildProc(), 0)

SetGadgetState(3, 0)
SetGadgetState(0, 0)

Repeat
  Define event = WaitWindowEvent()
  Select event
    Case #PB_Event_Gadget
      Select EventGadget()
          
        Case 2
          If Trim(GetGadgetText(0)) <> ""
            Define *tab._TAB = GetGadgetItemData(0, GetGadgetState(0))
            SendMessageTimeout_(*tab\hWnd, #SCI_GOTOPOS, GetGadgetState(1), 0, #SMTO_ABORTIFHUNG, 2000, 0)
            RunProgram(Chr(34) + *tab\path$ + Chr(34))
          EndIf
          
      EndSelect
  EndSelect
Until event = #PB_Event_CloseWindow
[/size]

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Wed Apr 17, 2019 2:40 am
by skywalk
Nice, I will check it out! I'll revisit some tool codes that hit this road block. :twisted:

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Wed Apr 17, 2019 3:11 pm
by chi
This is much faster now and also works with "Plain Text" encoded files in the IDE (if the character count doesn't exceed a certain amount)

Code: Select all

EnableExplicit
UseCRC32Fingerprint()

Structure _TAB
  path$
  text$
  hWnd.i
EndStructure
Global NewMap tab._TAB()

Procedure EnumChildProc(hWnd, lParam)
  Protected length = SendMessage_(hWnd, #WM_GETTEXTLENGTH, 0, 0) + 1
  Protected txt$ = Space(length)
  SendMessage_(hWnd, #WM_GETTEXT, length, @txt$)
  If Trim(txt$) <> ""
    If FindMapElement(tab(), StringFingerprint(txt$, #PB_Cipher_CRC32))
      tab()\hWnd = hWnd
    EndIf
  EndIf
  ProcedureReturn #True
EndProcedure

OpenWindow(0, 0, 0, 370, 70, "TabPosJumper - Select TAB, POS and press GO...", #PB_Window_Tool|#PB_Window_SystemMenu|#PB_Window_ScreenCentered, Val(GetEnvironmentVariable("PB_TOOL_MainWindow")))

ComboBoxGadget(0, 10, 10, 270, 21)
SpinGadget(1, 290, 10, 70, 21, 0, 9999999, #PB_Spin_Numeric)
SetGadgetState(1, 0)
ButtonGadget(2, 290, 40, 70, 21, "GO")
ProgressBarGadget(3, 10, 41, 270, 19, 0, 999)
RedrawWindow_(WindowID(0), 0, 0, #RDW_UPDATENOW)

Define fileList$ = GetEnvironmentVariable("PB_TOOL_FileList")
Define i, path$, text$, count = CountString(fileList$, Chr(10)) + 1
Define pos, progress = 1000.0 / count

For i = 1 To count
  SetGadgetState(3, progress * i)
  
  path$ = StringField(fileList$, i, Chr(10))
  
  If ReadFile(0, path$)
    ReadStringFormat(0)
    text$ = ReadString(0, #PB_File_IgnoreEOL)
    CloseFile(0)
    
    pos = FindString(text$, Chr(13) + Chr(10) + "; IDE Options") - 1
    If pos
      text$ = Mid(text$, 1, pos)
    EndIf
    
    tab(StringFingerprint(text$, #PB_Cipher_CRC32))
    tab()\path$ = path$
    tab()\text$ = text$
    
    AddGadgetItem(0, 0, Space(1) + GetFilePart(path$))
    SetGadgetItemData(0, 0, @tab())
  EndIf
Next

EnumChildWindows_(GetAncestor_(Val(GetEnvironmentVariable("PB_Tool_Scintilla")), #GA_PARENT), @EnumChildProc(), 0)

SetGadgetState(3, 0)
SetGadgetState(0, 0)

Repeat
  Define event = WaitWindowEvent()
  Select event
    Case #PB_Event_Gadget
      Select EventGadget()
          
        Case 2
          If Trim(GetGadgetText(0)) <> ""
            Define *tab._TAB = GetGadgetItemData(0, GetGadgetState(0))
            SendMessageTimeout_(*tab\hWnd, #SCI_GOTOPOS, GetGadgetState(1), 0, #SMTO_ABORTIFHUNG, 2000, 0)
            RunProgram(Chr(34) + *tab\path$ + Chr(34))
          EndIf
          
      EndSelect
  EndSelect
Until event = #PB_Event_CloseWindow
[/size]Edit: cleaned the code a little bit...

Re: [Solved] How to change the cursor position within PB-IDE

Posted: Wed Apr 17, 2019 4:00 pm
by skywalk
Wow chi :D :D :D :D :D
I can use this!
I will post some unified Tool code once I integrate this.
Thanks so much.