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

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

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

Post 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
Last edited by Michael Vogel on Sat Apr 13, 2019 6:18 am, edited 2 times in total.
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

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

Post 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.
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

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

Post 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.
User avatar
skywalk
Addict
Addict
Posts: 3999
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

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

Post 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.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

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

Post 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
Et cetera is my worst enemy
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

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

Post 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.
User avatar
gurj
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

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

Post by gurj »

@skywalk:
On the Tools menu, there is a process locator, which can also locate other content, code format:
;- your description
my pb for chinese:
http://ataorj.ys168.com
User avatar
skywalk
Addict
Addict
Posts: 3999
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

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

Post 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.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

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

Post 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
Et cetera is my worst enemy
User avatar
skywalk
Addict
Addict
Posts: 3999
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

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

Post 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"
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

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

Post 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
Et cetera is my worst enemy
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

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

Post 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]
Et cetera is my worst enemy
User avatar
skywalk
Addict
Addict
Posts: 3999
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

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

Post by skywalk »

Nice, I will check it out! I'll revisit some tool codes that hit this road block. :twisted:
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
chi
Addict
Addict
Posts: 1034
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

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

Post 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...
Last edited by chi on Wed Apr 17, 2019 4:31 pm, edited 1 time in total.
Et cetera is my worst enemy
User avatar
skywalk
Addict
Addict
Posts: 3999
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

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

Post 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.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Post Reply