AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

AHK code explorer for PSPad

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Rabiator



Joined: 17 Apr 2005
Posts: 266
Location: Sauerland

PostPosted: Sat Jan 27, 2007 8:26 pm    Post subject: AHK code explorer for PSPad Reply with quote

AHK Code Explorer
PSPad (my favourite editor) has a feature called code explorer, supporting several programming languages.
With it you can see and navigate to functions, defines, labels etc.
Due to the lack of a code explorer for AutoHotkey I coded something similar to bridgeover the time till PSPad supports it.
(Jan 29, 2007: Meanwhile AutoHotkey is supported, but still very rudimentarily.)

It is easy to use:
You start it and switch to the PSPad window.
With ctrl-shift-e you display the code explorer window with a treeview.
If you select an element (hotkey, hotstring, label or function) with a double-click, the code explorer window will disappear and you will be navigated to the corresponding line in the source code.
Or you hide the window with a second ctrl-shift-e.

The AHK code explorer considers both types of comments. It is surely adaptable to other editors; I pointed out the PSPad specific actions.

Changes
Jan 31, 2007: added a user definable label type.
Feb 12, 2007: advanced the above to show comments in a hierarchical contents list. The identification pattern has changed.
Mar 31, 2007: Fixed: Hotstrings with options will be identified now correctly. Fixed: Assignments like var:=value starting at the beginning of a line won't be identified as labels any more.

Comment format
A hierarchical contents list is fed with comment lines with certain rules.
Due to affect the readability of existing comments as little as possible, the precursory pattern for hierarchical comment lines is ";.", with eventually directly following points.
Because most coders start their comments in the same indentation as the following code, the HCL doesn't have to start necessarily in the first column. But the ";." sequence must be the first printable characters in the line.
The number of points in the precursory pattern represents the corresponding level inside the TreeView. ";." is the highest level, ";.." the second level etc. The level is not limited.
Code:
;.   Headline 1
;..  Headline 1.1
;..  Headline 1.2
;... Headline 1.2.1
;.   Headline 2

To avoid the necessity of creating additional lines with hierarchical comments, it is possible to show only a part of a comment line. AHK code explorer uses a separator consisting of a multiple-space/tab sequence, a succession of two or more spaces/tabs. That still allows largely individual formatting. Which text will be displayed obeys the following rules:
    a) No separator: the complete line
    b) One separator: the text followed by the separator.
    c) Two ore more separators: the first text enclosed by two separators
A multiple-space/tab sequence following the precursory pattern or standing at the end of the line will not be identified as a separator.
Code:
;. The complete line will be shown in the TreeView.
;.           as well as this line, without leading spaces within the comment
     ;. as well as this line
;. visible  hidden
;. hidden    visible  hidden hidden   hidden
;.    visible  hidden

Hierarchical comment lines are also recognized inside /* ... */-type comments.

Indentation
If the indentation level raises by more than 1, additional empty labels will be inserted in the TreeView.

This script itself is commented in the described style.
Code:
; A simplified surrogate for the missing PSPad code explorer for AutoHotkey
; by Rabiator
; -------------------------------------------------------------------------

;.  ---  Groups  ---
;   Control existance, order and behavior of the groups. The following table
;   contains for each group its name, starting state of "Expand" and an icon
;   number. If you dont't want to have it displayed in the TreeView, remove it
;   from the table.
;.. The  Group names  are: "Functions", "Hotkeys", "Hotstrings", "Labels",
;   "DllCalls", "MyLabels". These names are fix.
;.. Expanded     : 0 = collapsed, 1 = expanded
;.. Icon number  : The 3rd element is the number of the icon in the ImageList
;   (see there).

Groups =
(
Functions,  0, 2
Hotkeys,    0, 3
Hotstrings, 0, 4
Labels,     0, 5
DllCalls,   0, 6
MyLabels,   1, 7
)


Loop, Parse, Groups, `n
{
  Sep := (A_Index = 1) ? "" : "|"
  StringSplit, Arr, A_LoopField, `,
  GroupNames     = %GroupNames%%Sep%%Arr1%
  %Arr1%__Expanded = %Arr2%
  %Arr1%__IconNo   = %Arr3%
}


New := 1

; Start and Stop
^+e::

If (New = 0)
{
  Gui, Destroy
  New := 1
  Return
}

; Only run if the editor window is active.
IfWinNotActive, PSPad -
  Return

New := 0

;. Get the actual line number
;  (PSPad: from the status bar. I hope this won't change in later versions.)
My_TitleMatchMode := A_TitleMatchMode
My_TitleMatchModeSpeed := A_TitleMatchModeSpeed
SetTitleMatchMode, 2
SetTitleMatchMode, Slow
WinGetText, Var
RegExMatch(Var, "s)\s+?(?'LineNo'[\d]+) :\s*\d+\s*\((?'Lines'\d+)", Act)
SetTitleMatchMode, %My_TitleMatchMode%
SetTitleMatchMode, %My_TitleMatchModeSpeed%

;. Save the contents
MyClipboard := ClipBoard
Send, ^a^c
Sleep, 100
Contents := Clipboard
Clipboard := MyClipboard

; Unselect the text by jumping to the actual line number (PSPad).
Send, ^g%ActLineNo%{ENTER}


; ------------------------------------------------------------------------
;. Parse for hotstrings, hotkeys, labels, functions and DllCalls
;  Clear all lists
HotKeys =
Hotstrings =
Labels =
Functions =
DllCalls =
MyPatterns =
MyLabels =

bComment := 0
bFunction := 0
;. Parse each line
Loop, Parse, Contents, `n, `r
{
  LineNo := A_Index
  Line := A_LoopField

  ;
  If (Mod(LineNo, 1000) = 0)
    ToolTip Parsing line %LineNo% of %ActLines% , A_ScreenWidth/2, A_ScreenHeight/2

  ;.. Exclude /* .. */ comments
  FoundPos := RegExMatch(Line, "^\s\/\*")
  If (FoundPos)
  {
    bComment := 1      ; a comment section begins
    Continue
  }
  If (bComment = 1)
  {
    FoundPos := RegExMatch(Line, "^\s\*\/")
    If (FoundPos)
      bComment := 0    ; a comment section ends
    Continue
  }

  ;.. Find Hotkeys
  FoundPos := RegExMatch(Line, "([^\s:]+?)::", HotkeyPat)
  If (FoundPos = 1)
    Hotkeys = %Hotkeys%%HotkeyPat1%,%LineNo%`n

  ;.. Find Hotstrings
  ; improved by bold
  FoundPos := RegExMatch(Line, ":[*?a-zA-Z0-9]*:([^\s:]+?)::", HotstringPat)
  If (FoundPos)
    Hotstrings = %Hotstrings%%HotstringPat1%,%LineNo%`n

  ;.. Find Labels
  FoundPos := RegExMatch(Line, "([^\s;:]+):(\s|$)", LabelPat)
  If (FoundPos = 1)
    Labels = %Labels%%LabelPat1%,%A_Index%`n

  ;.. Find Functions
  If (bFunction = 0)
  {
    ; alphanumeric letters (international) and # _ @ $ ? [ ]

    FoundPos := RegExMatch(Line, "^\s*(?'Name'[\w€-ÿ#_@$\?\[\]]+)(?'Pars'\(.*\))", Function)
    If (FoundPos)
    {
      ; prevent from taking an expression-if with directly following ( as a function.
      If (FunctionName = "if")
        Continue

      FuncDeclLine := LineNo
      ; Find the {
      ; OTB?
      FoundPos := RegExMatch(Line, ")\s*\{")
      If (FoundPos)
        ; { found in the 1st line
        Functions = %Functions%%FunctionName%%FunctionPars%,%FuncDeclLine%`n
      Else
        bFunction := 1
    }
  }
  Else
  {
    ; no OTB
    FoundPos := RegExMatch(Line, "^\s*{")
    If (FoundPos)
    {
      ; { found in one of the following lines
      Functions = %Functions%%FunctionName%%FunctionPars%,%FuncDeclLine%`n
      bFunction := 0
    }

    FoundPos := RegExMatch(Line, "^\s*?[^;\s]")
    If (FoundPos)
      ; found something that doesn't belong to a function
      bFunction := 0
  }

  ;.. Find DllCalls
  FoundPos := RegExMatch(Line, "^\s*(DllCall\(.*?\))", DllCallPat)
  If (FoundPos)
    DllCalls = %DllCalls%%DllCallPat1%,%LineNo%`n

  ;.. Find user-defined labels
  If GroupNames contains MyLabels
  {
    ; Search for the pattern ";."
    FoundPos := RegExMatch(Line, "^\s*;(\.+)\s(.*)", MyPat)

    If (FoundPos)
    {
      Line = %Line%      ; Trim spaces and tabs

      ; Evaluate the indentation level
      StringLen Level, MyPat1
     
      MyPat2 = %MyPat2%  ; Trim spaces and tabs
      Var := RegExReplace(MyPat2, "\s{2,}", "¢")

      StringSplit, Arr, Var, ¢
      If (Arr0 > 2)
        MyLabels = %MyLabels%%Level%|%Arr2%,%LineNo%`n
      Else
        MyLabels = %MyLabels%%Level%|%Arr1%,%LineNo%`n
     
    }
  }
}


; ------------------------------------------------------------------------
;. Prepare and create the GUI   

;.. Create an ImageList
ImageListID := IL_Create(7)
IL_Add(ImageListID, "shell32.dll", 4)
IL_Add(ImageListID, "shell32.dll", 42)
IL_Add(ImageListID, "shell32.dll", 13)
IL_Add(ImageListID, "shell32.dll", 29)
IL_Add(ImageListID, "shell32.dll", 44)
IL_Add(ImageListID, "shell32.dll", 45)
IL_Add(ImageListID, "shell32.dll", 46)

;.. Create the GUI
Gui, Add, TreeView, ImageList%ImageListID% R20 gJump w400 h500 vTV

;.. Delete pending `n, sort objects and create the treeview
Level := -1
Loop, Parse, GroupNames, |
{
  Group := A_LoopField
  ObjIndex := A_Index
  IconNo := A_Index + 1
  StringTrimRight, %Group%, %Group%, 1

  ; Treat MyLabels differently
  If (Group <> "MyLabels")
  {
    Sort, %Group%
 
    ID_%Group% := TV_Add(Group, 0, "Icon1 Bold Expand" . %Group%__Expanded)
    StringSplit, Arr%Group%, %Group%, `n
    Loop, % Arr%Group%0
    {
      RegExMatch(Arr%Group%%A_Index%, "(.*),(\d*)", Name)
      ID_%Group%C%A_Index% := TV_Add(Name1, ID_%Group%, "Icon" . %Group%__IconNo gJump)
      a := ID_%Group%C%A_Index%
      Line_%a% := Name2
    }
  }
  Else   ; Group is "MyLabels"
  {
    If (Level = -1) {
      Level := 0
      ; Create the item and save the last ItemID of this level.
      LevelID%Level% := TV_Add(Group, 0, "Icon1 Bold Expand" . %Group%__Expanded)
      LastItem := LevelID%Level%
    }

    ; Add all items regarding their level.
    StringSplit, Arr%Group%, %Group%, `n
    Loop, % Arr%Group%0
    {
      RegExMatch(Arr%Group%%A_Index%, "(.*),(\d*)", Name)
      RegExMatch(Name1, "(\d+)\|(.*)", SubName)
      NewLevel := SubName1
      Name := SubName2
      LineNo := Name2

      Loop
      {
        If (NewLevel <= Level + 1)
        ; max. 1 indent
        {
          ParentLevel := NewLevel - 1
          LevelID%NewLevel% := TV_Add(Name, LevelID%ParentLevel%, "Expand Icon7" . gJump)
          If (NewLevel > Level)
            ; Mark parent item with bold and folder icon
            TV_Modify(LevelID%ParentLevel%, "Bold Icon1")
          Level := NewLevel
          a := LevelID%NewLevel%
          Line_%a% := LineNo
          Break
        }
        Else
        ; Overall more than 1 indent
        ; Step-by-step we create and add an indented empty item.
        {
          Level++
          ParentLevel := Level - 1
          LevelID%Level% := a := TV_Add("<empty>", LevelID%ParentLevel%, "Expand Icon7" . gJump)
          Line_%a% := -1  ; Empty items don't have a valid line number.
        }
      }
    }
  }
 
}
ToolTip
Gui, +Resize
Gui, Show,
Return


GuiSize:
; The treeview gets automatically resized with the window.
GuiControl, Move, TV, % "h" A_GuiHeight-20 " w" A_GuiWidth-20

; Minimizing the window will destroy it.
If (A_EventInfo = 1)
{
  Gui, Destroy
  New := 1
}
Return

GuiClose:
ExitApp

; Jump to the line with the selected item.
Jump:
  ; It's impossible to jump to the category
  ItemID := TV_GetSelection()
  ParentID := TV_GetParent(ItemID)
  If Not ParentID
    Return
 
  ; Fetch the line number
  LineNo := Line_%ItemID%
  ; Don't jump to an empty item
  If (LineNo = -1)
    Return
  Gui, Submit
 
  ; A command that selects the found line (PSPad).
  Send, ^g%LineNo%{ENTER}

  ; Remove the GUI
  Gui, Destroy
  New := 1
Return


__________________________________________
Created with BBCodeWriter 6.6 - the one and only Very Happy


Last edited by Rabiator on Fri Mar 30, 2007 11:47 pm; edited 4 times in total
Back to top
View user's profile Send private message
toralf



Joined: 31 Jan 2005
Posts: 3842
Location: Bremen, Germany

PostPosted: Sun Jan 28, 2007 11:16 am    Post subject: Reply with quote

Hi Rabiator,
Thanks for sharing.

Could you please point out what the differences are to ActiveGoTo? Thanks.
_________________
Ciao
toralf
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Rabiator



Joined: 17 Apr 2005
Posts: 266
Location: Sauerland

PostPosted: Sun Jan 28, 2007 3:53 pm    Post subject: Reply with quote

toralf wrote:
Could you please point out what the differences are to ActiveGoTo? Thanks.
I conceive suspicion that this is a rethorical question Wink .

Indeed, after discovering ActiveGoto's actual state I didn't feel certain whether to release my script or not.
My goal was to have a tool working similarly to PSPad code explorer in usage and appearance (especially the treeview) - ActiveGoto is not, so I released mine.
That is the main difference.

If the question was not rethorical:
ActiveGoto is more universal and configurable (and coded by exceptionally gifted programmers Smile ), displays only one type of items in a single list. AHK Code Explorer (now it has a name) is more special, doesn't need to be configured due to its mission and displays all items sorted by type.

__________________________________________
Created with BBCodeWriter 6.6 - the one and only Very Happy
Back to top
View user's profile Send private message
skwire



Joined: 18 Jan 2006
Posts: 150
Location: Conway, Arkansas

PostPosted: Mon Jan 29, 2007 7:29 am    Post subject: Re: AHK code explorer for PSPad Reply with quote

Rabiator wrote:
Due to the lack of a code explorer for AutoHotkey I coded something similar to bridgeover the time till PSPad supports it.


It's supported now in the latest beta.

http://pspad.cincura.net/beta/

Specifically:

http://pspad.cincura.net/beta/pspad453b2253.cab

It's not perfect...but it's a start.
Back to top
View user's profile Send private message AIM Address Yahoo Messenger MSN Messenger
Guest






PostPosted: Mon Jan 29, 2007 11:21 pm    Post subject: Re: AHK code explorer for PSPad Reply with quote

skwire wrote:
It's supported now in the latest beta.
Thank you for the hint! I tried it out.
Quote:
It's not perfect...but it's a start.
Wink Like mine.
It's a nice idea to show the DllCalls, I'll update my script with this ability.

__________________________________________
Created with BBCodeWriter 6.6 - the one and only Very Happy
Back to top
kiu



Joined: 18 Dec 2005
Posts: 229
Location: Italy - Galatro(RC)

PostPosted: Tue Jan 30, 2007 3:51 pm    Post subject: Reply with quote

Very good!
Only 1 problem: the script show if(..) as functions.
As very simple workaround:
Code:

if(SubStr(Name, 1, 2)="If")
       continue
 


after line 165
_________________
____________________
______________________
kiu
Back to top
View user's profile Send private message Visit poster's website
toralf



Joined: 31 Jan 2005
Posts: 3842
Location: Bremen, Germany

PostPosted: Tue Jan 30, 2007 9:03 pm    Post subject: Reply with quote

Rabiator wrote:
If the question was not rethorical
It wasn't. I am currently just to busy to test scripts, and I wanted to get an idea of what this script does differently. Thanks for pointing it out. I will test it if time permints. Thank you for sharing.
_________________
Ciao
toralf
Back to top
View user's profile Send private message Send e-mail Visit poster's website
kiu as guest
Guest





PostPosted: Tue Jan 30, 2007 11:13 pm    Post subject: Reply with quote

the main difference that I like is the grouping of items by category in e treeview:
+function
+---function1()
+---function2()
+---function3()
+hotkeys
+---hotkey1
...
so you can find faster what you want. I think it will be good to have the best from all two scripts in the same one.
Back to top
daonlyfreez



Joined: 16 Mar 2005
Posts: 745
Location: Berlin

PostPosted: Wed Jan 31, 2007 12:14 am    Post subject: Reply with quote

Nice!

Some quick mods... Wink

Code:
145 ; Create the GUI
146 Gui, Add, TreeView, ImageList%ImageListID% R20 gJump w400 h500 vTV

158   ID_%Group% := TV_Add(Group, 0, "Icon1 Bold Expand")

169+
Gui, +Resize
Gui, Show,
Return

GuiSize:
GuiControl, Move, TV, % "h" A_GuiHeight-20 " w" A_GuiWidth-20
Return


GuiClose:
ExitApp

_________________
(sorry, homesite offline atm)
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Rabiator



Joined: 17 Apr 2005
Posts: 266
Location: Sauerland

PostPosted: Wed Jan 31, 2007 11:45 pm    Post subject: Reply with quote

kiu wrote:
Only 1 problem: the script show if(..) as functions.
Thanks for your suggestion! The if "function" is now skipped.

daonlyfreez wrote:
Some quick mods... Wink
I added your quick mods, thank you!

I also added a user definable label type. It lets us navigate to important/interesting script passages like explanations, structures, sections etc. that don't belong to the previous types. (Of course that is an extension to the original code explorer functions and exceeds my primary intention, but: who cares?)

Example:
Code:
; ---------------------
;@ List of used hotkeys
;
; F1 = ...
; F2 = ...

The AHK code explorer in this example searches for the pattern ";@" at the beginning of a line and displays in the new group "MyLabels" for every matching line the text that follows the found pattern.

You can define the pattern in section "User-defined labels", (at the moment line 16); if you don't want this feature, leave the string empty.

A glance into a possible future: several or/and even nested label types (= more levels in the treeview), which allow you to give big (and therefore perhaps confusing) scripts a helpful structure (at least for editing Wink ).

__________________________________________
Created with BBCodeWriter 6.6 - the one and only Very Happy
Back to top
View user's profile Send private message
Rabiator



Joined: 17 Apr 2005
Posts: 266
Location: Sauerland

PostPosted: Mon Feb 12, 2007 10:36 pm    Post subject: Reply with quote

Added: "hierarchical" comment lines to support a structured contents list, see the first post.

__________________________________________
Created with BBCodeWriter 6.6 - the one and only Very Happy
Back to top
View user's profile Send private message
bold



Joined: 20 Apr 2006
Posts: 15

PostPosted: Fri Mar 30, 2007 5:26 pm    Post subject: Reply with quote

Nice,

I changed the hotstring regex because not all hotstrings are found

Code:
  ;.. Find Hotstrings
  FoundPos := RegExMatch(Line, ":[*?a-zA-Z0-9]*:([^\s:]+?)::", HotstringPat)
  If (FoundPos)
    Hotstrings = %Hotstrings%%HotstringPat1%,%LineNo%`n
Back to top
View user's profile Send private message
Guest+
Guest





PostPosted: Fri Mar 30, 2007 8:30 pm    Post subject: Reply with quote

I tried it on only one script (poorely written by me but works) and :
It didn't find any functions
it recognized xx:=xxx as a label
Back to top
Guest+
Guest





PostPosted: Fri Mar 30, 2007 8:33 pm    Post subject: Reply with quote

rajat's script works perfectly on the same script
Back to top
Rabiator



Joined: 17 Apr 2005
Posts: 266
Location: Sauerland

PostPosted: Fri Mar 30, 2007 11:48 pm    Post subject: Reply with quote

@bold
Thanks for your report and improvement! I adopted it.

@Guest+
It is fixed now, thanks for your report.

__________________________________________
Created with BBCodeWriter 6.6 - the one and only Very Happy
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group