Show all occurrences of a word in the IDE

Working on new editor enhancements?
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Updated the first post on the previous page
1. When entering a regular expression, you can press Enter to apply.
2. In the header of the table, added the line from which the call was made.
3. Made an event #NM_CLICK, since the BindGadgetEvent fires 3 events, one event from Header and two click events apparently press and release. In my debugger, for each click, there were 3 line numbers, now one.
4. Added a window search to test without compiling, just running the code. Now the jump to the line works. You need to remove this code before compiling. It is marked with the comment "; For test only" and "; End: For test only". This code does not interfere, but remove it so that the file size is smaller.

I tried to paint over the entire Header, but I couldn't get it to work properly.

Finding a window without using GetEnvironmentVariable()

Code: Select all

EnableExplicit
Global hWnd_Main, hScintilla, classText.s = Space(256)
; Global Length, Text$



Procedure.s GetScintillaText()
	Protected ReturnValue.s
	Protected length
	Protected buffer
	Protected processId
	Protected hProcess
	Protected result
	
	length = SendMessage_(hScintilla, #SCI_GETLENGTH, 0, 0)
	If length
		length + 2
		buffer = AllocateMemory(length)
		If buffer
			SendMessageTimeout_(hScintilla, #SCI_GETCHARACTERPOINTER, 0, 0, #SMTO_ABORTIFHUNG, 2000, @result)
			If result
				GetWindowThreadProcessId_(hScintilla, @processId)
				hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, #False, processId)
				If hProcess
					ReadProcessMemory_(hProcess, result, buffer, length, 0)
					ReturnValue = PeekS(buffer, -1, #PB_UTF8)
					CloseHandle_(hProcess)  ; <-- Axolotl, added acc. to MSDN
				EndIf
			EndIf
		EndIf
		FreeMemory(buffer)
	EndIf
	ProcedureReturn ReturnValue
EndProcedure

Procedure.l enumChildren0(hwnd.l)
	If hwnd
		GetClassName_(hwnd, @classText, 256)
		If classText = "WindowClass_2"
			GetWindowText_(hwnd, @classText, 256)
			If Left(classText, 9) = "PureBasic"
				hWnd_Main = hwnd
				ProcedureReturn 0
			EndIf
		EndIf
		ProcedureReturn 1
	EndIf
	ProcedureReturn 0
EndProcedure

Procedure.l isHandle(hwnd.l)
	If Not hwnd
		End
	EndIf
EndProcedure

Procedure.l enumChildren1(hwnd.l)
	If hwnd
		GetClassName_(hwnd, @classText, 256)
		If classText = "Scintilla"
			hScintilla = hwnd
			ProcedureReturn 0
		EndIf
		ProcedureReturn 1
	EndIf
	ProcedureReturn 0
EndProcedure

EnumChildWindows_(0, @enumChildren0(), 0)
isHandle(hWnd_Main)
EnumChildWindows_(hWnd_Main, @enumChildren1(), 0)
; Debug hWnd_Main
; Debug hScintilla

; Length = SendMessage_(hScintilla, #SCI_GETLENGTH, 0, 0)
; Debug Length
; Length = SendMessage_(hScintilla, #SCI_GETSELTEXT, 0, 0)
; Text$ = Space(Length)
; SendMessage_(hScintilla, #SCI_GETSELTEXT, 0, @Text$)
; Debug Text$


MessageRequester("", GetScintillaText())
Dadlick
New User
New User
Posts: 6
Joined: Thu Feb 16, 2023 3:28 am

Re: Show all occurrences of a word in the IDE

Post by Dadlick »

AZJIO
I tried to paint over the entire Header, but I couldn't get it to work properly.
Add procedure

Code: Select all

Procedure SubclassedListIcon(hwnd, msg, wparam, lparam) 
  Protected hdi.hd_item, result,*nmhdr.NMHDR, *pnmcd.NMCUSTOMDRAW, text$
  result = CallWindowProc_(oldListIconCallback, hwnd, msg, wparam, lparam) 
  Select msg 
    Case #WM_NOTIFY 
      *nmhdr.NMHDR = lparam  
        If *nmhdr\code = #NM_CUSTOMDRAW
        *pnmcd.NMCUSTOMDRAW = lparam 
        Select *pnmcd\dwDrawStage 
          Case #CDDS_PREPAINT 
            result = #CDRF_NOTIFYITEMDRAW 
          Case #CDDS_ITEMPREPAINT 
            text$=GetGadgetItemText(GetDlgCtrlID_(hWnd),-1,*pnmcd\dwItemSpec)
              DrawFrameControl_(*pnmcd\hdc, *pnmcd\rc, #DFC_BUTTON, #DFCS_BUTTONPUSH)
            InflateRect_(*pnmcd\rc,-1,0)
            SetBkMode_(*pnmcd\hdc,#TRANSPARENT) 
            FillRect_(*pnmcd\hdc, *pnmcd\rc, BackColorBrush)
            If *pnmcd\dwItemSpec = 1
              SetTextColor_(*pnmcd\hdc, colors(0))
            Else
              SetTextColor_(*pnmcd\hdc, colors(1))
            EndIf
            *pnmcd\rc\top+2
            InflateRect_(*pnmcd\rc,-8,0)
            If *pnmcd\rc\right>*pnmcd\rc\left
              DrawText_(*pnmcd\hdc, @text$, Len(text$), *pnmcd\rc, #DT_END_ELLIPSIS|#DT_VCENTER|#DT_SINGLELINE)
            EndIf
            result = #CDRF_SKIPDEFAULT
        EndSelect 
      EndIf 
  EndSelect 
  ProcedureReturn result 
EndProcedure 
And a link to it after creating the gadget

Code: Select all

oldListIconCallback = SetWindowLong_(GadgetID(#frmMain_References), #GWL_WNDPROC, @SubclassedListIcon())
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

1. Added regular expressions, now there are 28 of them.
2. Yellow color in Header to distinguish this item.
3. The second column expands with the window, this avoids the white background on the right.
4. The button is drawn according to the black style.

Download: yandex
Last edited by AZJIO on Wed Mar 22, 2023 2:14 pm, edited 13 times in total.
nsstudios
Enthusiast
Enthusiast
Posts: 274
Joined: Wed Aug 28, 2019 1:01 pm
Location: Serbia
Contact:

Re: Show all occurrences of a word in the IDE

Post by nsstudios »

Thanks so much! This is really useful!
I had to prevent it firing on item focus change, and added enter shortcut (used the code from the first post, hopefully that's OK and it's still up to date)

Code: Select all

;   Description: Find all references of a variable
;            OS: Windows
; English-Forum: 
;  French-Forum: 
;  German-Forum: http://www.purebasic.fr/german/viewtopic.php?f=8&t=28292
;-----------------------------------------------------------------------------

; MIT License
; 
; Copyright (c) 2015 Kiffi
; 
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
; 
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
; 
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.

; FindAllReferences



CompilerIf #PB_Compiler_OS<>#PB_OS_Windows
	CompilerError "Windows Only!"
CompilerEndIf

EnableExplicit

Enumeration ; Windows
	#frmMain
EndEnumeration
Enumeration ; Gadgets
	#frmMain_References
EndEnumeration
Enumeration ; Menu-/Toolbaritems
	#frmMain_Shortcut_Escape_Event
	#frmMain_Shortcut_Return_Event
EndEnumeration

Global PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
If PbIdeHandle = 0 : End : EndIf

Global ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
If ScintillaHandle = 0 : End : EndIf

Procedure.s RemoveLeadingWhitespaceFromString(InString.s)
	
	While Left(InString, 1) = Chr(32) Or Left(InString, 1) = Chr(9)
		InString = LTrim(InString, Chr(32))
		InString = LTrim(InString, Chr(9))
	Wend
	
	ProcedureReturn InString
	
EndProcedure

Procedure.s GetScintillaText()
	
	Protected ReturnValue.s
	
	Protected length
	Protected buffer
	Protected processId
	Protected hProcess
	Protected result
	
	length = SendMessage_(ScintillaHandle, #SCI_GETLENGTH, 0, 0)
	If length
		length + 2
		buffer = AllocateMemory(length)
		If buffer   
			SendMessageTimeout_(ScintillaHandle, #SCI_GETCHARACTERPOINTER, 0, 0, #SMTO_ABORTIFHUNG, 2000, @result)
			If result
				GetWindowThreadProcessId_(ScintillaHandle, @processId)
				hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, #False, processId)
				If hProcess
					ReadProcessMemory_(hProcess, result, buffer, length, 0)   
					ReturnValue = PeekS(buffer, -1, #PB_UTF8)
				EndIf
			EndIf
		EndIf
		FreeMemory(buffer)
	EndIf
	
	ProcedureReturn ReturnValue
	
EndProcedure

Procedure frmMain_SizeWindow_Event()
	ResizeGadget(#frmMain_References, #PB_Ignore, #PB_Ignore, WindowWidth(#frmMain) - 20, WindowHeight(#frmMain) - 20)
EndProcedure

Procedure frmMain_References_Event()
	
	Protected SelectedLine
	
	SelectedLine = Val(GetGadgetItemText(#frmMain_References, GetGadgetState(#frmMain_References), 0))
	
	If SelectedLine > 0
		SendMessage_(ScintillaHandle, #SCI_GOTOLINE, SelectedLine - 1, 0)
		SendMessage_(ScintillaHandle, #SCI_ENSUREVISIBLE, SelectedLine - 1, 0)
		SetForegroundWindow_(PbIdeHandle)
		SetActiveWindow_(PbIdeHandle)
	EndIf
	
EndProcedure

Define SelectedWord.s = GetEnvironmentVariable("PB_TOOL_Word")
If SelectedWord = "" : End : EndIf

Define ScintillaText.s = GetScintillaText()
If ScintillaText = "" : End : EndIf

Define Line.s
Define CountLines, LineCounter
Define CountTokens, TokenCounter
Define WWE
Define RegexLines, PbRegexTokens

Structure sFoundReference
	LineNo.i
	Reference.s
	
EndStructure

NewList FoundReference.sFoundReference()

Dim Tokens.s(0)


;http://www.purebasic.fr/english/viewtopic.php?f=12&t=37823
RegexLines = CreateRegularExpression(#PB_Any , ".*\r\n")
PbRegexTokens = CreateRegularExpression(#PB_Any, #DOUBLEQUOTE$ + "[^" + #DOUBLEQUOTE$ + "]*" + #DOUBLEQUOTE$ + "|[\*]?[a-zA-Z_]+[\w]*[\x24]?|#[a-zA-Z_]+[\w]*[\x24]?|[\[\]\(\)\{\}]|[-+]?[0-9]*\.?[0-9]+|;.*|\.|\+|-|[&@!\\\/\*,\|]|::|:|\|<>|>>|<<|=>{1}|>={1}|<={1}|=<{1}|={1}|<{1}|>{1}|\x24+[0-9a-fA-F]+|\%[0-1]*|%|'")

CountLines = CountString(ScintillaText, #CRLF$)

Dim Lines.s(0)

CountLines = ExtractRegularExpression(RegexLines, ScintillaText, Lines())

SelectedWord = LCase(SelectedWord)

For LineCounter = 0 To CountLines - 1
	
	Line = Lines(LineCounter)   
	
	CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())
	
	For TokenCounter = 0 To CountTokens - 1   
		If SelectedWord = LCase(Tokens(TokenCounter))
			AddElement(FoundReference())
			FoundReference()\LineNo = LineCounter + 1
			Line = Trim(Line)
			Line = Mid(Line, 1, Len(Line)-2)
			FoundReference()\Reference = Line
		EndIf
		
	Next
	
Next

If ListSize(FoundReference()) = 0
	
	SelectedWord = "#" + SelectedWord
	
	For LineCounter = 0 To CountLines - 1
		
		Line = Lines(LineCounter)   
		
		CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())
		
		For TokenCounter = 0 To CountTokens - 1   
			If SelectedWord = LCase(Tokens(TokenCounter))
				AddElement(FoundReference())
				FoundReference()\LineNo = LineCounter + 1
				Line = Trim(Line)
				Line = Mid(Line, 1, Len(Line)-2)
				FoundReference()\Reference = Line
			EndIf
			
		Next
		
	Next	
	
	If ListSize(FoundReference()) = 0 : End : EndIf
EndIf

OpenWindow(#frmMain,
           #PB_Ignore,
           #PB_Ignore,
           600,
           300,
           "Display all: '" + SelectedWord + "'",
           #PB_Window_SystemMenu |
           #PB_Window_SizeGadget |
           #PB_Window_ScreenCentered)

StickyWindow(#frmMain, #True)

ListIconGadget(#frmMain_References,
               10,
               10,
               WindowWidth(#frmMain) - 20,
               WindowHeight(#frmMain) - 20,
               "Line",
               50,
               #PB_ListIcon_FullRowSelect |   
               #PB_ListIcon_GridLines |
               #PB_ListIcon_AlwaysShowSelection)

AddGadgetColumn(#frmMain_References, 1, "Ref", 400)


ForEach FoundReference()
	AddGadgetItem(#frmMain_References, -1, Str(FoundReference()\LineNo) + #LF$ + FoundReference()\Reference)   
Next

Define i

SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 0, #LVSCW_AUTOSIZE_USEHEADER)
SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 1, #LVSCW_AUTOSIZE)
SendMessage_(GadgetID(#frmMain_References), #LVM_SETCOLUMNWIDTH, 2, #LVSCW_AUTOSIZE)

AddKeyboardShortcut(#frmMain, #PB_Shortcut_Escape, #frmMain_Shortcut_Escape_Event)
AddKeyboardShortcut(#frmMain, #PB_Shortcut_Return, #frmMain_Shortcut_Return_Event)
BindEvent(#PB_Event_SizeWindow, @frmMain_SizeWindow_Event(), #frmMain)
BindGadgetEvent(#frmMain_References, @frmMain_References_Event(), #PB_EventType_LeftClick)

SetActiveGadget(#frmMain_References)


Repeat
	
	WWE = WaitWindowEvent()
	
	If WWE = #PB_Event_Menu
		Select EventMenu()
			Case #frmMain_Shortcut_Escape_Event
				Break
			Case #frmMain_Shortcut_Return_Event
				PostEvent(#PB_Event_Gadget, #frmMain, #frmMain_References, #PB_EventType_LeftClick)
		EndSelect
	EndIf
	
Until WWE=#PB_Event_CloseWindow
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

I tried to adapt for Notepad++. Download: yandex, upload.ee (updated). It would be great if there was some kind of window automation library, such as searching for a window by class and searching for window elements by class.
But in Notepad ++ this can be done by searching for all occurrences, while the entire list of lines will be displayed in the console and by clicking it also moves through the lines.

I improved the regular expressions on the previous page, I forgot to add "\K". Now the keywords If, Loop, Select, Include are highlighted.
Added search execution time.
The Ctrl+C copy command has been replaced with Ctrl+Shift+C, otherwise it won't let you copy the regular expression.

I tried to adapt for SciTE. Download: yandex, upload.ee. It turned out well, because I successfully received the Scintilla handle and all Scintilla commands worked with it without problems. Screenshot
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Linux

command line:
"%WORD" "%CURSOR" "%TEMPFILE"

But it is not clear how to make a jump to the line.
No word highlighting.

Code: Select all

; ----------------------------------------------------------------------------
; File : FindAllReferences[Linux].pb
; ----------------------------------------------------------------------------

EnableExplicit

;- Structure

Structure sFoundReference
	LineNo.i
	Reference.s
	Selregexp.s
EndStructure

Structure xywhm
	x.i
	y.i
	w.i
	h.i
	m.i
EndStructure

;- Enumeration
Enumeration ; Windows
	#frmMain
EndEnumeration

Enumeration ; Gadgets
	#cmbRex
	#btnRex
	; 	#btnClose
	#frmMain_References
EndEnumeration

Enumeration ; Menu-/Toolbaritems
	#frmMain_Shortcut_Escape_Event
	#Shortcut_Ctrl_Shift_C
	#Shortcut_Enter
EndEnumeration

;- Constants
CompilerIf #PB_Compiler_Debugger
	#SelectedWordMarker$ = "|"
CompilerElse
	#SelectedWordMarker$ = Chr(1)  ; not used in source codes
CompilerEndIf
; "	 Line = Trim(Line)"
; "	 |Line| = Trim(|Line|)"
; --> ReplaceString(text$, SelectedWord, #SelectedWordMarker$ + SelectedWord + #SelectedWordMarker$)

;/-----------------------------------------------------------------------------
;| RGB() as HEX() -->     BB GG RR   .. i.e. RGB (1, 2, 3)    -->    03 02 01
;| RGB() as HEX() -->  AA BB GG RR   .. i.e. RGBA(1, 2, 3, 4) --> 04 03 02 01
;\

#coloredChars_Delimeter = "{***\"

;- Global
Global ini$ = LSet(ProgramFilename(), Len(ProgramFilename()) - 3) + "ini"
Global centered
Global xywh.xywhm
Global xywh2.xywhm
Global xywh\w = 600
Global xywh\h = 300
Global hHeader
Global frmMain_References
Global CursorLine
Global flgRead

Global PbIdeHandle, ScintillaHandle

Global SelectedWord.s, ScintillaText.s
Global CountSelectedWords    ; new, because we want to know all references (not only the lines)
Global NewList FoundReference.sFoundReference()
Global Dim Lines.s(0)

Global BackColor = $3f3f3f
Global ForeColor = $cccccc
Global BackColorHeader = $222222
Global ForeColorHeader = $72ADC0
Global BorderColor = $888888
; Global HightLightBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
; Global HightLightBrush = CreateSolidBrush_($423926)
; Global BackColorBrush = CreateSolidBrush_(BackColor)
; Global BackColorBrushHeader = CreateSolidBrush_(BackColorHeader)

; ; ; Global PbIdeHandle = Val(GetEnvironmentVariable("PB_TOOL_MainWindow"))
; ; ; If PbIdeHandle = 0 : End : EndIf
; ; ;
; ; ; Global ScintillaHandle = Val(GetEnvironmentVariable("PB_TOOL_Scintilla"))
; ; ; If ScintillaHandle = 0 : End : EndIf

; ---== Procedures ==--------------------------------------------------------------------------------------------------

; AZJIO
Procedure.s LTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
	Protected *memChar, *c.Character, *jc.Character

	If Not Asc(String$)
		ProcedureReturn ""
	EndIf

	*c.Character = @String$
	*memChar = @TrimChar$

	While *c\c
		*jc.Character = *memChar

		While *jc\c
			If *c\c = *jc\c
				*c\c = 0
				Break
			EndIf
			*jc + SizeOf(Character)
		Wend

		If *c\c
			String$ = PeekS(*c)
			Break
		EndIf
		*c + SizeOf(Character)
	Wend

	ProcedureReturn String$
EndProcedure

Procedure.s RTrimChar(String$, TrimChar$ = #CRLF$ + #TAB$ + #FF$ + #VT$ + " ")
    Protected Len2, Blen, i
    Protected *memChar, *c.Character, *jc.Character

    Len2 = Len(String$)
    Blen = StringByteLength(String$)

    If Not Asc(String$)
        ProcedureReturn ""
    EndIf

    *c.Character = @String$ + Blen - SizeOf(Character)
    *memChar = @TrimChar$

    For i = Len2 To 1 Step - 1
        *jc.Character = *memChar

        While *jc\c
            If *c\c = *jc\c
                *c\c = 0
                Break
            EndIf
            *jc + SizeOf(Character)
        Wend

        If *c\c
            Break
        EndIf
        *c - SizeOf(Character)
    Next

    ProcedureReturn String$
EndProcedure


Procedure Initialization()
	Protected PathFile$
	If CountProgramParameters() > 0
		SelectedWord = ProgramParameter(0)
		CursorLine = Int(Val(StringField(ProgramParameter(1), 1, "x")))
		PathFile$ = ProgramParameter(2)
		
		#File = 0
		If ReadFile(#File, PathFile$)
			ScintillaText = ReadString(#File, #PB_UTF8 | #PB_File_IgnoreEOL)
			CloseFile(#File)
		EndIf
; 		MessageRequester(SelectedWord, Str(CountProgramParameters()))
; 		MessageRequester(SelectedWord, ScintillaText)
	EndIf



	


; For test only
	CompilerIf #PB_Compiler_Debugger

		If SelectedWord = ""
			;     SelectedWord = "Line"    ; try one of these
			;     SelectedWord = "#Line"   ; -"-  #Line could be in a comment also
			SelectedWord = "ScintillaText"   ; -"-
		EndIf

		If ScintillaText = ""
			#File = 0
			If ReadFile(#File, #PB_Compiler_File)
				ScintillaText = ReadString(#File, #PB_UTF8 | #PB_File_IgnoreEOL)
				CloseFile(#File)
			EndIf
			If ScintillaText = ""
				MessageRequester("", "Не могу получить текст Scintilla.")
			EndIf
		EndIf
	CompilerEndIf
; End: For test only

	ProcedureReturn 0  ; default (ZERO is returned by default, even if there is no ProcedureReturn)
EndProcedure

; ---------------------------------------------------------------------------------------------------------------------

; ChrisR
Procedure CopyClipboard()
	Protected text$
	PushListPosition(FoundReference())
	ForEach FoundReference()
		If text$ : text$ + #CRLF$ : EndIf
		If Right(FoundReference()\Reference, 2) = #CRLF$
			text$ + Left(FoundReference()\Reference, Len(FoundReference()\Reference) - 2)
		Else
			text$ + FoundReference()\Reference
		EndIf
	Next
	PopListPosition(FoundReference())
	If text$
		text$ = ReplaceString(text$, #SelectedWordMarker$, "")
		SetClipboardText(text$)
		Protected Title$ = GetWindowTitle(#frmMain)
		SetWindowTitle(#frmMain, Title$ + " (Reference copied To the clipboard)")
		Delay(500)
		SetWindowTitle(#frmMain, Title$)
	EndIf
EndProcedure

; AZJIO
Procedure GoRegExp()
	; LINK : https://www.purebasic.fr/english/viewtopic.php?p=595832#p595832
	Protected rex, LSize, Pos = 0, i, tmp$
	Protected Dim Tokens.s(0)
	Protected timer
	
	timer = ElapsedMilliseconds()

	ClearGadgetItems(#frmMain_References)
	ClearList(FoundReference())

	tmp$ = GetGadgetText(#cmbRex)
	If Not Asc(tmp$)
		ProcedureReturn
	EndIf
	rex = CreateRegularExpression(#PB_Any, tmp$)
	; 	CountTokens = ExtractRegularExpression(rex, ScintillaText, Tokens()) ; tokenize the line

	; 	Debug ArraySize(Lines())

	If rex
		If ExamineRegularExpression(rex, ScintillaText)
			While NextRegularExpressionMatch(rex)
				If Not FindString(RegularExpressionMatchString(rex), #LF$)
					AddElement(FoundReference())
					FoundReference()\Selregexp = RegularExpressionMatchString(rex)
					FoundReference()\LineNo = RegularExpressionMatchPosition(rex)
					; 					Debug  FoundReference()\LineNo
				EndIf
			Wend
		EndIf
	Else
		MessageRequester("Regular expression error", RegularExpressionError())
		ProcedureReturn
	EndIf

	LSize = ListSize(FoundReference())
	If LSize > 0
		; 		If LSize > 5000 And MessageRequester("Continue?", "Found" + Str(LSize) + " rows, Continue?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
		; 			ProcedureReturn
		; 		EndIf

		Pos = 0
		i = 0
		ForEach FoundReference()
			While Pos < FoundReference()\LineNo
				Pos = FindString(ScintillaText, #LF$, Pos + 1)
				If Pos
					i + 1
				Else
					Break
				EndIf
				; 				Debug Str(FoundReference()\LineNo) + " "  + Str(Pos)
			Wend
			If i < 1 Or i > ArraySize(Lines())
				Continue
			EndIf
			FoundReference()\LineNo = i
			FoundReference()\Reference = Lines(i - 1)


			FoundReference()\Reference = LTrimChar(FoundReference()\Reference, " " + #TAB$)
			FoundReference()\Reference = RTrimChar(FoundReference()\Reference, #CRLF$)

			; >> first attempt to mark the selected word in the string
			FoundReference()\Reference = ReplaceString(FoundReference()\Reference, FoundReference()\Selregexp, #SelectedWordMarker$ + FoundReference()\Selregexp + #SelectedWordMarker$, #PB_String_NoCase)

			AddGadgetItem(#frmMain_References, -1, Str(FoundReference()\LineNo) + #LF$ + FoundReference()\Reference)
		Next

		SelectedWord = "regexp"
		SetWindowTitle(#frmMain, Str(ElapsedMilliseconds() - timer) + " ms, '"  + SelectedWord + "', Found " + " in " + Str(ListSize(FoundReference())) + " Lines")
	EndIf
EndProcedure


Procedure LookForWordUnderCursor()
	; LINK : http://www.purebasic.fr/english/viewtopic.php?f=12&t=37823
	Protected RegexLines, PbRegexTokens
	Protected CountLines, LineCounter, CountTokens, TokenCounter
	Protected Line.s, selWord.s, stx.s
	Protected Dim Tokens.s(0)

	RegexLines = CreateRegularExpression(#PB_Any , ".*\r?\n")
; 	RegexLines = CreateRegularExpression(#PB_Any , ".*(?=\r?\n)")
	PbRegexTokens = CreateRegularExpression(#PB_Any, #DOUBLEQUOTE$ + "[^" + #DOUBLEQUOTE$ + "]*" + #DOUBLEQUOTE$ + "|[\*]?[a-zA-Z_]+[\w]*[\x24]?|#[a-zA-Z_]+[\w]*[\x24]?|[\[\]\(\)\{\}]|[-+]?[0-9]*\.?[0-9]+|;.*|\.|\+|-|[&@!\\\/\*,\|]|::|:|\|<>|>>|<<|=>{1}|>={1}|<={1}|=<{1}|={1}|<{1}|>{1}|\x24+[0-9a-fA-F]+|\%[0-1]*|%|'")

	CountLines = CountString(ScintillaText, #CRLF$)

	CountLines = ExtractRegularExpression(RegexLines, ScintillaText, Lines())

	selWord = LCase(SelectedWord)  ; keep the original writing
	CountSelectedWords = 0		   ; init for new search
	
	
; 	MessageRequester("Lines", Str(ArraySize(Lines())))

	For LineCounter = 0 To CountLines - 1
		Line = Lines(LineCounter)

		;Debug "tokenize Line '" + Line + "'"

		CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens()) ; tokenize the line

		For TokenCounter = 0 To CountTokens - 1
			;Debug "  check Token '" + Tokens(TokenCounter) + "'"

			If selWord = LCase(Tokens(TokenCounter))
				AddElement(FoundReference())
				FoundReference()\LineNo = LineCounter + 1

				Line = Trim(Line)
				Line = Mid(Line, 1, Len(Line) - 2)  ; remove the #CRLF$

				CountSelectedWords + CountString(LCase(Line), selWord)   ; <-- count SelectedWord in the codeline

				FoundReference()\Reference = Line
				Break  ; only one line (evenn if there are more than one SelectedWord )
			EndIf
		Next TokenCounter
	Next LineCounter
; 	MessageRequester("FoundReference", Str(ListSize(FoundReference())))

	; because of #Constant or *Pointer
	If ListSize(FoundReference()) = 0
		For LineCounter = 0 To CountLines - 1
			Line = Lines(LineCounter)
			CountTokens = ExtractRegularExpression(PbRegexTokens, Line, Tokens())
			For TokenCounter = 0 To CountTokens - 1
				stx = LCase(Tokens(TokenCounter))
				If stx = "#" + selWord Or stx = "*" + selWord
					AddElement(FoundReference())
					FoundReference()\LineNo = LineCounter + 1

					Line = Trim(Line)
					Line = Mid(Line, 1, Len(Line) - 2)

					CountSelectedWords + CountString(LCase(Line), stx)  ; <-- count SelectedWord in the codeline

					FoundReference()\Reference = Line
					Break
				EndIf
			Next
		Next

		CompilerIf Not #PB_Compiler_Debugger
			If ListSize(FoundReference()) = 0 : End : EndIf
		CompilerEndIf
	EndIf
EndProcedure



; ---------------------------------------------------------------------------------------------------------------------
; XIncludeFile "ColorListIconGadget.pbi"  ; I prefer .pbi (instead of .pb)
; ---------------------------------------------------------------------------------------------------------------------

;... Create brushes for painting item background
Structure MYBRUSHES
	brushDefault.l
	brushSelected.l
EndStructure

; Global brush.MYBRUSHES
Global Dim Colors(1)

; brush\brushSelected = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
; brush\brushSelected = CreateSolidBrush_(GetSysColor_(#COLOR_INFOBK))
; brush\brushDefault = GetStockObject_(#WHITE_BRUSH)
; brush\brushSelected = ForeColor
; brush\brushDefault = BackColor


; ---== Color for Default Text and Selected Word ==--------------------------------------------------------------------


; Colors(0) = #Red                                ; the SelectedWord
Colors(0) = $8080FF                           ; the SelectedWord
											  ; Colors(1) = GetSysColor_(#COLOR_HIGHLIGHTTEXT)  ; the default text
											  ; Colors(1) = GetSysColor_(#COLOR_WINDOWTEXT); the default text
Colors(1) = ForeColor ; the default text


; ---== MainWindow Procedures ==---------------------------------------------------------------------------------------

Procedure Resize_Event()
	Protected wlv
	xywh\w = WindowWidth(#frmMain)
	xywh\h = WindowHeight(#frmMain)
	ResizeGadget(#cmbRex, #PB_Ignore, #PB_Ignore, xywh\w - 39, 30)
	ResizeGadget(#btnRex, xywh\w - 33, #PB_Ignore, #PB_Ignore, #PB_Ignore)
	ResizeGadget(#frmMain_References, #PB_Ignore, #PB_Ignore, xywh\w - 6, xywh\h - 38)
EndProcedure



; Procedure SendMessage2(x, y, w, h)
; EndProcedure

Procedure JumpToLine(SelectedLine)
	Protected Count
; 	SendMessage2(ScintillaHandle, #SCI_GOTOLINE, SelectedLine - 1, 0)
; 	Count = SendMessage2(ScintillaHandle, #SCI_LINESONSCREEN, 0, 0) / 2
; 	SendMessage2(ScintillaHandle, #SCI_SETFIRSTVISIBLELINE, SelectedLine - Count - 1, 0)
EndProcedure

Procedure Event_ListView()
	Protected SelectedLine
	SelectedLine = Val(GetGadgetItemText(#frmMain_References, GetGadgetState(#frmMain_References), 0))
	If SelectedLine > 0
		JumpToLine(SelectedLine)
	EndIf
EndProcedure

; ---------------------------------------------------------------------------------------------------------------------

Procedure main()
	Protected WWE ;, idx, pos, le
	Protected timer
	
	timer = ElapsedMilliseconds()

	Initialization()  ;
	LookForWordUnderCursor()

; 		MessageRequester(SelectedWord, ini$)
	;--> ini
	If OpenPreferences(ini$) ; открываем ini
		If PreferenceGroup("set")
			xywh\x = ReadPreferenceInteger("x", xywh\x)
			xywh\y = ReadPreferenceInteger("y", xywh\y)
			xywh\w = ReadPreferenceInteger("w", xywh\w)
			xywh\h = ReadPreferenceInteger("h", xywh\h)
		EndIf
		ClosePreferences()
	EndIf
	If xywh\x = 0 And xywh\y = 0
		centered = #PB_Window_ScreenCentered
	EndIf
	CopyStructure(@xywh, @xywh2, xywhm)


	;- GUI
	If OpenWindow(#frmMain, xywh\x, xywh\y, xywh\w, xywh\h,
	              Str(ElapsedMilliseconds() - timer) + " ms, '" + SelectedWord + "', Found " + CountSelectedWords + " in " + Str(ListSize(FoundReference())) + " Lines",
	              #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | centered)
		SetWindowColor(#frmMain, BackColor)
		StickyWindow(#frmMain, #True)

		ComboBoxGadget(#cmbRex, 3, 3, 30, 30, #PB_ComboBox_Editable)
		ResizeGadget(#cmbRex, #PB_Ignore, #PB_Ignore, WindowWidth(#frmMain) - 39, 30)
		;ComboBoxGadget(#cmbRex, 3, 3, WindowWidth(#frmMain) - 60, 24, #PB_ComboBox_Editable)
		AddGadgetItem(#cmbRex, -1, "(?# Debug, All )\bDebug\b")
		AddGadgetItem(#cmbRex, -1, "(?# Debug, real )(?m)^\h*\KDebug\b")
		AddGadgetItem(#cmbRex, -1, "(?# WinAPI )(?mi)[a-z][\da-z]*_(?=\h*\()")
		AddGadgetItem(#cmbRex, -1, "(?# Link )https?://[\w.:]+/?(?:[\w/?&=.~;\+!*_#%-]+)")
		AddGadgetItem(#cmbRex, -1, "(?# Procedure )(?mi)^\h*(?:Procedure[CDL$]{0,5}?(?:\h*\.[abcdfilqsuw])?\h+\K)[A-Za-z_]\w*\h*(?=\()")
		AddGadgetItem(#cmbRex, -1, "(?# Macro )(?mi)^\h*Macro\h+\K[A-Za-z_]\w*\h*(?=\()")
		AddGadgetItem(#cmbRex, -1, "(?# Var$ )(?<![#@\w])\w+\$")
		AddGadgetItem(#cmbRex, -1, "(?# @*Point, whole )[@*]{1,2}\w+\b\$?(?![\\.(])")
		AddGadgetItem(#cmbRex, -1, "(?# @*Point, var)[@*]{1,2}\w+(?!\()")
		AddGadgetItem(#cmbRex, -1, "(?# @Point, Procedure)@\w+\(\)")
		AddGadgetItem(#cmbRex, -1, "(?# Hex num )(?i)\$[\da-f]+")
		AddGadgetItem(#cmbRex, -1, "(?# Comments )(?m)^\h*\K;.*?(?=\r?$)")
		#q$ = Chr(34)
		AddGadgetItem(#cmbRex, -1, "(?# Comments, All )(?m)^(?:[^" + #q$ + ";]*" + #q$ + "[^" + #q$ + "]*?" + #q$ + ")*[^" + #q$ + ";]*(;.*?)(?=\r?$)")
		AddGadgetItem(#cmbRex, -1, "(?# Structures, Declare )(?i)(?<![=\w" + #q$ + "\\./-])[a-z]\w*\.[a-z]\w+(?![\w" + #q$ + "\\./-])")
		AddGadgetItem(#cmbRex, -1, "(?# Structures, item )(?<![\w.:" + #q$ + "\\])\*?\w+(?:(?:\(\))?\\[\d_a-zA-Z]+)+(?![\w" + #q$ + "\\])")
		AddGadgetItem(#cmbRex, -1, "(?# Structures, Content )(?m)^\h*Structure\h*\K\w+")
		; 		AddGadgetItem(#cmbRex, -1, ~"(?# Comments )(?m)^(?:[^\";]*\"[^\"]*?\")*[^\";]*(;.*?)(?=\r?$)")
		; 		AddGadgetItem(#cmbRex, -1, ~"(?# Structures, Declare )(?i)(?<![=\\w\"\\./-])[a-z]\\w*\\.[a-z]\\w+(?![\\w\"\\\\./-])")
		; 		AddGadgetItem(#cmbRex, -1, ~"(?# Structures, item )(?<![\\w.:\"\\\\])\\*?\\w+(?:(?:\\(\\))?\\\\[\\d_a-zA-Z]+)+(?![\\w\"\\\\])")
		AddGadgetItem(#cmbRex, -1, "(?# Types )\b\w+\.[sfdqbliwcapu]\b")
		AddGadgetItem(#cmbRex, -1, "(?# Constants, Declare )(?m)^\h*\K#\w+\$?(?=\h*(?:=|\r?$))")
		AddGadgetItem(#cmbRex, -1, "(?# Constants, All )#\w+\b\$?")
		AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, DECLARE )(?m)^\h*\K#[A-Z\d_]+(?=\h*(?:=|\r?$))")
		AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, ALL )#[A-Z\d_]+\b")
		AddGadgetItem(#cmbRex, -1, "(?# CONSTANTS, X_X )#[A-Z\d]+_[A-Z\d]+\b")
		AddGadgetItem(#cmbRex, -1, "(?# Constants, #PB_ )#PB_\w+\b\$?")
		AddGadgetItem(#cmbRex, -1, "(?# Constants, Str )#\w+\$")
		AddGadgetItem(#cmbRex, -1, "(?# If )(?mi)^\h*\KIf(?=\h)")
		AddGadgetItem(#cmbRex, -1, "(?# Loop )(?mi)^\h*\K(For(Each)?|Repeat|While)(?=\h)")
		AddGadgetItem(#cmbRex, -1, "(?# Select )(?mi)^\h*\KSelect(?=\h)")
		AddGadgetItem(#cmbRex, -1, "(?# Include )(?mi)^\h*\KX?Include[a-z]{4,6}\b(?=\h)")

; 		ButtonGadget(#btnRex, WindowWidth(#frmMain) - 28, 3, 24, 24, ">")
; 		ButtonImageGadget(#btnRex, WindowWidth(#frmMain) - 28, 3, 24, 24, GetClassLongPtr_(WindowID(#frmMain), #GCL_HICONSM))

		#img = 0
; 		Protected tmp = GadgetHeight(#cmbRex)
		Protected tmp = 30
		If CreateImage(#img, tmp, tmp, 32, RGB(255, 255, 255))
			StartDrawing(ImageOutput(#img))
			Box(0, 0, tmp, tmp, BorderColor)
			Box(1, 1, tmp - 2, tmp - 2, BackColorHeader)
			DrawText((tmp - TextWidth(">")) / 2, (tmp - TextHeight(">")) / 2, ">", ForeColor, BackColorHeader)
			StopDrawing()
		EndIf
		ImageGadget(#btnRex, WindowWidth(#frmMain) - 33, 3, tmp, tmp, ImageID(0))
; 	    ButtonImageGadget(#btnRex, WindowWidth(#frmMain) - 28, 3, 24, 24, ImageID(0))
; 		CatchImage(0, GetClassLongPtr_(WindowID(#frmMain), #GCL_HICONSM))
; 		ButtonImageGadget(#btnRex, WindowWidth(#frmMain) - 28, 3, 24, 24, ImageID(0))
		; ButtonGadget(#btnClose, WindowWidth(#frmMain) - 27, 3, 24, 24, "x") ; to make a black theme
		
		
; 		MessageRequester("CursorLine", Str(CursorLine))
		If CursorLine < 1 Or CursorLine > ArraySize(Lines())
			CursorLine = 1
		EndIf
		ListIconGadget(#frmMain_References, 3, 35, WindowWidth(#frmMain) - 6, WindowHeight(#frmMain) - 38, Str(CursorLine), 55, #PB_ListIcon_FullRowSelect | #PB_ListIcon_GridLines | #PB_ListIcon_AlwaysShowSelection)
		; 		SetWindowLongPtr_(GadgetID(#frmMain_References),#GWL_STYLE,GetWindowLongPtr_(GadgetID(#frmMain_References),#GWL_STYLE) | #LVS_NOCOLUMNHEADER)

		AddGadgetColumn(#frmMain_References, 1, LTrimChar(RTrimChar(Lines(CursorLine - 1), #CRLF$), " " + #TAB$), 400)
		SetGadgetColor(#frmMain_References, #PB_Gadget_BackColor, BackColor)
		SetGadgetColor(#frmMain_References, #PB_Gadget_FrontColor, ForeColor)

		ForEach FoundReference()
			FoundReference()\Reference = LTrimChar(FoundReference()\Reference, " " + #TAB$)

			; >> first attempt to mark the selected word in the string
			FoundReference()\Reference = ReplaceString(FoundReference()\Reference, SelectedWord, #SelectedWordMarker$ + SelectedWord + #SelectedWordMarker$, #PB_String_NoCase)

			AddGadgetItem(#frmMain_References, -1, Str(FoundReference()\LineNo) + #LF$ + FoundReference()\Reference)
		Next



		AddKeyboardShortcut(#frmMain, #PB_Shortcut_Escape, #frmMain_Shortcut_Escape_Event)
		BindEvent(#PB_Event_SizeWindow, @Resize_Event(), #frmMain)
; 		BindGadgetEvent(#frmMain_References, @Event_ListView())
		SetActiveGadget(#frmMain_References)

		AddKeyboardShortcut(#frmMain, #PB_Shortcut_Control | #PB_Shortcut_Shift | #PB_Shortcut_C, #Shortcut_Ctrl_Shift_C)
		AddKeyboardShortcut(#frmMain, #PB_Shortcut_Return, #Shortcut_Enter)

;- Loop
		Repeat
			Select WaitWindowEvent()
				Case #PB_Event_MoveWindow
					xywh\x = WindowX(#frmMain)
					xywh\y = WindowY(#frmMain)
				Case #PB_Event_CloseWindow
; 					Если размеры окна изменились, то сохраняем.
					If Not CompareMemory(@xywh, @xywh2, SizeOf(xywhm))
						If OpenPreferences(ini$) Or CreatePreferences(ini$)
							PreferenceGroup("set")
							WritePreferenceInteger("x", xywh\x)
							WritePreferenceInteger("y", xywh\y)
							WritePreferenceInteger("w", xywh\w)
							WritePreferenceInteger("h", xywh\h)
							ClosePreferences()
						EndIf
					EndIf
					Break
				Case #PB_Event_Menu
					Select EventMenu()
						Case #Shortcut_Enter
							If GetActiveGadget() = #cmbRex
								flgRead = 0
								GoRegExp()
							EndIf
							If GetActiveGadget() = #frmMain_References
								Event_ListView()
							EndIf
						Case #Shortcut_Ctrl_Shift_C
							CopyClipboard()
						Case #frmMain_Shortcut_Escape_Event
							Break
					EndSelect
				Case #PB_Event_Gadget
					Select EventGadget()
						Case #cmbRex
							If EventType() = #PB_EventType_Change
								flgRead = 0
								GoRegExp()
							EndIf
						Case #btnRex
							GoRegExp()
					EndSelect
			EndSelect
		ForEver

	EndIf
	ProcedureReturn 0  ; not necessary, but looks good/better
EndProcedure

End main()

;- Bottom of File
Mesa
Enthusiast
Enthusiast
Posts: 345
Joined: Fri Feb 24, 2012 10:19 am

Re: Show all occurrences of a word in the IDE

Post by Mesa »

In the first post, i've added my final version with the use of a scintilla gadget and your own PB settings.

Image

Mesa.
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Fix for "Loop" for not finding "Repeat" which doesn't require a subexpression. I didn't find window event loops so I added "*".

Code: Select all

; old
AddGadgetItem(#cmbRex, -1, "(?# Loop )(?mi)^\h*\K(For(Each)?|Repeat|While)(?=\h)")
; new
AddGadgetItem(#cmbRex, -1, "(?# Loop )(?mi)^\h*\K(For(Each)?|Repeat|While)(?=\h*)")
Mesa
Interesting, but there are drawbacks:
1. Highlight matches more clearly by specifying a lower percentage of transparency.
2. In the first line, add a link to return to the starting point from which the search was called.
3. After the second launch, the cursor starts blinking, then an arrow, then a text cursor, even if the mouse is on the window title bar.

Another idea, if the cursor leaves the tool window, then the window is hidden, and when the cursor moves to the left border of the screen, the window should appear again. Under these conditions, the window must have one process, otherwise there will be many open windows.

I tried restarting the process to avoid duplicating windows. Works fine.

Code: Select all

Global FAR
Global classText1.s = Space(256)

Procedure.l enumChildrenFAR(hwnd.l)
	If hwnd
		GetClassName_(hwnd, @classText1, 256)
		If classText1 = "WindowClass_0"
			FAR = hwnd
			ProcedureReturn 0
		EndIf
		ProcedureReturn 1
	EndIf
	ProcedureReturn 0
EndProcedure

Procedure ClosePrevWindow()
	Protected processId
	Protected *a = CreateSemaphore_(#Null, 0, 1, "FAR459317")
	If *a And GetLastError_() = #ERROR_ALREADY_EXISTS
		EnumChildWindows_(0, @enumChildrenFAR(), 0)
		If FAR
			; 		SendMessage_(FAR, #WM_CLOSE, 0, 0)
			GetWindowThreadProcessId_(FAR, @processId)
			If processId
				; 			MessageRequester("", Str(processId))
				RunProgram("taskkill.exe", "/F /PID " + processId, "", #PB_Program_Wait | #PB_Program_Hide)
				; 			KillProgram(processId)
				CloseHandle_(*a)
				*a = CreateSemaphore_(#Null, 0, 1, "FAR459317")
			EndIf
		EndIf
	EndIf
	classText1 = ""
EndProcedure
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Updated the archives in the 3rd post on this page.
Added window hiding. Move the cursor to the right to the edge of the screen to display the pop-up window.
Added restart on repeated calls.

Updated, at the first start the window is held for 2 seconds.

Fixed - accurate positioning, reveals collapsed code snippets.
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Updated the archives in the 3rd post on this page.
The ini file supports a color for highlighting the found entry and an auto-hide flag
Added context menu with 5 items (Copy, Autohide, Next color, ini, Exit)
When launched, the search word is inserted as a regular expression to make the search also in comments.
Axolotl
Enthusiast
Enthusiast
Posts: 435
Joined: Wed Dec 31, 2008 3:36 pm

Re: Show all occurrences of a word in the IDE

Post by Axolotl »

Hey AZJIO,

when searching for a PB App, using the classname is only reliable if you make sure that the classname you are looking for is correct.
For example, the classname for me is always different (WindowClass_0, WindowClass_1 or WindowClass_2).
Why? -- no idea.

My solution if I want to use the classname: I always check/debug the classname after OpenWindow(..) to be sure.
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Axolotl wrote: Fri Mar 17, 2023 2:19 pm WindowClass_0
1. I checked several programs and they all had WindowClass_0. From this I concluded that this is the default. Perhaps for the next created window in the same program there will be a value of WindowClass_1, this would be logical.
2. I googled the possibility of changing the window class, it turned out to be possible only once. That is, you need to create a window using WinAPI.
3. When testing, I ran several of my programs so that there were many WindowClass_0 classes, but when you activate the IDE window to call the hotkey, the child programs created by it become higher in the queue and the program kills the PID of the window only FindAllReferences. When testing, I never encountered a problem.
4. If there is a problem, then I have a fallback - find the elements of the window, for example Button1, determine the number of elements, or create a hidden empty button with a specific name in the window.

I played around with Linux a bit and added the source to the archive. But there is no line jump and highlighting. I am only getting a list of strings.

I forgot to report another update, now when searching with a regular expression there are no duplicate lines.
Axolotl
Enthusiast
Enthusiast
Posts: 435
Joined: Wed Dec 31, 2008 3:36 pm

Re: Show all occurrences of a word in the IDE

Post by Axolotl »

On my system, all created PB Apps have the classname WindowClass_1.
As written, I have never questioned this, but simply noticed that the value is not constant.

Another possibility is of course to keep the first characters in the window title constant and search for them....
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Updated archives.

Code: Select all

#Title = Chr($25CF) + Chr(160)

Procedure.l enumChildrenFAR(hwnd.l)
	If hwnd
		GetWindowText_(hwnd, @classText1, 256)
		If Left(classText1, 2) = #Title
			GetClassName_(hwnd, @classText1, 256)
			If Left(classText1, 12) = "WindowClass_"
				FAR = hwnd
				ProcedureReturn 0
			EndIf
			ProcedureReturn 1
		EndIf
		ProcedureReturn 1
	EndIf
	ProcedureReturn 0
EndProcedure
AZJIO
Addict
Addict
Posts: 1313
Joined: Sun May 14, 2017 1:48 am

Re: Show all occurrences of a word in the IDE

Post by AZJIO »

Download: yandex, upload.ee
Update
Improved regular expressions, which simplified the code and increased the speed by almost 2 times.
Fixed word search calculation. Now counts and highlights only whole words, as it should be.

The regex for getting strings was not getting the last string. Spaces and tabs at the beginning of lines are now removed immediately when lines are captured by a regular expression "^\h*\K.+(?=\r?$)". The token regex was not capturing strings with tilde "~" correctly, now fixed. I combined some tokens into a group, for example, why do we need to search for the [<>=] + operators separately. But it did not work so that these tokens did not fall into the array.

Here is the regular expression broken down into captured tokens.

Code: Select all

~".+"|
"[^"]*"|
[\*]?[a-zA-Z_]+[\w]*[\x24]?|
#[a-zA-Z_]+[\w]*[\x24]?|
[\[\]\(\)\{\}]+|
[-+]?[0-9]*\.?[0-9]+|
;.*|
[.+-]|
[&@!\\\/\*,\|]|
[:\\]+|
[<>=]+|
\x24+[0-9a-fA-F]+|
\%[0-1]*|
%|
'
Line count is not token count, so fixed. I found this by comparing the search for the same word with a regular expression (\bScintillaText\b). It didn't match the list of highlighted words.

Code: Select all

CountSelectedWords + CountString(LCase(Lines(L)), selWord)
There is still a discrepancy in the regular expressions. Counts the number of occurrences correctly, but highlights the match using ReplaceString(). To fix this you need to support references to groups in regular expressions, which makes the code more complicated.

By the way, using \SDK\Syntax Highlighting\SyntaxHighlighting.dll I think it will speed up the process, since the tokens there have a type and you can exclude operators, comments, quoted strings and other tokens that do not correspond to the type.
Last edited by AZJIO on Wed Mar 22, 2023 4:44 pm, edited 2 times in total.
Post Reply