Here is my
first pass at a function to search a HiEdit control using using the AutoHotkey RegExMatch command. It needs the HiEdit library to work. I am not a RegEx expert (not even close) so I'm hoping that a few of you HiEdit/RegEx experts will give a try to confirm that it is works OK. If you find anything more than superficial problems or if you have any questions, please
PM me so that we don't trash this excellent thread.
Here's the code (2 functions):
Code:
;-------------------------------------------------------------------------------
;
; Function: FindRegEx
;
; Description:
;
; Find text within the HiEdit control using the AutoHotkey RegExMatch command.
;
;
; Parameters:
;
; p_Pattern - The regular expression pattern to search for.
;
; p_Min, p_Max - Zero-based search range within the HiEdit control.
;
; p_Min is the character index of the first character in the range and
; p_Max is the character index immediately following the last character
; in the range. Ex: To search the first 5 characters of the text, set
; p_Min to 0 and p_Max to 5. Set p_Max to -1 to search to the end of
; the text.
;
; To search backward, the roles and descriptions of the p_Min and p_Max
; are reversed. Ex: To search the first 5 characters of the control in
; reverse, set p_Min to 5 and p_Max to 0.
;
; p_Flags - Valid flags are as follows:
;
; Flag Description
; ---- -----------
; Static [Advanced feature]
; Text collected from the HiEdit control remains in memory is
; used to satisfy the search request. The static text remains
; in memory until the "Reset" flag is used or until the
; "Static" flag is not used.
;
; Advantages: Search time is reduced 10 to 60 percent
; (or more) depending on the size of the text in the control.
; There is no speed increase on the first use of the "Static"
; flag.
;
; Disadvantages: Any changes in the HiEdit control are not
; reflected in the search.
;
; Bottom line: Don't use this flag unless performing multiple
; search requests on a control that will not be modified
; while searching.
;
;
; Reset [Advanced feature]
; Clears the saved text created by the "Static" flag so that
; the next use of the "Static" flag will get the text directly
; from the HiEdit control. To clear the saved memory without
; performing a search, use the following syntax:
;
; HE_FindRegEx("","",0,0,"Reset")
;
;
; r_RegExOutput - Variable that contains the part of the source text that
; matched the RegEx pattern. [Optional]
;
;
; Returns:
;
; Zero-based character index of the first character of the match or -1 if
; no match is found.
;
;
; Programming notes:
;
; Searching using regular expressions (RegEx) can produce results that have a
; dynamic number of characters. For this reason, searching for the "next"
; pattern (forward or backward) may produce different results from developer
; to developer depending on how the values of p_Min and p_Max are determined.
;
;
HE_FindRegEx(hEdit,p_Pattern,p_Min=0,p_Max=-1,p_Flags="",ByRef r_RegExOut="")
{
Static s_Text
;-- Initialize
r_RegExOut:=""
if InStr(p_Flags,"Reset")
s_Text:=""
;-- Anything to search?
if StrLen(p_Pattern)=0
Return -1
l_MaxLen:=HE_GetTextLength(hEdit)
if (l_MaxLen=0)
Return -1
;-- Parameters
if (p_Min<0 or p_Max>l_MaxLen)
p_Min:=l_MaxLen
if (p_Max<0 or p_Max>l_MaxLen)
p_Max:=l_MaxLen
;-- Anything to search?
if (p_Min=p_Max)
Return -1
;-- Get text
if InStr(p_Flags,"Static")
{
if StrLen(s_Text)=0
s_Text:=HE_GetTextRange(hEdit)
l_Text:=SubStr(s_Text,(p_Max>p_Min) ? p_Min+1:p_Max+1,(p_Max>p_Min) ? p_Max:p_Min)
}
else
{
s_Text:=""
l_Text:=HE_GetTextRange(hEdit,(p_Max>p_Min) ? p_Min:p_Max,(p_Max>p_Min) ? p_Max:p_Min)
}
p_Pattern:=RegExReplace(p_Pattern,"^P\)?","",1) ;-- Remove P or P)
if (p_Max>p_Min) ;-- Search forward
{
l_FoundPos:=RegExMatch(l_Text,p_Pattern,r_RegExOut,1)-1
if ErrorLevel
{
outputdebug,
(ltrim join`s
Function: %A_ThisFunc% - RegExMatch error.
ErrorLevel=%ErrorLevel%
)
l_FoundPos:=-1
}
}
else ;-- Search backward
{
;-- Programming notes:
;
; - The first search begins from the user-defined minimum position.
; This will establish the true minimum position to begin search
; calculations. If nothing is found, no additional searching is
; necessary.
;
; - The RE_MinPos, RE_MaxPos, and RE_StartPos variables contain
; 1-based values.
;
RE_MinPos :=1
RE_MaxPos :=StrLen(l_Text)
RE_StartPos :=RE_MinPos
Saved_FoundPos:=-1
Saved_RegExOut:=""
loop
{
;-- Positional search. Last found match (if any) wins
l_FoundPos:=RegExMatch(l_Text,p_Pattern,r_RegExOut,RE_StartPos)-1
if ErrorLevel
{
outputdebug,
(ltrim join`s
Function: %A_ThisFunc% - RegExMatch error.
ErrorLevel=%ErrorLevel%
)
l_FoundPos:=-1
break
}
;-- If found, update saved and RE_MinPos, else update RE_MaxPos
if (l_FoundPos>-1)
{
Saved_FoundPos:=l_FoundPos
Saved_RegExOut:=r_RegExOut
RE_MinPos :=l_FoundPos+2
}
else
RE_MaxPos:=RE_StartPos-1
;-- Are we done?
if (RE_MinPos>RE_MaxPos or RE_MinPos>StrLen(l_Text))
{
l_FoundPos:=Saved_FoundPos
r_RegExOut:=Saved_RegExOut
break
}
;-- Calculate new start position
RE_StartPos:=RE_MinPos+Floor((RE_MaxPos-RE_MinPos)/2)
}
}
;-- Adjust FoundPos
if (l_FoundPos>-1)
l_FoundPos += (p_Max>p_Min) ? p_Min:p_Max
Return l_FoundPos
}
;--- Experimental
HE_FindRegExReset()
{
HE_FindRegEx("","",0,0,"Reset")
}
...and here is some example code. You'll need to point to a new or existing HiEdit control.
Code:
^+F::
InputBox $FindWhat,Find RegEx,RegEx Pattern:,,220,130,,,,,%$FindWhat%
if ErrorLevel
return
;-- Fall through to next label
^+F3:: ;-- RE Find next
if StrLen($FindWhat)=0
return
HE_GetSel(hEdit,$StartSelPos,$EndSelPos)
$FoundPos:=HE_FindRegEx(hEdit,$FindWhat,$EndSelPos,-1,"",$RegExOut)
if $FoundPos=-1
{
MsgBox Next occurrence not found. %A_Space%
return
}
HE_SetSel(hEdit,$FoundPos,$FoundPos+StrLen($RegExOut))
HE_ScrollCaret(hEdit)
return
^+F2:: ;-- RE Find previous
if StrLen($FindWhat)=0
return
HE_GetSel(hEdit,$StartSelPos,$EndSelPos)
$FoundPos:=HE_FindRegEx(hEdit,$FindWhat,$StartSelPos,0,"",$RegExOut)
if $FoundPos=-1
{
MsgBox Next occurrence not found. %A_Space%
return
}
HE_SetSel(hEdit,$FoundPos,$FoundPos+StrLen($RegExOut))
HE_ScrollCaret(hEdit)
return
Thanks for your help.