Seite 1 von 4
PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 08.08.2014 17:53
von Kiffi
Hallo,
mich hat schon immer gestört, dass man nicht auf einen Blick sehen kann, in welcher Procedure man sich befindet.
Aus diesem Grund hier folgender Code, den man zu einem PB-Tool kompilieren kann. Wird dieses Tool aufgerufen (ich habe es mir auf das Tastaturkürzel Shift + Ctrl + P gelegt), so wird die der Name der aktuellen Procedure mittels MessageRequester ausgegeben:
Bitte beachten: In den Werkzeug-Einstellungen als Argument "%TEMPFILE" eintragen
Code: Alles auswählen
; GetProcedureName
; #################################################################
; In den Werkzeug-Einstellungen als Argumente "%TEMPFILE" eintragen
; #################################################################
EnableExplicit
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()
; thx to sicro (http://www.purebasic.fr/german/viewtopic.php?p=324916#p324916)
Protected ReturnValue.s
Protected FilePath.s
Protected File, BOM
FilePath = ProgramParameter(0) ; %TEMPFILE (Datei existiert auch, wenn Code nicht gespeichert ist)
File = ReadFile(#PB_Any, FilePath, #PB_File_SharedRead)
If IsFile(File)
BOM = ReadStringFormat(File) ; BOM überspringen, wenn vorhanden
ReturnValue = ReadString(File, #PB_File_IgnoreEOL | BOM)
CloseFile(File)
EndIf
ProcedureReturn ReturnValue
EndProcedure
Define ScintillaText.s
Define CursorLine = Val(StringField(GetEnvironmentVariable("PB_TOOL_Cursor"), 1, "x"))
Define Line.s
Define LineCounter
ScintillaText = GetScintillaText()
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
#LineFeed = #CRLF$
CompilerDefault
#LineFeed = #LF$
CompilerEndSelect
If ScintillaText <> ""
For LineCounter = CursorLine - 1 To 1 Step - 1
Line = RemoveLeadingWhitespaceFromString(StringField(ScintillaText, LineCounter, #LineFeed))
If Left(LCase(Line), Len("endprocedure")) = "endprocedure"
Break
EndIf
If Left(LCase(Line), Len("procedure")) = "procedure"
If Left(LCase(Line), Len("procedurereturn")) <> "procedurereturn"
MessageRequester("You are here:", Line)
Break
EndIf
EndIf
Next
EndIf
Grüße ... Kiffi
Edit: Verbesserungsvorschläge von Sicro implementiert. Danke dafür!
Verfasst: 20.08.2014 21:05
von CodeCommander
Dein Tool stürzt mit IMA bei Zeile 42 ab.
Feedback zum Code: Was mir auffiel:
1. Die Variablenbenennung ist nicht einheitlich. Mal schreibst du am Anfang groß und dann doch wieder klein.
2.
Das mit <> "" brauchst du nicht und ist unnötig. Es reicht schon wen du so abfragst:
Genauso mit If ScintillaText <> "" --> If ScintillaText
3. Du benutzt sehr viele String Funktionen. Besser und schneller wäre es wenn du reguläre Ausdrücke benutzt weils viel schneller ist als tausende String Funktionen.
Re: PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 20.08.2014 22:27
von c4s
Kiffi hat geschrieben:mich hat schon immer gestört, dass man nicht auf einen Blick sehen kann, in welcher Procedure man sich befindet.
Gute Idee, denn das "Problem" kenne ich auch!
Ich habe auch gleich einen Feature-Request

: Das Ergebnis direkt in der Compiler-Statusliste ausgeben. Der offensichtliche Vorteil ist, dass es sich noch integrierter anfühlt. Ich meine mich zu erinnern, dass der Quellcode von "Dead Procedure Remover" (von Danilo,
hier) einen Trick/Workaround dafür besitzt. Vielleicht hast du Lust es dir mal anzusehen. Andernfalls werde ich es morgen mal probieren.
Re: PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 20.08.2014 22:33
von NeoChris
Kiffi hat geschrieben:mich hat schon immer gestört, dass man nicht auf einen Blick sehen kann, in welcher Procedure man sich befindet.
Wie muss ich mir das vorstellen? Du musst doch wissen in welcher Procedure du gerade codest? Warum soll man nicht (mehr? Alzheimer?) wissen in welcher Procedure man sich befindet? Oder hast du solche übertriebene langen Proceduren? Wenn ja dann hast du ein sehr schlechtes Code Design. Teile diese doch in mehreren kleineren so das es für dich übersichtlicher ist.
Re: PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 20.08.2014 23:32
von Shardik
CodeCommander hat geschrieben:2.
Das mit <> "" brauchst du nicht und ist unnötig. Es reicht schon wen du so abfragst:
Genauso mit If ScintillaText <> "" --> If ScintillaText
Kiffi ist lediglich vorsichtig, weil
die von Fred empfohlene Schreibweise ist. Denn seit PB 5.00 Beta 7 ist schon die frühere Möglichlichkeit, mit
zu testen, ob der String Test.s leer ist, nicht mehr möglich:
http://www.purebasic.fr/english/viewtop ... 13&t=51880
Daher könnte es durchaus sein, dass irgendwann einmal auch
nicht mehr funktionieren könnte. Mit Kiffis Methode ist man daher immer auf der sicheren Seite...

Verfasst: 20.08.2014 23:38
von CodeCommander
Danke Shardik für deine kompetente Antwort und den Link

Sehr interessant und informativ und ich werde absofort auch mit <> "" abrprüfen ob ein String ungleich leer ist.
Dann hat sich meine Frage an Kifi erledigt.

Re: PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 20.08.2014 23:40
von c4s
NeoChris hat geschrieben:Du musst doch wissen in welcher Procedure du gerade codest? [...] Oder hast du solche übertriebene langen Proceduren? Wenn ja dann hast du ein sehr schlechtes Code Design.
Mit schlechtem Programmierstil hat dies überhaupt nichts zu tun. Eine einzelne Prozedur kann, darf und ist in der Praxis durchaus länger als ca. 40 Zeilen (d.h. der sichtbare Bereich).
Zumindest für mich wäre folgendes ein häufiger Anwendungsfall: Wenn du ein oder sogar mehrere Quelltexte gleichzeitig nach Schlüsselwörtern durchsucht kann es vorkommen, dass der Kontext des Fundes nicht sofort ersichtlich ist. Anstatt nun mühselig hoch scrollen zu müssen bis der Prozedurname sichtbar wird (und dann wieder zurück zur Fundstelle), kann dieses Tool einem sofort weiterhelfen.
Re: PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 20.08.2014 23:50
von NeoChris
Ahhhh danke jetzt weiß ich Bescheid. Daran habe ich noch gar nicht gedacht. Dann ergibt es natürlich Sinn. Danke

Re: PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 21.08.2014 13:32
von c4s
@NeoChris
Ein weiterer Anwendungsfall ergibt sich mit dem neuen Issue-Feature: Bei Doppelklick auf einen Eintrag springt man sofort zur jeweiligen Zeile im Code - auch hier kann der Prozedurname nicht sofort ersichtlich sein.
c4s hat geschrieben:[...] Ergebnis direkt in der Compiler-Statusliste ausgeben. [...] Vielleicht hast du Lust es dir mal anzusehen. Andernfalls werde ich es morgen mal probieren.
Ein kurzer Test hat gezeigt, dass Danilos Trick mit PB 5.30 ohne (mir unbekannte) Anpassungen leider nicht mehr funktioniert. Es wird wohl an der neuen Unicode-IDE bzw. den damit zusammenhängenden internen Änderungen liegen, denn mit PB 5.22 funktioniert es. Hier ist der Code, der "test" als Statusmeldung ausgeben sollte:
Code: Alles auswählen
EnableExplicit
Global regExPBIDEwin = CreateRegularExpression(#PB_Any, "^PureBasic ([0-9])+(\056)+([0-9])+ (LTS )*\((x86|x64)+\)", #PB_RegularExpression_NoCase)
Global gMainWindow.i = Val( GetEnvironmentVariable("PB_TOOL_MainWindow") )
Global gListBox.i = 0
Procedure EnumWindowsProc(hwnd, lParam)
Protected.s windowname, classname
If hwnd
windowname = Space(1024*10)
GetWindowText_(hwnd, @windowname, 1024*10)
windowname = PeekS(@windowname, -1)
If windowname <> ""
If MatchRegularExpression(regExPBIDEwin, windowname)
classname = Space(1024)
GetClassName_(hwnd, @classname, 1024)
If Left(classname, 11) = "WindowClass"
gMainWindow = hwnd
ProcedureReturn #False
EndIf
EndIf
EndIf
EndIf
ProcedureReturn #True
EndProcedure
Procedure EnumChildProc(hwnd, lParam)
Protected.s windowname, classname, classname2
classname = Space(1024)
GetClassName_(hwnd, @classname, 1024)
If FindString(classname, "ListBox") <> 0
windowname = Space(1024)
SendMessage_(hwnd, #WM_GETTEXT, 1024, @windowname)
windowname = PeekS(@windowname, -1, #PB_UTF8)
classname2 = Space(1024)
GetClassName_(GetParent_(hwnd), @classname2, 1024)
If FindString(classname2, "Window")
gListBox = hwnd
ProcedureReturn #False
EndIf
EndIf
ProcedureReturn #True
EndProcedure
Procedure AddStatusMessage(msg.s)
If gListBox
SendMessage_(gListBox, #LB_ADDSTRING, 0, @msg)
SendMessage_(gListBox, #LB_SETTOPINDEX, SendMessage_(gListBox, #LB_GETCOUNT, 0, 0) -1, 0)
EndIf
EndProcedure
If gMainWindow = 0
EnumWindows_(@EnumWindowsProc(), 0)
EndIf
If gMainWindow
EnumChildWindows_(gMainWindow, @EnumChildProc(), 0)
EndIf
AddStatusMessage("test")
Re: PB-Tool: Namen der aktuellen Procedure ausgeben lassen
Verfasst: 21.08.2014 13:42
von Sicro
So funktioniert es unter Windows, Linux und sicherlich auch unter MacOS:
Code: Alles auswählen
; GetProcedureName
; #################################################################
; In den Werkzeug-Einstellungen als Argumente "%TEMPFILE" eintragen
; #################################################################
EnableExplicit
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 FilePath.s
Protected File
FilePath = ProgramParameter(0) ; %TEMPFILE (Datei existiert auch, wenn Code nicht gespeichert ist)
File = ReadFile(#PB_Any, FilePath, #PB_File_SharedRead)
If IsFile(File)
ReadStringFormat(File) ; BOM überspringen, wenn vorhanden
ReturnValue = ReadString(File, #PB_File_IgnoreEOL | #PB_UTF8)
CloseFile(File)
EndIf
ProcedureReturn ReturnValue
EndProcedure
Define ScintillaText.s
Define CursorLine = Val(StringField(GetEnvironmentVariable("PB_TOOL_Cursor"), 1, "x"))
Define Line.s
Define LineCounter
ScintillaText = GetScintillaText()
If ScintillaText <> ""
For LineCounter = CursorLine - 1 To 1 Step - 1
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
#LineFeed = #CRLF$
CompilerDefault
#LineFeed = #LF$
CompilerEndSelect
Line = RemoveLeadingWhitespaceFromString(StringField(ScintillaText, LineCounter, #LineFeed))
If Left(LCase(Line), Len("endprocedure")) = "endprocedure"
Break
EndIf
If Left(LCase(Line), Len("procedure")) = "procedure"
If Left(LCase(Line), Len("procedurereturn")) <> "procedurereturn"
MessageRequester("You are here:", Line)
Break
EndIf
EndIf
Next
EndIf