Thank you for this wonderful idea.
I played with your code. I was able to simplify it in a lot of cases and I think I made it more robust to find labels. It now also finds functions.
Code:
/*
PSPad Label Helper
==================
by evl www.autohotkey.com/forum/viewtopic.php?t=&p=48986#48986
mod by toralf
Hotkey = F12
Shows/hides a listview of all labels in the active PSPad window.
- Double-click the label name to go to the line in PSPad.
*/
#Persistent
#SingleInstance force
Return
#IfWinActive, ahk_class TfPSPad
F12:: GoSub, PSPad_Labels_Gui
PSPad_Labels_Gui:
WinGet, PSPadWindowID, ID, A ;remember PSPadWindow to get back to it
Gui, Destroy ;destroy old instances
Fill_ListView() ;use a function to avoid left-over variables
Return
Fill_ListView() {
global LsvListOfLabel
;try # times to get Text from PSPad
NumberOfTrys = 20
Loop, {
SetTitleMatchMode, Slow
VarSetCapacity(Text, 1000000)
WinGetText, Text, A
; trim off junk from the start of the text
StringTrimLeft, Text, Text, InStr(Text, "ToolBarProject")
StringTrimLeft, Text, Text, InStr(Text, "`n")
StringTrimLeft, Text, Text, InStr(Text, "`n")
StringTrimLeft, Text, Text, InStr(Text, "`n")
;loop thought Text to find Labels
ListOfLabels =
NumberOfLabels = 0
Loop, Parse, Text, `n ; filter results and add to listview
{
Line := A_LoopField ;remove spaces
If Line contains :,( ;it may be a subroutine or function
{
Label := CheckForLabel(Line) ;check if it is a valid label
If Label { ;if it is, store it
NumberOfLabels++
ListOfIDs%NumberOfLabels% := A_Index
ListOfLabels%NumberOfLabels% := Label
}
}
}
;more then one should be found, since there is an entry "C:", that is below the line count of PSPad
If (NumberOfLabels > 1 )
Break
Else If (A_index = NumberOfTrys){
MsgBox, 4160, Failed to get Text, Script failed %NumberOfTrys% times to get text from PSPad.
Return
}
}
NumberOfLabels -- ;remove last entry "C:", since it is below the line count of PSPad
;create GUI
Gui, +AlwaysOnTop +ToolWindow
Gui, Margin, 2, 2
Gui, Add, ListView, r%NumberOfLabels% w200 Count%NumberOfLabels% vLsvListOfLabel gLsvListOfLabel, Line|Label
Loop, %NumberOfLabels%
LV_Add("", ListOfIDs%A_Index%, ListOfLabels%A_Index%)
LV_ModifyCol(1, "AutoHdr Integer")
LV_ModifyCol(2)
;get GUI ID of still hidden GUI
DetectHiddenWindows, On
Gui, +LastFound
Gui_ID := WinExist()
;get width of Columns and adjust width of ListView control
SendMessage, 0x1000+29, 0, 0, SysListView321, ahk_id %Gui_ID% ; LVM_GETCOLUMNWIDTH is 0x1000+29
Width_Column_1 := ErrorLevel
SendMessage, 0x1000+29, 1, 0, SysListView321, ahk_id %Gui_ID% ; LVM_GETCOLUMNWIDTH is 0x1000+29
Width_Column_2 := ErrorLevel
NewWidth := Width_Column_1 + Width_Column_2 + 4
GuiControl, Move, LsvListOfLabel, w%NewWidth%
;calculate position on right screen edge and show gui
PosX := A_ScreenWidth - NewWidth - 10
Gui, Show, AutoSize x%PosX% NoActivate, PSPad Labels
}
CheckForLabel(Line){
;find out, if Label is a function or subroutine
PosColon := InStr(Line, ":")
PosDoubleColon := InStr(Line, "::")
PosBraket := InStr(Line, "(")
If (PosColon > 1 AND PosDoubleColon = PosColon) ;its a hotkey
Return
Else If (PosColon > 1 AND (PosColon < PosBraket OR PosBraket = 0)){
IsFunction := False
Pos = %PosColon%
}
Else IF (PosBraket > 1 AND (PosBraket < PosColon OR PosColon = 0)){
IsFunction := True
Pos = %PosBraket%
}
Else ;this should never happen, but is fail-save
Return
;get the label
StringLeft, Label, Line, % Pos - 1
;it is an If statement "If("
If (Label = "If")
Return
;check each char in Label if it is allowed
Loop, Parse, Label
If ( A_LoopField <> "_" )
If A_LoopField is not Alnum
Return
;add postfix
If Label {
If IsFunction
Return Label "()"
Else
Return Label ":"
}
}
LsvListOfLabel:
If (A_GuiEvent = "DoubleClick") {
LV_GetText(Row_Number, A_EventInfo) ; Get the row's first-column text.
Gui, Destroy
WinActivate, ahk_id %PSPadWindowID%
Send, ^g%Row_Number%{Enter}
}
Return
GuiClose: ; Indicate that the script should exit automatically when the window is closed.
GuiEscape:
Gui, Destroy
Return