PB-Tool: Alle Verweise finden

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

PB-Tool: Alle Verweise finden

Beitrag von Kiffi »

Hallo,

im Visual Studio kann man mit der rechten Maustaste auf eine Variable oder eine Prozedur klicken und im dann aufklappenden Menü auf "Alle Verweise finden" klicken, um alle Codezeilen aufgelistet zu bekommen, die den angeklickten Suchbegriff enthalten.

Hier ist so was ähnliches für PureBasic, welches als PB-Tool eingerichtet werden kann (leider unterstützt die PB-IDE das nicht über das Popup-Menü der Maus, aber mit einem Keyboard-Shortcut eingerichtet ist funktioniert es auch ganz komfortabel.)

Bild

Code: Alles auswählen

; FindAllReferences

EnableExplicit

Enumeration ; Windows
	#frmMain
EndEnumeration
Enumeration ; Gadgets
	#frmMain_References
EndEnumeration
Enumeration ; Menu-/Toolbaritems
	#frmMain_Shortcut_Escape_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
			FoundReference()\Reference = Line
		EndIf
	Next
	
Next

If ListSize(FoundReference()) = 0 : End : EndIf

OpenWindow(#frmMain, 
           #PB_Ignore,
           #PB_Ignore, 
           600,
           300,
           "All references for: '" + SelectedWord + "'",
           #PB_Window_SystemMenu | 
           #PB_Window_SizeGadget | 
           #PB_Window_ScreenCentered)

StickyWindow(#frmMain, #True)

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

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

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

AddKeyboardShortcut(#frmMain, #PB_Shortcut_Escape, #frmMain_Shortcut_Escape_Event)
BindEvent(#PB_Event_SizeWindow, @frmMain_SizeWindow_Event(), #frmMain)
BindGadgetEvent(#frmMain_References, @frmMain_References_Event())
SetActiveGadget(#frmMain_References)

Repeat
	
	WWE = WaitWindowEvent()
	
	If (WWE = #PB_Event_Menu And EventMenu() = #frmMain_Shortcut_Escape_Event) Or (WWE = #PB_Event_CloseWindow)
		Break
	EndIf
	
ForEver
Grüße ... Peter

P.S.: Der Gültigkeitsbereich von Variablen wird noch nicht beachtet. Vielleicht baue ich das später mal ein...

// Edit:

* Zeilenfehler behoben. (c4s)
* Groß- und Kleinschreibung wird jetzt nicht mehr beachtet. (Nino)
Zuletzt geändert von Kiffi am 19.08.2014 14:01, insgesamt 2-mal geändert.
a²+b²=mc²
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: PB-Tool: Alle Verweise finden

Beitrag von RSBasic »

Super Idee. :allright:
So ein Tool stand sogar in meiner ToDo-Liste, welches ich gerne umsetzen wollte, aber hat sich nun erledigt.
Danke fürs Schreiben und Bereitstellen. :allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Rings
Beiträge: 977
Registriert: 29.08.2004 08:48

Re: PB-Tool: Alle Verweise finden

Beitrag von Rings »

Danke fürs teilen, sehr hilfreich !
Rings hat geschrieben:ziert sich nich beim zitieren
c4s
Beiträge: 1235
Registriert: 19.09.2007 22:18

Re: PB-Tool: Alle Verweise finden

Beitrag von c4s »

Danke! :allright:

Kleines Problem: Bei mir ist jedes Ergebnis eine Zeile zu "früh", d.h. der Fund ist bspw. in Zeile 11 wird aber als 10 angezeigt (und springt dann auch zu 10). Ist das bei euch nicht der Fall?
"Menschenskinder, das Niveau dieses Forums singt schon wieder!" — GronkhLP ||| "ich hogffe ihr könnt den fehle endecken" — Marvin133 ||| "Ideoten gibts ..." — computerfreak ||| "Jup, danke. Gruss" — funkheld
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: PB-Tool: Alle Verweise finden

Beitrag von Kiffi »

@c4s: ups, ja, ein Fehler (habe ich oben korrigiert).

Bitte folgende Zeile:

Code: Alles auswählen

FoundReference()\LineNo = LineCounter
in dieses hier ändern:

Code: Alles auswählen

FoundReference()\LineNo = LineCounter + 1
Danke für den Hinweis & Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: PB-Tool: Alle Verweise finden

Beitrag von NicTheQuick »

Oh, ich merke gerade, dass das ja gar nicht unter Linux geht. :cry:
Benutzeravatar
Tommy
Spassvogel
Beiträge: 319
Registriert: 17.10.2013 14:36

Re: PB-Tool: Alle Verweise finden

Beitrag von Tommy »

Tolles Tool :allright:
@NickTheQuick: Nicht gleich aufgeben. :D
Man kann es doch konvertieren. Man muss nur die GTK APIs für Process und Scintilla finden und nutzen.
Dann geht es auch unter Linux. :)
Da du Linuxer bist kannst du auch gleich damit anfangen dann können auch die anderen 3 Linuxer nutzen.
Viel Glück :D
Zuletzt geändert von Tommy am 27.01.2015 11:06, insgesamt 2-mal geändert.
PB 5.41 x64
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: PB-Tool: Alle Verweise finden

Beitrag von Nino »

Schönes Tool, vielen Dank! :allright:

Zur Zeit wird beim Vergleich ja Groß- und Kleinschreibung berücksichtigt.
Ich schreibe in der Regel meine Identifizierer auch einheitlich, also z.B. nicht mal "Foo" und mal "foO", einfach weil das schöner aussieht. Da man sich aber auch mal vertippen kann und dem PB-Compiler die Groß- und Kleinschreibung egal ist, wäre evtl. zu überlegen, Zeile 121 zu ändern:

Code: Alles auswählen

If LCase(SelectedWord) = LCase(Tokens(TokenCounter))
( Gut, LCase(SelectedWord) besser nur 1x außerhalb der Schleife. ;-) )
P.S.: Der Gültigkeitsbereich von Variablen wird noch nicht beachtet. Vielleicht baue ich das später mal ein...
Das wäre natürlich nicht schlecht. :-)

Danke nochmal!
Benutzeravatar
dige
Beiträge: 1235
Registriert: 08.09.2004 08:53

Re: PB-Tool: Alle Verweise finden

Beitrag von dige »

Danke Kiffi, das ist sehr nützlich!
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: PB-Tool: Alle Verweise finden

Beitrag von NicTheQuick »

Tommy hat geschrieben:@NickTheQuick: Nicht gleich aufgeben. :D
Man kann es doch konvertieren. Man muss nur die GTK APIs für Process und Scintilla finden und nutzen.
Dann geht es auch unter Linux. :)
Da du Linuxer bist kannst du auch gleich damit anfangen dann können auch die anderen 3 Linuxer nutzen.
Viel Glück :D
Das hat nichts mit Glück zu tun. Bei manch anderen hier vielleicht schon, aber bei mir zumindest nicht. <)
Momentan bin ich nur etwas faul und hab außerdem wenig Zeit. Und so wichtig ist mir dieses Tool jetzt auch nicht. ;)

Aber ich hätte einen Verbesserungsvorschlag.
Ich würde das Fenster zunächst rahmenlos machen. Sobald man mit dem Mauszeiger darüber fährt, sollte sich eine Möglichkeit einblenden es sticky zu machen, sodass man es irgendwo hin schieben kann und es immer sichtbar bleibt, falls man öfter hin und her springen möchte.

PS.: Wieso schreiben mich hier eigentlich so viele immer falsch? :?
Antworten