the script is updated. → viewtopic.php?p=404344#p404344 ← click this link
star-one-b added a new feature, a 3-tier search mechanism.
Text Filter
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
i think i have found the "Oops..." problem of my "wm_activate" function, which requires myself or any developers using this to note about. that is, at the moment when a window is created, its title doesn't meet the "wm_activate" checking. and it only becomes "met" (the checking) thereafter by changing/updating its title which won't trigger "wm_activate" to update the global variable "_cwi_".SundayProgrammer wrote: ↑07 Jun 2021, 13:09hi @Kellyzkorner_NJ, thank you for letting me know the error. i myself did hit this a few times during testing, but can never repeat it immediately. are you having this problem consistently?
by the way, the _cwi_ (current window id) global variable is set by the wm_activate function via onmessage. the "other windows" message simply means the active window is other than those created from the "tf" object (the text filter and its associated windows).
two ways to fix it: either make sure the window title meets the "wm_activate" checking at the moment when the window is born, or execute "wm_activate(1)" after its window title becomes "met".
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
star-two
added a "slim" gui, and it becomes the going one at the "start". you can nonetheless switch between slim and full-blown by a button click or selecting it from rightclick menu anytime.
people sometimes may want a light and clean interface for simple tasks, and the full-blown gui takes up almost the whole screen could be too much for that purpose.
this slim gui starts with a smaller footprint. all the checkboxes are removed, yet, "assorted matches", "treeview", and "context peeking" got their own button now. added a match count, and it can be used as a refresh button as well.
side note: the match count is not equivalent to the line count shown on the window title, they may show the same number when each line has one and only one match though.
although there is no "multi-level" thing in slim gui, the current level in full-blown will be brought forward when you switch over. and hence, you may work at different level in slim because of that.
2021-6-30: star-two-a made three tweaks:
(a) improved the indentation for the scenario when "assorted matches" shown with word wrapping.
although the 1st-step richedit indentation is already there since "matches highlighting" was implemented, "assorted matches" was not benefited as it requires 2nd-step indentation (due to its "grouped" layout).
as a legacy of the pre-richedit era, indentation for "assorted matches" relied on the "tab" character (which never worked well with word wrapping). now, the "tab" character is removed, and the 2nd-step richedit indentation is applied.
(b) extended the "doubleclick" to invoke "copy the line/selection".
it all depends on whether "context peeking" window exists or not when "doubleclick" is made. if exists, "context peeking" will be scrolled to show the line. otherwise, "copy the line/selection" is assumed.
(c) enabled user to specify new instance be created from which class object.
there are two ways to create new instance within the user interface. either through "paste into the base" or "open a file". however, both ways were set to create from the "tf" class object.
now, user can specify it explicitly. at the input box when "object instance identification" is popped for a response, you may enter like this: mytf=stf where "mytf" is the id and "stf" is the class object that "mytf" will be created from.
likewise, if you have your own extended class, say, named "abc", you may also enter it like udtf=abc to create the instance "udtf" from the class "abc".
this explicit specification of class object is optional. if it's not specified, class "tf" is assumed if the id is changed (otherwise, it's just a "replace" operation thus what class was the instance created from will remain unchanged), same as before.
2021-7-7: star-two-b added a feature to load the text in reverse order, by line.
at the input box when "object instance identification" is popped for a response, just append "/r" or "-r" to indicate the loading shall be in reverse order. examples, joy/r or joy=stf/r.
2021-7-11: star-two-c two adjustments are made.
(a) "reload the file" can cater "reversed" file now. that is, if the file was loaded in reversed order, its order will be preserved after "reload".
(b) a better fix (regarding the "doubleclick" feature) is crafted. and hence, all those dirty fixes (made recently) are removed.
besides, a new trivial feature is added.
long press the "yes" button of the msgbox for "copy" (the one triggered by "doubleclick") not only will copy the selected text but will also use it as the new search term.
if the msgbox did not pop up after the text is selected and you so happen wanting it, just place your mouse pointer on top of the selected text and give it a long press.
if this still doesn't bring up the msgbox you wanted, just select something else (to reset the memory) and get back to select it again.
that's it for now.
added a "slim" gui, and it becomes the going one at the "start". you can nonetheless switch between slim and full-blown by a button click or selecting it from rightclick menu anytime.
people sometimes may want a light and clean interface for simple tasks, and the full-blown gui takes up almost the whole screen could be too much for that purpose.
this slim gui starts with a smaller footprint. all the checkboxes are removed, yet, "assorted matches", "treeview", and "context peeking" got their own button now. added a match count, and it can be used as a refresh button as well.
side note: the match count is not equivalent to the line count shown on the window title, they may show the same number when each line has one and only one match though.
although there is no "multi-level" thing in slim gui, the current level in full-blown will be brought forward when you switch over. and hence, you may work at different level in slim because of that.
2021-6-30: star-two-a made three tweaks:
(a) improved the indentation for the scenario when "assorted matches" shown with word wrapping.
although the 1st-step richedit indentation is already there since "matches highlighting" was implemented, "assorted matches" was not benefited as it requires 2nd-step indentation (due to its "grouped" layout).
as a legacy of the pre-richedit era, indentation for "assorted matches" relied on the "tab" character (which never worked well with word wrapping). now, the "tab" character is removed, and the 2nd-step richedit indentation is applied.
(b) extended the "doubleclick" to invoke "copy the line/selection".
it all depends on whether "context peeking" window exists or not when "doubleclick" is made. if exists, "context peeking" will be scrolled to show the line. otherwise, "copy the line/selection" is assumed.
(c) enabled user to specify new instance be created from which class object.
there are two ways to create new instance within the user interface. either through "paste into the base" or "open a file". however, both ways were set to create from the "tf" class object.
now, user can specify it explicitly. at the input box when "object instance identification" is popped for a response, you may enter like this: mytf=stf where "mytf" is the id and "stf" is the class object that "mytf" will be created from.
likewise, if you have your own extended class, say, named "abc", you may also enter it like udtf=abc to create the instance "udtf" from the class "abc".
this explicit specification of class object is optional. if it's not specified, class "tf" is assumed if the id is changed (otherwise, it's just a "replace" operation thus what class was the instance created from will remain unchanged), same as before.
2021-7-7: star-two-b added a feature to load the text in reverse order, by line.
at the input box when "object instance identification" is popped for a response, just append "/r" or "-r" to indicate the loading shall be in reverse order. examples, joy/r or joy=stf/r.
2021-7-11: star-two-c two adjustments are made.
(a) "reload the file" can cater "reversed" file now. that is, if the file was loaded in reversed order, its order will be preserved after "reload".
(b) a better fix (regarding the "doubleclick" feature) is crafted. and hence, all those dirty fixes (made recently) are removed.
besides, a new trivial feature is added.
long press the "yes" button of the msgbox for "copy" (the one triggered by "doubleclick") not only will copy the selected text but will also use it as the new search term.
if the msgbox did not pop up after the text is selected and you so happen wanting it, just place your mouse pointer on top of the selected text and give it a long press.
if this still doesn't bring up the msgbox you wanted, just select something else (to reset the memory) and get back to select it again.
that's it for now.
Code: Select all
SetWorkingDir %A_ScriptDir%
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
thePoem=
(
The Road Not Taken
BY ROBERT FROST
Two roads diverged in a yellow wood,
And sorry I could not travel both
And be one traveler, long I stood
And looked down one as far as I could
To where it bent in the undergrowth;
Then took the other, as just as fair,
And having perhaps the better claim,
Because it was grassy and wanted wear;
Though as for that the passing there
Had worn them really about the same,
And both that morning equally lay
In leaves no step had trodden black.
Oh, I kept the first for another day!
Yet knowing how way leads on to way,
I doubted if I should ever come back.
I shall be telling this with a sigh
Somewhere ages and ages hence:
Two roads diverged in a wood, and I—
I took the one less traveled by,
And that has made all the difference.
)
; tf.start("Load Clipboard")
; msgbox
; tf.start("Load File log.txt")
; msgbox
tf.start(thePoem)
; msgbox
; tf.start() ;from what's leftoff in the object's memory
;multiple instances can be coexisting as below
; w1 := new tf, w1.start("Load Clipboard")
; w2 := new tf, w2.start("Load File log.txt")
; w3 := new tf, w3.start(thePoem)
; msgbox
; w3.start() ;from what's leftoff in the object's memory
Return
Class stf extends tf {
FlexRxR(ByRef Hays, Nee) {
v := this.ov
If Resu := RegExReplace(Hays, this.Maker(Nee))
Return (Resu, this[v].r := Nee)
last_index := 0, s := Nee
While, pos := RegExMatch(s, "\([^)]+\)|\[[^\]]+\]", m)
s := SubStr(s, 1, pos - 1) Chr(168) Chr(168 + A_Index) Chr(168) SubStr(s, pos + StrLen(m)), s%A_Index% := m, last_index := A_Index
Loop, Parse, s
{ If A_Index > 1
r .= t A_LoopField
Else r := A_LoopField
t := RegExMatch(A_LoopField, "[a-z]") ? "\w{0,3}" : ""
}
Loop, % last_index
i := last_index - A_Index + 1, r := StrReplace(r, Chr(168) Chr(168 + i) Chr(168), s%i%)
If Resu := RegExReplace(Hays, this.Maker(r))
Return (Resu, this[v].r := r)
Loop, Parse, Nee
{ If A_Index > 1
r .= t A_LoopField
Else r := A_LoopField
t := RegExMatch(A_LoopField, "\w") ? "[\w'\-+]*" : ""
}
If Resu := RegExReplace(Hays, this.Maker(r))
Return (Resu, this[v].r := r)
Loop, Parse, Nee, % ("", r := "")
r .= RegExMatch(A_LoopField, "\w") ? "(?=[\w'\-+]*" A_LoopField ")" : ""
If StrLen(r)
r .= "\b[\w'\-+]*\b"
Else Return ""
If Resu := RegExReplace(Hays, this.Maker(r))
Return (Resu, this[v].r := r)
Else Return ("", this[v].r := "")
}
} ;end of class
FocusedControl() {
ControlGetFocus, foco, A
Return foco
}
#If, WinActive("The Text Filter") and FocusedControl() = "Edit1"
`::
Tab::ControlFocus, RICHEDIT50W1, A
#If, WinActive("The Text Filter") and FocusedControl() = "RICHEDIT50W1"
Tab::ControlFocus, Edit1, A
Space::PgDn
+Space::PgUp
s::Home
e::End
t::^Home
b::^End
-::%_cwi_%.DecrFontSize()
+::
=::%_cwi_%.IncrFontSize()
`::
Enter::%_cwi_%.TakeThisLine()
f::%_cwi_%.FindNextMatch()
+f::%_cwi_%.FindNextMatch(1)
#If, WinActive("TreeView Of Assorted Matches") and FocusedControl() = "SysTreeView321"
`::
Enter::%_cwi_%.tvButtonEnter()
#If, WinActive("Context Peeking") and FocusedControl() = "RICHEDIT50W1"
~WheelUp::
~WheelDown::%_cwi_%.WheelSearchMode()
#IfWinActive, The Text Filter
F1::%_cwi_%.ToggleHelpPage(_cwi_)
~WheelUp::
~WheelDown::%_cwi_%.WheelSearchMode()
!a::%_cwi_%.ShowAssMatches()
^t::%_cwi_%.AssTreeView(_cwi_)
^p::%_cwi_%.ContextPeek(_cwi_)
!v::Gosub, PasteHaySub
^o::Gosub, OpenFileSub
^r::%_cwi_%.ReloadFile()
#If, WinActive("The Text Filter") and (_bundledRB_ not = "disabled")
~RButton::%_cwi_%.RClickMenu()
#IfWinActive, ahk_class #32770
~LButton::EventHandler(0, 0, 0x201, 0)
~LButton up::EventHandler(0, 0, 0x202, 0)
#IfWinActive
PasteHaySub:
%_cwi_%[%_cwi_%.ov].eFlag := True
If _uii_ := %_cwi_%.PasteIntoHaystack()
{ If _rev_ := RegExMatch(_uii_, "^r\)")
_uii_ := RegExReplace(_uii_, "^r\)")
If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load Clipboard", _rev_)
Else If not InStr(_uii_, "=")
%_uii_% := new tf, %_uii_%.start("Load Clipboard", _rev_)
}
%_cwi_%[%_cwi_%.ov].eFlag := False
Return
OpenFileSub:
%_cwi_%[%_cwi_%.ov].eFlag := True
If _OpFi_ := %_cwi_%.OpenFile()
{ If _rev_ := RegExMatch(_OpFi_, "^r\)")
_OpFi_ := RegExReplace(_OpFi_, "^r\)")
RegExMatch(_OpFi_, "^[\w=]+(?=\t)", _uii_), RegExMatch(_OpFi_, "\t\K.+$", _usf_)
If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load File " _usf_, _rev_)
Else If not InStr(_uii_, "=")
%_uii_% := new tf, %_uii_%.start("Load File " _usf_, _rev_)
}
%_cwi_%[%_cwi_%.ov].eFlag := False
Return
WM_ACTIVATE(wParam) {
global _cwi_
If (wParam > 0)
If WinActive("The Text Filter") or WinActive("TreeView Of Assorted Matches") or WinActive("Context Peeking") or WinActive("Edit Variables")
{ WinGetTitle, t, A
If RegExMatch(t, "\| *?(\w*?) *?\|", m) and StrLen(m1)
_cwi_ := m1
Else _cwi_ := "Oops..."
}Else _cwi_ := "Other Windows"
}
EventHandler(wParam, lParam, msg, hwnd) {
static lbdowntime := 0, dx, dy
global lbduration := 0
If msg = 0x201 ;WM_LBUTTONDOWN
{ MouseGetPos, dx, dy
lbdowntime := A_TickCount
}Else If msg = 0x202 ;WM_LBUTTONUP
If (lbduration := A_TickCount - lbdowntime) > 1000
{ MouseGetPos, ux, uy,, moc
If (moc = "RICHEDIT50W1") and Abs(ux - dx) < 10 and Abs(uy - dy) < 10
MsgBox,, Prompt, Hang On..., 1
}
Return
}
Class tf {
static o := {}
v := {}
start(Param := "", Reverse := 0) {
OnMessage(0x6, "WM_ACTIVATE")
OnMessage(0x201, "EventHandler") ;WM_LBUTTONDOWN
OnMessage(0x202, "EventHandler") ;WM_LBUTTONUP
this.id := this.GetObjVarNam(), v := this.ov := (this.id = this.__class ? "o" : "v")
this[v].Version := "Star-Two-C"
If StrLen(Param)
{ this[v].SelectedFile := ""
If Param = Load Clipboard
this[v].Haystack := Clipboard
Else If SubStr(Param, 1, 9) = "Load File"
this[v].Haystack := this.FileRead((Reverse ? "<R>" : "") SubStr(Param, 11))
Else this[v].Haystack := Param
this[v].Haystack := StrReplace(this[v].Haystack, "`r`n", "`n")
If Reverse
theHays := this[v].Haystack, this.ReverseByLine(theHays), this[v].Haystack := theHays
this[v].Fayt := this[v].Case := this[v].Wwrap := True, this[v].Whole := this[v].Linum := False, this[v].n := 1, this[v].Hs[0] := this[v].GetAddress("Haystack"), this[v].Hs[1] := this[v].Haystack
}
this.SlimGui(this.id), this.CleanUp(this.id)
}
FileRead(theFile) {
FileRead, theHays, % (SubStr(theFile, 1, 3) = "<R>" ? SubStr(theFile, 4) : theFile, this[this.ov].SelectedFile := theFile)
Return theHays
}
HsP(n) {
If (n > 1)
Return this[this.ov].Hs[n - 1]
Else Return StrGet(this[this.ov].Hs[0])
}
NeeP(n) {
If (n > 1)
Return this[this.ov].Needle[n - 1]
Else Return ""
}
GetObjVarNam() {
r := "(\w+?):.+?\{address: " Format("0x{:X}", &this) "\}"
Return RegExMatch(this.ListGlobalVars(), r, m) ? m1 : ""
}
SlimGui(id) {
static Fayt
Gui, %id%:New, +Labeltf.sGui_On
Gui, +Resize +MinSize +MaximizeBox
Gui, Font, s18, Consolas
Gui, Add, Edit, xm w280 vFayt
OnSuch := this.Fayt_OnTyping.Bind(this)
GuiControl +g, Edit1, % OnSuch
Gui, Add, Button, x+10 ys h37 w85 Center, 0
OnSuch := this.Refresh_OnClick.Bind(this)
GuiControl +g, Button1, % OnSuch
Gui, Font, s10, Arial
Gui, Add, Button, x+10 w40 ys h37 Default, A
OnSuch := this.A_OnClick.Bind(this)
GuiControl +g, Button2, % OnSuch
Gui, Add, Button, x+0 w40 ys h37, T
OnSuch := this.T_OnClick.Bind(this)
GuiControl +g, Button3, % OnSuch
Gui, Add, Button, x+0 w40 ys h37, C
OnSuch := this.C_OnClick.Bind(this)
GuiControl +g, Button4, % OnSuch
Gui, Add, Button, x+0 w40 ys h37, F
OnSuch := this.F_OnClick.Bind(this)
GuiControl +g, Button5, % OnSuch
begWwrap := this[this.ov].Wwrap ? "+Wrap" : "+HScroll"
Gui, Font, s18, Consolas
Gui, Add, Custom, ClassRICHEDIT50W Section xm h300 w534 %begWwrap% +VScroll +hwndHRE +0x804 ;ES_READONLY = 0x800, ES_MULTILINE = 0x4
this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
OnSuch := this.RE_OnEvent.Bind(this)
GuiControl +g, %HRE%, % OnSuch
Gui, Show,, The Text Filter (Slim)
this.RenewGui(), WM_ACTIVATE(1) ;show content
}
sGui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
GuiControl, Move, Button5, % "x" (A_GuiWidth - 62)
GuiControl, Move, Button4, % "x" (A_GuiWidth - 102)
GuiControl, Move, Button3, % "x" (A_GuiWidth - 142)
GuiControl, Move, Edit1, % "w" (A_GuiWidth - 309)
GuiControl, Move, Button2, % "x" (A_GuiWidth - 182)
GuiControl, Move, Button1, % "x" (A_GuiWidth - 277)
}
sGui_OnEscape() {
%A_Gui%.GuiClose(A_Gui)
}
sGui_OnClose() {
%A_Gui%.GuiClose(A_Gui)
}
Fayt_OnTyping() {
v := this.ov, n := this[v].n
If IsFunc(this.eciwbeg)
{ this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
If not theNeedle = this[v].Needle[n]
ControlSetText, Edit1, % theNeedle
}
Gui, Submit, NoHide
this[v].Needle[n] := theNeedle := this.Fpat()
If StrLen(theNeedle)
this[v].Hs[n] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
Else this[v].Hs[n] := this.HsP(n)
this.RenewGui(theNeedle)
}
A_OnClick() {
this.ShowAssMatches()
ControlFocus, Edit1, A
}
T_OnClick() {
this.AssTreeView(this.id)
ControlFocus, Edit1, A
}
C_OnClick() {
v := this.ov
If not this[v].Linum
{ MsgBox, 4, Request Response, Context Peeking Needs Line Numbering`n`nTurn it on now ?
IfMsgBox, No
Goto, EndingThis
this[v].Linum := True, this.Linum_Sub1(), this.Linum_Sub2(), this.RenewGui(this.Fpat())
}
this.ContextPeek(this.id)
EndingThis:
ControlFocus, Edit1, A
}
F_OnClick() {
v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
this.GuiClose(this.id)
this.BuildGui(this.id)
GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
ControlSetText, Edit1, % this[v].Needle[n], A
this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
Send, {End}
}
SwitchToSlim() {
v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
this.GuiClose(this.id)
this.SlimGui(this.id)
ControlSetText, Edit1, % this[v].Needle[n], A
this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
Send, {End}
}
BuildGui(id) {
global NeedleCB
static Fayt, Case, Whole, Linum, Wwrap
v := this.ov
Gui, %id%:New, +Labeltf.Gui_On
Gui, +Delimiter`n
Gui, +Resize +MinSize +MaximizeBox
Gui, Font, s10, Arial New
Gui, Add, Text,, O p t i o n s:
begFayt := this[v].Fayt ? "Checked" : ""
Gui, Add, Checkbox, ym vFayt %begFayt% Tabstop, Instant Filter (aka Find As You Type)
OnSuch := this.Fayt_OnToggle.Bind(this)
GuiControl +g, Button1, % OnSuch
begCase := this[v].Case ? "Checked" : ""
Gui, Add, Checkbox, ym vCase %begCase% Tabstop, Case Insensitive
OnSuch := this.Case_OnToggle.Bind(this)
GuiControl +g, Button2, % OnSuch
begWhole := this[v].Whole ? "Checked" : ""
Gui, Add, Checkbox, ym vWhole %begWhole% Tabstop, Whole Word
OnSuch := this.Whole_OnToggle.Bind(this)
GuiControl +g, Button3, % OnSuch
begLinum := this[v].Linum ? "Checked" : ""
Gui, Add, Checkbox, ym vLinum %begLinum% Tabstop, Line Number
OnSuch := this.Linum_OnToggle.Bind(this)
GuiControl +g, Button4, % OnSuch
beg_Wrap := this[v].Wwrap ? "Checked" : ""
Gui, Add, Checkbox, ym vWwrap %beg_Wrap% Tabstop, Word Wrap
OnSuch := this.Wwrap_OnToggle.Bind(this)
GuiControl +g, Button5, % OnSuch
Gui, Font, s18, Arial New
Gui, Add, Text, xm Section, Filter:
w := A_ScreenWidth - 330
Gui, Add, ComboBox, w%w% ys vNeedleCB +hwndhEdit1
OnSuch := this.Fpat_OnTyping.Bind(this)
GuiControl +g, %hEdit1%, % OnSuch
Gui, Add, Button, h38 ys Default, Go
OnSuch := this.Go_OnClick.Bind(this)
GuiControl +g, Button6, % OnSuch
Gui, Font, s10, Arial New
Gui, Add, Button, h38 ys, Refresh
OnSuch := this.Refresh_OnClick.Bind(this)
GuiControl +g, Button7, % OnSuch
Gui, Font, s18, Arial New
Gui, Add, Button, h38 ys, Back
OnSuch := this.Back_OnClick.Bind(this)
GuiControl +g, Button8, % OnSuch
h := A_ScreenHeight - 143, w := A_ScreenWidth - 30, begWwrap := this[v].Wwrap ? "+Wrap" : "+HScroll"
Gui, Font, s18, Consolas
Gui, Add, Custom, ClassRICHEDIT50W x10 h%h% w%w% %begWwrap% +VScroll +hwndHRE +0x804 ;ES_READONLY = 0x800, ES_MULTILINE = 0x4
this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
OnSuch := this.RE_OnEvent.Bind(this)
GuiControl +g, %HRE%, % OnSuch
h := A_ScreenHeight - 64, w := A_ScreenWidth - 6
Gui, Show, h%h% w%w%, The Text Filter
this.RenewGui(), WM_ACTIVATE(1) ;show content
}
RE_OnEvent() {
global lbduration
v := this.ov
If not WinExist("The Text Filter")
Return
If (this[v].REseleT = this.RE.Selection.Text)
Return
If GetKeyState("RButton", "P")
Return
Sleep, 500 ;this "sleep" exists with reason
If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
Return
If not this[v].eFlag and this[v].Linum and WinActive("The Text Filter") and WinExist("Context Peeking | " this.id) and StrLen(this.RE.Selection.Text)
{ this[v].eFlag := True
n := this[v].n
slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, SelBegChar := this.RE.Range(slcs, slcs + 1).Text, SelEndChar := this.RE.Range(slce - 1, slce).Text, Hays := this.RE.Range(0, 999999999).Text
If InStr(A_Priorkey, "WheelUp")
this.RE.Range(slcs, slcs).Select
Else maybe := InStr("`r`n", SelEndChar) ? 1 : 0, this.RE.Range(slce - maybe, slce - maybe).Select
Sleep, 500
maybe := InStr("`r`n", SelBegChar) and (SelEndChar = A_Space) ? 2 : 1, mpos := this.ULoNLoCR(Hays, slcs + maybe)
slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
this.RE_PeekContext(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
}Else If not this[v].eFlag and WinActive("The Text Filter") and StrLen(this.RE.Selection.Text) and Clipboard not = this.RE.Selection.Text
{ this[v].eFlag := True, slcs := this.RE.Selection.Start
If InStr("`r`n", SubStr(this.RE.Selection.Text, 0))
this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
Else
{ MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
IfMsgBox, Yes
{ Clipboard := this.RE.Selection.Text
Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
If lbduration > 1000
{ ControlSetText, Edit1, % Trim(Clipboard)
ControlGetText, TextExists, Static1, % "ahk_id " WinExist("The Text Filter")
If TextExists
this.Fpat_OnTyping()
}
}IfMsgBox, No
this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
Sleep, 500 ;this "sleep" exists with reason
}
this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
}
}
RE_PeekContext(theOne) {
cpLnum := RegExReplace(theOne, "^\t? *?(\d+?):.*$", "$1")
If cpLnum is not digit
Return
v := this.ov, Hays := this[v].HaystackN, cpLend := RegExMatch(RegExReplace(Hays, "`n",,, cpLnum - 1), "`n") + cpLnum - 1, mpos := this.ULoNLoCR(Hays, cpLend), cpLbeg := mpos - 1, this[v].xFlag := True, this.CP.Range(cpLbeg, cpLend).Select, this.cpScroIntoView()
timer := ObjBindMethod(this, "OffxFlag")
SetTimer, % timer, -1000
}
OffxFlag() {
this[this.ov].xFlag := False
}
Gui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 95) " w" (A_GuiWidth - 14)
}
Gui_OnEscape() {
%A_Gui%.GuiClose(A_Gui)
}
Gui_OnClose() {
%A_Gui%.GuiClose(A_Gui)
}
GuiClose(id) {
Gui, %id%:Destroy
%id%.CleanUp(id)
}
CleanUp(id) {
IfExist, tf_%id%Work.rtf
FileDelete, tf_%id%Work.rtf
IfExist, tfHelp.rtf
FileDelete, tfHelp.rtf
}
GetTomDoc(HRE) { ;written by "@just me"
Static IID_ITextDocument := "{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}"
DocObj := 0
If DllCall("SendMessage", "Ptr", HRE, "UInt", 0x043C, "Ptr", 0, "PtrP", IRichEditOle, "UInt") ;EM_GETOLEINTERFACE
{ DocObj := ComObject(9, ComObjQuery(IRichEditOle, IID_ITextDocument), 1) ; ITextDocument
ObjRelease(IRichEditOle)
}
Return DocObj
}
Fayt_OnToggle() {
v := this.ov, n := this[v].n
If not (this[v].Fayt := this.Fayt())
If (this[v].Hs[n] != this.HsP(n))
{ this[v].Needle[n] := this.Fpat(), theHaystack := this[v].Hs[n]
n := (this[v].n += 1), this[v].Hs[n] := theHaystack
this.UpdateTitle()
}
ControlFocus, Edit1, A
this.Fpat_OnTyping()
}
Case_OnToggle() {
this[this.ov].Case := this.Case()
ControlFocus, Edit1, A
this.Fpat_OnTyping()
}
Whole_OnToggle() {
this[this.ov].Whole := this.Whole()
ControlFocus, Edit1, A
this.Fpat_OnTyping()
}
Linum_OnToggle() {
v := this.ov
If this[v].Linum := this.Linum()
this.Linum_Sub1()
Else this[v].Hs[0] := this[v].GetAddress("Haystack")
this.Linum_Sub2()
this.RenewGui(this.Fpat())
}
Linum_Sub1() {
v := this.ov
Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Line Numbering, Segoe UI
lsl := StrLen(this.LineCount())
HsN =
Loop, Parse, % this[v].Haystack, `n`r
HsN .= SubStr(this.StrRepeat(A_Space, lsl) A_Index, 1 - lsl) ":" A_Space A_LoopField "`n"
Progress, Off
this[v].HaystackN := HsN, this[v].Hs[0] := this[v].GetAddress("HaystackN")
}
Linum_Sub2() {
v := this.ov
Loop, % this[v].n
this[v].Hs[A_Index] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(A_Index), this[v].Needle[A_Index]) : RegExReplace(this.HsP(A_Index), this.Maker(this[v].Needle[A_Index]))
}
Wwrap_OnToggle() {
v := this.ov, this[v].Wwrap := this.Wwrap(), n := this[v].n, this[v].Needle[n] := this.Fpat()
this.BuildGui(this.id)
GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
ControlSetText, Edit1, % this[v].Needle[n], A
this.RenewGui(this[v].Needle[n])
Send, {End}
}
Fpat_OnTyping() {
v := this.ov, n := this[v].n
If IsFunc(this.eciwbeg)
{ this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
If not theNeedle = this[v].Needle[n]
ControlSetText, Edit1, % theNeedle
}
If not this[v].Fayt and not this[v].CommitLevel
Return
Gui, Submit, NoHide
this[v].Needle[n] := theNeedle := this.Fpat()
If not StrLen(theNeedle) and this[v].CommitLevel
{ this[v].CommitLevel := False, this.Back_OnClick()
Progress, Off
Return
}
theHaystack := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
If this[v].CommitLevel
{ If not StrLen(this[v].NeedleHistory)
this[v].NeedleHistory := theNeedle, Added := True
Else If not RegExMatch(this[v].NeedleHistory, (this[v].Case ? "i" : "") "m`a)^\Q" theNeedle "\E$")
this[v].NeedleHistory := theNeedle "`n" this[v].NeedleHistory, Added := True
Else Added := False
If Added
{ GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
ControlSetText, Edit1, % theNeedle
}
If (theHaystack = this.HsP(n))
Progress, zh0 w450 c10 fs18, `nResult No Change Thus Not Anew Level`n,, Prompt, Segoe UI
Else
{ If not this[v].Fayt
this[v].Hs[n] := theHaystack
If (this.LineCount(n) < 2) and not (theNeedle == this.NeeP(n))
Progress, zh0 w450 c10 fs18, `nUltimate/Empty Result Reached`nThus Level Not Advanced`n,, Prompt, Segoe UI
Else
{ n := (this[v].n += 1), this[v].Hs[n] := theHaystack
Send, ^a
}
}
this[v].CommitLevel := False
Sleep, 500
Progress, Off
}Else this[v].Hs[n] := theHaystack
this.RenewGui(theNeedle)
If not this[v].Fayt and not StrLen(this[v].Hs[n])
{ Progress, zh0 w450 c10 fs18, `nEmpty Result Reached`n`nFalling Back Now`n,, Prompt, Segoe UI
Sleep, 1000
this[v].Hs[n] := this.HsP(n)
ControlSetText, Edit1, % this.NeeP(n)
this.RenewGui(this.Fpat())
Send, ^a
Progress, Off
}
}
Maker(t) {
v := this.ov, t := this.tw4sh(t), r := (this[v].Case ? "i" : "") "m`a)^(?!"
Loop, Parse, t, % A_Space
If SubStr(A_LoopField, 1, 1) = "-"
r .= "(?!.*(" (this[v].Whole ? "\b" : "") SubStr(A_LoopField, 2) (this[v].Whole ? "\b" : "") "))"
Else r .= "(?=.*(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") "))"
r .= ").*\R?"
Return r
}
Go_OnClick() {
ControlFocus, Edit1, A
Progress, zh0 w380 c10 fs18, `nCommitting This Level`n,, Prompt, Segoe UI
this[this.ov].CommitLevel := True, this.Fpat_OnTyping()
}
Refresh_OnClick() {
this.RenewGui(this[this.ov].Needle[this[this.ov].n] := this.Fpat(), "retain")
}
Back_OnClick() {
ControlFocus, Edit1, A
v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat()
If (n = 1) and (this[v].Hs[n] != this.HsP(n))
this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
Else If (this[v].Hs[n] = this.HsP(n)) and (this[v].Needle[n] = this.NeeP(n))
If (n > 2)
n := (this[v].n -= 2)
Else If (n = 2)
n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
Else n := this[v].n := 0
Else n := (this[v].n -= 1)
If n
{ ControlSetText, Edit1, % this[v].Needle[n]
this.RenewGui(this[v].Needle[n])
Send, ^a
If (n = 1) and (this[v].Hs[n] = this.HsP(n))
{ Progress, zh0 w380 c10 fs18, `nReturned To The Origin`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
}Else
{ Progress, zh0 w380 c10 fs18, `nReturned To Level %n%`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
}
}Else this.Gui_OnClose()
}
Fpat() {
GuiControlGet, Fpat,, Edit1
If not StrLen(Fpat)
ControlGetText, Fpat, Edit1
Return Fpat
}
Fayt() {
GuiControlGet, Fayt,, Button1
If not StrLen(Fayt)
ControlGetText, Fayt, Button1
Return Fayt
}
Case() {
GuiControlGet, Case,, Button2
If not StrLen(Case)
ControlGetText, Case, Button2
Return Case
}
Whole() {
GuiControlGet, Whole,, Button3
If not StrLen(Whole)
ControlGetText, Whole, Button3
Return Whole
}
Linum() {
GuiControlGet, Linum,, Button4
If not StrLen(Linum)
ControlGetText, Linum, Button4
Return Linum
}
Wwrap() {
GuiControlGet, Wwrap,, Button5
If not StrLen(Wwrap)
ControlGetText, Wwrap, Button5
Return Wwrap
}
RenewGui(theNee := "", AMt := "") {
global lbduration
v := this.ov, n := this[v].n
If this.Fpat() not = theNee
Goto, WorkInterrupt
this.ToggleReadOnly(this.HRE, this[v].Wwrap)
If not this[v].PriorRefreshTime is digit
this[v].PriorRefreshTime := 0
If (AMt = "retain") and lbduration < 1000 and A_TickCount - this[v].PriorRefreshTime > 1000
theHays := this.RE.Range(0, 999999999).Text, this[v].PriorRefreshTime := A_TickCount, this[v].combed := False
Else If StrLen(AMt) and (AMt not = "retain")
theHays := this[v][AMt]
Else If IsFunc(this.Comb) and this.LineCount(n) < 1000 and lbduration < 1000
theHays := this.Comb(this[v].Hs[n]), this[v].combed := True
Else theHays := this[v].Hs[n], this[v].combed := False
ControlSetText, RICHEDIT50W1, %theHays%, A
indent := (StrLen(this.LineCount()) + 2) * 10, this.RE.Range(0, StrLen(theHays)).SetIndents(-indent, indent, 0)
If this.Fpat() not = theNee
Goto, WIP_Interrupt
r := this.MakerC(IsFunc(this.FlexRxR) ? (this[v].combed ? this[v].combed_r : this[v].r) : theNee)
If StrLen(theNee) and StrLen(r) and RegExMatch(theHays, r)
{ Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Matches Highlighting, Segoe UI
mpos := 1, mlen := 0
While, (mpos := RegExMatch(theHays, r, nm, mpos + mlen)) and (A_Index < 1000 or lbduration > 1000)
mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).Font.BackColor := 0x00FFFF, npos := mpos
lbduration := 0
Progress, Off
}
If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
{ Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assorted Matches Formatting, Segoe UI
mpos := 1, mlen := 0
While, (mpos := RegExMatch(theHays, "\R\d+\. .+?\R\K.+?(?=\R\d+\. .+|\R*$)", nm, mpos + mlen))
mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).SetIndents(-indent, indent * 2, 0), npos := mpos
Progress, Off
}
WIP_Interrupt:
this.ToggleReadOnly(this.HRE, this[v].Wwrap)
ControlFocus, Edit1, A
this.UpdateTitle()
WorkInterrupt:
GuiControlGet, TextExists,, Static2
If not TextExists
{ If StrLen(theNee)and StrLen(r) and RegExMatch(theHays, r)
RegExReplace(theHays, r,, mc)
Else mc := 0
ControlSetText, Button1, %mc%, A
}
If this.Fpat() not = theNee
If TextExists
this.Fpat_OnTyping()
Else this.Fayt_OnTyping()
}
UpdateTitle() {
WinSetTitle, The Text Filter, % ("", v := this.ov, Version := this[v].Version, id := this.id, n := this[v].n, lc := this.LineCount(n), SelectedFile := this[v].SelectedFile), The Text Filter (Version: %Version%) | %id% | Level %n% | Line Count: %lc% | %SelectedFile%
}
LineCount(n := 0) {
If n is digit
theHays := this.HsP(n + 1)
Else theHays := n
StrReplace(theHays, "`n",, lc), lc += StrLen(theHays) and SubStr(theHays, 0) != "`n" ? 1 : 0
Return lc
}
ToggleReadOnly(HRE, Wwrap) {
ControlGet, Style, Style,,, ahk_id %HRE%
If not (Style & 0x800)
SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HRE% ;tune Down BackgroundColor
SendMessage, 1101, 1, (Style & 0x800) ? (Wwrap ? 0x44 : 0xC4) : (Wwrap ? 0x844 : 0x8C4),, ahk_id %HRE% ;ES_READONLY = 0x800
If (Style & 0x800)
SendMessage, 0x443, 0, 0xEEFFFF,, ahk_id %HRE% ;light Up BackgroundColor
}
MakerC(theNee) {
theNee := this.tw4sh(theNee), r := "", v := this.ov
Loop, Parse, theNee, % A_Space
If SubStr(A_LoopField, 1, 1) != "-"
r .= "(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") ")|"
If StrLen(r)
{ If SubStr(r, 0) = "|"
r := SubStr(r, 1, StrLen(r) - 1)
r := (this[v].Case ? "i" : "") "m`a)" r
}
Return r
}
IncrFontSize() {
MouseGetPos, mpx, mpy,, moc
If (moc not = "RICHEDIT50W1")
MouseMove, 400, 200
Send, ^{WheelUp}
If (moc not = "RICHEDIT50W1")
MouseMove, mpx, mpy
}
DecrFontSize() {
MouseGetPos, mpx, mpy,, moc
If (moc not = "RICHEDIT50W1")
MouseMove, 400, 200
Send, ^{WheelDown}
If (moc not = "RICHEDIT50W1")
MouseMove, mpx, mpy
}
TakeThisLine(id := "RE") {
slcs := this[id].Selection.Start, slce := this[id].Selection.End, Hays := this[id].Range(0, 999999999).Text
If (slce > slcs)
{ Clipboard := this[id].Selection.Text
Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
Return
}
mpos := this.ULoNLoCR(Hays, slce + 1)
slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
this.FinalTouch(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
}
ULoNLoCR(hays, mpos) {
While, mpos > 1 and not InStr("`r`n", SubStr(hays, mpos - 1, 1))
mpos--
Return mpos
}
DLoNLoCR(hays, mpos) {
pmax := StrLen(hays)
While, mpos <= pmax and not InStr("`r`n", SubStr(hays, mpos, 1))
mpos++
Return mpos
}
FinalTouch(theOne) {
Clipboard := RegExReplace(theOne, "^\t?(?: *?\d+?: )?(.*)$", "$1")
If IsFunc(this.altTakeThisLine)
this.altTakeThisLine()
Else MsgBox,,, Has Put This Line Into Clipboard, 3
}
FindNextMatch(Reverse := 0) {
If StrLen(sPat := this.Fpat())
r := this.MakerC(IsFunc(this.FlexRxR) ? this[this.ov].r : sPat)
Else r := "nothing to be matched this"
slcs := this.RE.Selection.Start, slce := this.RE.Selection.End
If (slce > slcs) and (RegExMatch(A_ThisHotkey, "^\+?f$") and StrLen(sPat) ? False : not RegExMatch(this.RE.Selection.Text, r))
r := this.MakerS(this.RE.Selection.Text)
If StrLen(r) and RegExMatch(Hays := this.RE.Range(0, 999999999).Text, r)
{ StartHere:
slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, slcs++, slce++
cp := Reverse ? slcs : slce
If Reverse
{ If cp > 1
{ mpos := 0, pmax := cp - 1
Loop
{ npos := RegExMatch(Hays, r, pm, mpos + 1)
If npos between 1 and %pmax%
mpos := npos, nm := pm
Else Break
}
found := (npos > pmax) and mpos > 0
}
If not found
{ mpos := cp - 1, pmax := StrLen(Hays)
Loop
{ npos := RegExMatch(Hays, r, pm, mpos + 1)
If npos between %cp% and %pmax%
mpos := npos, nm := pm
Else Break
}
}
}Else mpos := RegExMatch(Hays, r, nm, cp)
mpos--
If mpos >= 0
{ cp := mpos + StrLen(nm)
this.RE.Range(mpos, cp).Select
}Else If (mpos < 0) and not Reverse
{ this.RE.Range(0, 0).Select
Goto, StartHere
}
}
}
MakerS(st) {
Return (StrLen(st), v := this.ov) ? (this[v].Case ? "i)" : "") (this[v].Whole ? "\b" : "") this.escrx(st) (this[v].Whole ? "\b" : "") : ""
}
WheelSearchMode() {
MouseGetPos,,,, moc
If not StrLen(moc) or not InStr("Edit1|RICHEDIT50W1", moc)
{ IfWinNotActive, The Text Filter
{ WinActivate % "ahk_id " this[this.ov].ParWin
WinWaitActive
}
ControlFocus, RICHEDIT50W1, A
this.FindNextMatch(InStr(A_ThisHotkey, "WheelUp"))
}
}
ShowAssMatches() {
If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
{ sPat := this.Fpat()
If this.RE.Range(19, 31).Text = "Alphabetical"
this.RenewGui(sPat, "AssHays")
Else this.RenewGui(sPat, "AAssHays")
Return
}
z := this.ov, n := this[z].n
If not StrLen(this[z].Hs[n]) or not StrLen(sPat := this.Fpat()) or not StrLen(r := this.MakerC(sPat))
Return
r := IsFunc(this.FlexRxR) ? this.MakerC(this[z].r) : r
Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assortment, Segoe UI
UniqMatches := [], Seq := 0, this[z].combed := IsFunc(this.Comb) and this.LineCount(n) < 1000
Loop, Parse, % this[z].Hs[n], `n`r
{ mpos = 1
worknm:
npos := RegExMatch(A_LoopField, r, nm, mpos), C_LoopField := this[z].combed ? Trim(this.Comb(A_LoopField)) : ""
If npos
{ If UniqMatches.HasKey(nm)
Ums := UniqMatches[nm], AssHays%Ums% .= InStr(AssHays%Ums%, A_LoopField) ? "" : ("`n" A_LoopField, cAssHays%Ums% .= this[z].combed ? "`n" C_LoopField : "")
Else
Seq++, UniqMatches[nm] := Seq, AssHays%Seq% := nm "`n" A_LoopField, cAssHays%Seq% := this[z].combed ? nm "`n" C_LoopField : ""
mpos := npos + StrLen(nm)
Goto, worknm
}
}
If Seq
{ UniqHays := tvAAssHays := cAAssHays := "", umNoSort := []
For k, v in UniqMatches
UniqHays .= "`n" this.StrRepeat(A_Space, 3) A_Index ".`t" k, tvAAssHays .= "`n" A_Index ". " AssHays%v%, cAAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%v% : "", umNoSort[v] ? umNoSort[v].Insert(k) : umNoSort[v] := k
AAssHays := "Assorted Matches:`t(Alphabetical Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAAssHays : tvAAssHays)
UniqHays := tvAssHays := cAssHays := ""
For k, v in umNoSort
UniqHays .= "`n" this.StrRepeat(A_Space, 3) k ".`t" v, tvAssHays .= "`n" A_Index ". " AssHays%k%, cAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%k% : ""
AssHays := "Assorted Matches:`t(Chronological Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAssHays : tvAssHays)
this[z].AssHays := AssHays, this[z].AAssHays := AAssHays, this[z].tvAssHays := tvAssHays, this[z].tvAAssHays := tvAAssHays
this.RenewGui(sPat, "AssHays")
}
Progress, Off
}
AssTreeView(id) {
If this.RE.Range(0, 19).Text not = "Assorted Matches:`t("
Return
parwin := this[v].ParWin := WinExist("A")
Gui, tv%id%:New, +Owner%parwin%
Gui, +Resize +MinSize +MaximizeBox
Gui, +Labeltf.tvGui_On
Gui, Font, s18, Consolas
Gui, Add, Text,, % this.RE.Range(19, 31).Text = "Alphabetical" ? "Assorted Matches: (Alphabetical Order)" : "Assorted Matches: (Chronological Order)"
;Gui, Add, Button, Hidden Default, Enter
Gui, Add, TreeView, AltSubmit Section xm w545
OnSuch := this.tvEventHdlr.Bind(this)
GuiControl +g, SysTreeView321, % OnSuch
Seq := 0, aHays := this.RE.Range(19, 31).Text = "Alphabetical" ? this[this.ov].tvAAssHays : this[this.ov].tvAssHays, lc := this.LineCount(aHays) - 1
Loop, Parse, aHays, `n`r
If StrLen(A_LoopField)
If RegExMatch(A_LoopField, "^ *\d+\.[ \t]")
Seq++, P%Seq% := TV_Add(A_LoopField), Num := 0
Else Num++, P%Seq%C%Num% := TV_Add(A_LoopField, P%Seq%)
Gui, Show, x97 y539 h283, TreeView Of Assorted Matches | %id% | Line Count: %lc%
GuiControl, Focus, SysTreeView321
}
tvGui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, SysTreeView321, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
}
tvGui_OnEscape() {
Gui, %A_Gui%:Destroy
}
tvGui_OnClose() {
Gui, %A_Gui%:Destroy
}
tvEventHdlr() {
If InStr("DoubleClick|S|K|Normal", A_GuiEvent)
TV_GetText(theOne, TV_GetSelection())
this[this.ov].theOne := theOne
If A_GuiEvent = DoubleClick
IfWinExist, % "Context Peeking | " this.id
this.RE_PeekContext(theOne)
Else this.tvButtonEnter()
}
tvButtonEnter() {
this.FinalTouch(this[this.ov].theOne)
}
PasteIntoHaystack() {
global _cwi_
If StrLen(Clipboard)
{ InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
If not ErrorLevel and StrLen(Trim(id))
{ If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
id := RegExReplace(id, "[-/]\s*[rR]$")
If RegExMatch(id, "[^\w=]")
id := RegExReplace(id, "[^\w=]")
If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
Return (Reverse ? "r)" id : id)
If InStr(id, "=")
MsgBox, Invalid Input
Else If (id = _cwi_)
this.start("Load Clipboard", Reverse)
Else Return (Reverse ? "r)" id : id)
}
}Else MsgBox, Clipboard is empty
}
OpenFile() {
global _cwi_
FileSelectFile, SelectedFile
If StrLen(SelectedFile)
{ InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
If not ErrorLevel and StrLen(Trim(id))
{ If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
id := RegExReplace(id, "[-/]\s*[rR]$")
If RegExMatch(id, "[^\w=]")
id := RegExReplace(id, "[^\w=]")
ido := (Reverse ? "r)" id : id)
If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
Return ido "`t" SelectedFile
If InStr(id, "=")
MsgBox, Invalid Input
Else If (id = _cwi_)
this.start("Load File " SelectedFile, Reverse)
Else Return ido "`t" SelectedFile
}
}
}
ReloadFile() {
If StrLen(SelectedFile := this[this.ov].SelectedFile)
{ If Reverse := (SubStr(SelectedFile, 1, 3) = "<R>")
SelectedFile := SubStr(SelectedFile, 4)
this.start("Load File " SelectedFile, Reverse)
}
}
RClickMenu() {
global lbduration
MouseGetPos, xb4, yb4
While, GetKeyState("RButton", "P")
Continue
MouseGetPos, rbx, rby, mow, moc
If Abs(rbx - xb4) > 10 or Abs(rby - yb4) > 10
Return
If (mow = (HGUI := WinExist("A"))) and rby > 30
If (moc = "Button8")
this.ShowTrail()
Else If (moc not = "Edit1")
{ Menu, myMenu, Add
Menu, myMenu, DeleteAll
If IsFunc(this.EditVars)
{ Menu, myMenu, Add, Edit Variables, MenuHandler
Menu, myMenu, Add
}
Menu, myMenu, Add, Show Assorted Matches, MenuHandler
If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
Menu, myMenu, Add, Put Assorted Matches In TreeView, MenuHandler
If this[this.ov].Linum and not WinExist("Context Peeking | " this.id)
{ Menu, myMenu, Add
Menu, myMenu, Add, Context Peeking, MenuHandler
}
Menu, myMenu, Add
Menu, myMenu, Add, Increase Font Size, MenuHandler
Menu, myMenu, Add, Decrease Font Size, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, Paste Into The Base, MenuHandler
Menu, myMenu, Add, Open A File, MenuHandler
Menu, myMenu, Add, Reload The File, MenuHandler
Menu, myMenu, Add
ControlGetText, TextExists, Static1, ahk_id %HGUI%
If TextExists
Menu, myMenu, Add, Switch To Slim Gui, MenuHandler
Else Menu, myMenu, Add, Switch To Full-Blown Gui, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, List Global Variables, MenuHandler
If (moc = "RICHEDIT50W1")
{ Menu, myMenu, Add
Menu, myMenu, Add, Copy The Line/Selection, MenuHandler
Menu, myMenu, Add, Go To Rightmost Of The Line, MenuHandler
Menu, myMenu, Add, Go To Leftmost Of The Line, MenuHandler
Menu, myMenu, Add, Go To The Bottom, MenuHandler
Menu, myMenu, Add, Go To The Top, MenuHandler
Menu, myMenu, Add, Page Down, MenuHandler
Menu, myMenu, Add, Page Up, MenuHandler
}
Menu, myMenu, Add
Menu, myMenu, Add, Downward Find Next Match, MenuHandler
Menu, myMenu, Add, Upward Find Next Match, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, Override The 1K Default, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, Show/Hide Help Page, MenuHandler
Menu, myMenu, Show
}
Return
MenuHandler:
WinWaitActive, ahk_id %HGUI%
If A_ThisMenuItem = Edit Variables
this.EditVars(this.id) ;basically for debugging purpose
Else If A_ThisMenuItem = Show Assorted Matches
this.ShowAssMatches()
Else If A_ThisMenuItem = Put Assorted Matches In TreeView
this.AssTreeView(this.id)
Else If A_ThisMenuItem = Context Peeking
this.ContextPeek(this.id)
Else If A_ThisMenuItem = Increase Font Size
this.IncrFontSize()
Else If A_ThisMenuItem = Decrease Font Size
this.DecrFontSize()
Else If A_ThisMenuItem = Paste Into The Base
Gosub, PasteHaySub
Else If A_ThisMenuItem = Open A File
Gosub, OpenFileSub
Else If A_ThisMenuItem = Reload The File
this.ReloadFile()
Else If A_ThisMenuItem = Switch To Slim Gui
this.SwitchToSlim()
Else If A_ThisMenuItem = Switch To Full-Blown Gui
this.F_OnClick()
Else If A_ThisMenuItem = List Global Variables
this.start(this.ListGlobalVars())
Else If A_ThisMenuItem = Copy The Line/Selection
{ If this.RE.Selection.End = this.RE.Selection.Start
MouseClick, Left, rbx, rby
this.TakeThisLine()
}Else If A_ThisMenuItem = Go To Rightmost Of The Line
{ MouseClick, Left, rbx, rby
Send, {End}
}Else If A_ThisMenuItem = Go To Leftmost Of The Line
{ MouseClick, Left, rbx, rby
Send, {Home}
}Else If A_ThisMenuItem = Go To The Bottom
{ MouseClick, Left, rbx, rby
Send, ^{End}
}Else If A_ThisMenuItem = Go To The Top
{ MouseClick, Left, rbx, rby
Send, ^{Home}
}Else If A_ThisMenuItem = Page Down
{ MouseClick, Left, rbx, rby
Send, {PgDn}
}Else If A_ThisMenuItem = Page Up
{ MouseClick, Left, rbx, rby
Send, {PgUp}
}Else If A_ThisMenuItem = Downward Find Next Match
{ ControlFocus, RICHEDIT50W1, A
this.FindNextMatch()
}Else If A_ThisMenuItem = Upward Find Next Match
{ ControlFocus, RICHEDIT50W1, A
this.FindNextMatch(1)
}Else If A_ThisMenuItem = Override The 1K Default
lbduration := 1234, this.RenewGui(this.Fpat(), "retain")
Else If A_ThisMenuItem = Show/Hide Help Page
this.ToggleHelpPage(this.id)
Return
}
ShowTrail() {
HGUI := WinExist("A"), v := this.ov, n := this[v].n
Menu, myTrail, Add
Menu, myTrail, DeleteAll
While, A_Index < n
{ tn := n - A_Index, theNeedle := this[v].Needle[tn], lc := this.LineCount(tn)
Menu, myTrail, Add, Level &%tn% remains %lc% lines after this filter: %theNeedle%, BtsLevel
}
lc := this.LineCount()
Menu, myTrail, Add, Origin %lc% lines (Level &0), BtsLevel
Menu, myTrail, Show
Return
BtsLevel:
WinWaitActive, ahk_id %HGUI%
n -= A_ThisMenuItemPos
If n < 1
n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
Else this[v].n := n
ControlSetText, Edit1, % this[v].Needle[n]
this.RenewGui(this[v].Needle[n])
Return
}
ToggleHelpPage(id) {
theFile = tf_%id%Work.rtf
If this.RE.Range(0, 17).Text = "H e l p _ P a g e"
IfExist, %theFile%
this.RE.Open(theFile, 0x01, 0)
Else this.RenewGui(this.Fpat())
Else
{ IfExist, %theFile%
this.RE.Save(0, 0, 0)
Else this.RE.Save(theFile, 0x01, 0)
helpfile = tfHelp.rtf
IfExist, % helpfile
FileDelete, % helpfile
FileAppend, % this.HelpPage(), % helpfile
this.RE.Open(helpfile, 0x01, 0)
}
}
ContextPeek(id) {
v := this.ov
If not this[v].Linum
Return
parwin := this[v].ParWin := WinExist("A")
Gui, cp%id%:New, +Owner%parwin%
Gui, +Resize +MinSize +MaximizeBox
Gui, +Labeltf.cpGui_On
Gui, Font, s12, Arial New
Gui, Add, Button,, Close
OnSuch := this.cpBclose.Bind(this)
GuiControl +g, Button1, % OnSuch
Gui, Add, Button, ys, Maximize
OnSuch := this.cpBmaxim.Bind(this)
GuiControl +g, Button2, % OnSuch
Gui, Add, Button, ys, Restore
OnSuch := this.cpBresto.Bind(this)
GuiControl +g, Button3, % OnSuch
Gui, Add, Button, ys, Minimize
OnSuch := this.cpBminim.Bind(this)
GuiControl +g, Button4, % OnSuch
Gui, Font, s18, Consolas
Gui, Add, Custom, ClassRICHEDIT50W xm Section +Wrap +VScroll +hwndHCP +0x804 ;ES_READONLY = 0x800, ES_MULTILINE = 0x4
this.HCP := HCP, this.CP := this.GetTomDoc(HCP)
OnSuch := this.cpEventHdlr.Bind(this)
GuiControl +g, RICHEDIT50W1, % OnSuch
x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6, lc := this.LineCount()
Gui, Show, x%x% y51 h%h% w%w%, Context Peeking | %id% | Line Count: %lc%
Progress, zh0 w300 c10 fs18, `nHang On...`n,, Loading Origin, Segoe UI
GuiControl,, RICHEDIT50W1, % this[v].HaystackN
GuiControl, Focus, RICHEDIT50W1
this.ToggleReadOnly(this.HCP, this[v].Wwrap)
indent := (StrLen(lc) + 2) * 10, this.CP.Range(0, StrLen(this[v].HaystackN)).SetIndents(-indent, indent, 0)
SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HCP% ;tune Down BackgroundColor
this.ToggleReadOnly(this.HCP, this[v].Wwrap)
Progress, Off
}
cpScroIntoView() {
GuiControlGet, gCPg, Pos, % this.HCP
this.CP.Selection.ScrollIntoView(0), slcs := this.CP.Selection.Start, slce := this.CP.Selection.End
this.CP.Range(cp := this.CfromP(this.HCP, 1, this.PfromC(this.HCP, slcs) + gCPgH / 2), cp).Select
WinActivate, % "Context Peeking | " this.id
WinWaitActive
this.CP.Range(slcs, slce).Select
this[this.ov].CPseleT := this.CP.Selection.Text
}
CfromP(hE, x := -1, y := -1) {
VarSetCapacity(RECT, 16, 0)
SendMessage 0xB2,, &RECT,, ahk_id %hE% ;EM_GETRECT
LefP := NumGet(RECT, 0, "Int"), TopP := NumGet(RECT, 4, "Int"), RigP := NumGet(RECT, 8, "Int"), BotP := NumGet(RECT, 12, "Int")
VarSetCapacity(PoL, 8, 0), NumPut(x < 0 ? RigP : x, PoL,, "Int"), NumPut(y < 0 ? BotP : y, PoL, 4, "Int")
SendMessage 0xD7,, &PoL,, ahk_id %hE% ;EM_CHARFROMPOS
Return ErrorLevel
}
PfromC(hE, i) {
VarSetCapacity(PoL, 8, 0)
SendMessage 0xD6, &PoL, i,, ahk_id %hE% ;EM_POSFROMCHAR
Return NumGet(PoL, 4, "Int")
}
cpGui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 65) " w" (A_GuiWidth - 30)
}
cpGui_OnEscape() {
Gui, %A_Gui%:Destroy
}
cpGui_OnClose() {
Gui, %A_Gui%:Destroy
}
cpBclose() {
Gui, %A_Gui%:Destroy
}
cpBmaxim() {
WinGet, wMM, MinMax, A
If wMM = 1 ;already maximized
WinRestore, A
Else WinMaximize, A
GuiControl, Focus, RICHEDIT50W1
}
cpBresto() {
static x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6
WinGet, wMM, MinMax, A
If wMM = 0 ;already restored
{ WinGetPos, GuiX,,,, A
If (GuiX + x >= A_ScreenWidth)
Gui, Show, x-5 y51 h%h% w%w%
Else Gui, Show, x%x% y51 h%h% w%w%
}Else WinRestore, A
GuiControl, Focus, RICHEDIT50W1
}
cpBminim() {
WinMinimize, A
}
cpEventHdlr() {
global lbduration
IfWinActive, Context Peeking
{ ControlGetFocus, foco, A
If (foco not = "RICHEDIT50W1")
{ MouseGetPos,,, mow, moc
If not (mow = WinExist("Context Peeking") and InStr(moc, "Button"))
GuiControl, Focus, RICHEDIT50W1
}
}
v := this.ov
If (this[v].CPseleT = this.CP.Selection.Text)
Return
If GetKeyState("RButton", "P")
Return
Sleep, 500 ;this "sleep" exists with reason
If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
Return
If not this[v].xFlag and WinActive("Context Peeking") and StrLen(this.CP.Selection.Text)
{ this[v].xFlag := True, slcs := this.CP.Selection.Start
If InStr("`r`n", SubStr(this.CP.Selection.Text, 0))
this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
Else
{ MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
IfMsgBox, Yes
{ Clipboard := this[v].CPseleT := this.CP.Selection.Text
Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
If lbduration > 1000
{ WinMinimize
ControlSetText, Edit1, % Trim(Clipboard), % "ahk_id " this[v].ParWin
}
}IfMsgBox, No
this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
Sleep, 500 ;this "sleep" exists with reason
}
this[v].xFlag := False, this[v].CPseleT := this.CP.Selection.Text
}
}
tw4sh(t) {
tog := "\/", va := "?\\'\w", ph := "[^" va "\n]", tar := "\" tog ph "*?\K[" va "]", ph := "[^\w\n]"
If mpos:=RegExMatch(t, tar) ;contained toggle (on)
{ pb := "[^\w\n]", sh := "((?<=^|" ph ")", st := "(?=(\W|$)))"
skip_c := skip_w := yb := False
r := StrReplace(SubStr(t, 1, mpos - 1), tog) sh, rr := xx := ""
Loop
{ c := SubStr(t, mpos, 1), cc := SubStr(t, mpos + 1, 1)
If skip_c
skip_c--
Else If SubStr(t, mpos, StrLen(tog)) = tog ;toggle (off) encountered
{ this.flush(r, xx, pb, yb, st), rr := xx := ""
mpos += StrLen(tog), npos := mpos
If mpos:=RegExMatch(t, tar,, npos) ;found next toggle (on)
r .= StrReplace(SubStr(t, npos, mpos - npos), tog) sh, rr := xx := ""
Else
{ r .= SubStr(t, npos)
Break
}
Continue
}Else If RegExMatch(c, "\w") or (c = "?") ;valid character
{ If rr
If not skip_w and ((cc not = "/") or StrLen(xx))
this.flush(r, xx, pb, yb)
Else If (cc = "/") and not StrLen(xx)
{ If SubStr(t, mpos + 2, 1) = "/"
skip_w := skip_w ? skip_w : True, skip_c++
skip_c++
}Else{}
Else If StrLen(rr)
r .= xx sh, rr := xx := ""
r .= (c = "?") ? (skip_w ? "\w" : ("\w+?", yb++)) : c (skip_w ? "" : ("\w*?", yb++)), skip_w -= skip_w ? 1 : 0, rr := True
}Else If (c = A_Space) and rr
this.flush(r, xx, pb, yb, st), xx := A_Space, rr := 0
Else If (c = "'")
xx .= "\W"
Else If (c = "\") and skip_w not < 0
If (cc == "Q")
skip_c++, skip_w := -1, this.flush(r, xx, pb, yb)
Else If (cc == "E")
skip_c++, skip_w := False
Else If (cc = c)
xx .= c
Else If RegExMatch(cc, "\w")
skip_c++, xx .= cc
Else skip_c++, xx .= c cc
Else xx .= c
mpos++
If (mpos > StrLen(t)) ;exceeded
{ If rr
this.flush(r, xx, pb, yb, st), rr := xx := ""
Break
}
}
}Else r := t
Return r
}
flush(ByRef r, ByRef xx, pb, ByRef yb, st := "") {
mb := "[^,;\w\n.?!]+?", ss := SubStr(xx, -1), sc := (ss == "\W") or (ss == "\s") or (ss == "\t") or (ss == "\r") or (ss == "\n"), r .= xx ? (RegExMatch(SubStr(xx, 1, 1), "\w") ? mb : pb "*?") xx (st ? ")" : (RegExMatch(ss, "\\?\w$") and not sc ? "" : pb "*?")) : (st ? st : (yb ? (mb, yb--) : "")), xx := ""
}
StrRepeat(string, times) {
Loop, %times%
output .= string
Return output
}
escrx(h) {
e := "\().[]*+?{}^$|"
Loop, Parse, e
If InStr(h, A_LoopField)
h := StrReplace(h, A_LoopField, "\" A_LoopField)
Return h
}
ReverseByLine(ByRef text, delimiter := "`n") {
array := StrSplit(SubStr(text, 0) = delimiter ? SubStr(text, 1, StrLen(text) - 1) : text, delimiter), mi := array.MaxIndex()
Loop, % mi
If A_Index > 1
text .= array[mi - A_Index + 1] delimiter
Else text := array[mi] delimiter
}
ListGlobalVars() { ;written by Lexikos
static hwndEdit, pSFW, pSW, bkpSFW, bkpSW
If !hwndEdit
{ dhw := A_DetectHiddenWindows
DetectHiddenWindows, On
Process, Exist
ControlGet, hwndEdit, Hwnd,, Edit1, ahk_class AutoHotkey ahk_pid %ErrorLevel%
DetectHiddenWindows, %dhw%
astr := A_IsUnicode ? "astr":"str"
ptr := A_PtrSize=8 ? "ptr":"uint"
hmod := DllCall("GetModuleHandle", "str", "user32.dll")
pSFW := DllCall("GetProcAddress", ptr, hmod, astr, "SetForegroundWindow")
pSW := DllCall("GetProcAddress", ptr, hmod, astr, "ShowWindow")
DllCall("VirtualProtect", ptr, pSFW, ptr, 8, "uint", 0x40, "uint*", 0)
DllCall("VirtualProtect", ptr, pSW, ptr, 8, "uint", 0x40, "uint*", 0)
bkpSFW := NumGet(pSFW+0, 0, "int64")
bkpSW := NumGet(pSW+0, 0, "int64")
}
If (A_PtrSize=8)
{ NumPut(0x0000C300000001B8, pSFW+0, 0, "int64") ;return TRUE
NumPut(0x0000C300000001B8, pSW+0, 0, "int64") ;return TRUE
}Else
{ NumPut(0x0004C200000001B8, pSFW+0, 0, "int64") ;return TRUE
NumPut(0x0008C200000001B8, pSW+0, 0, "int64") ;return TRUE
}
ListVars
NumPut(bkpSFW, pSFW+0, 0, "int64")
NumPut(bkpSW, pSW+0, 0, "int64")
ControlGetText, text,, ahk_id %hwndEdit%
RegExMatch(text, "sm)(?<=^Global Variables \(alphabetical\)`r`n-{50}`r`n).*", text)
Return text
}
HelpPage() {
HelpPage=
(
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil\fcharset0 Consolas;}}
{\colortbl ;\red255\green0\blue0;\red155\green0\blue211;\red0\green77\blue187;\red0\green176\blue80;\red0\green0\blue255;}
{\*\generator Riched20 10.0.19041}\viewkind4\uc1
\pard\sa200\sl276\slmult1\b\fs36\lang9 H e l p _ P a g e\b0\par
\par
\cf1\b F1\cf0\b0 - to toggle this help page\par
\par
\b Basic syntax by example:\b0\par
\pard\li720\sa200\sl276\slmult1 coexisting words/strings/patterns -unwanted\par
for instance, \cf2\b\f1 d.*d -the and -oo \\ws\cf0\b0\f0\par
(the 5 segments (space separated) above can go all at once, and yet, they can also be entered one by one. that's the so-called multilevel approach, instead.)\par
\pard\sa200\sl276\slmult1\par
\b Feature keys:\b0\par
\pard\li720\sa200\sl276\slmult1\cf3\b Alt+a\cf0\b0 - to show assorted matches and toggle between chronological and alphabetical order.\par
\cf3\b Ctrl+t\cf0\b0 - to put assorted matches into a treeview gui which may ease the exploration when the list is long and involved multiple groups.\par
\cf3\b Ctrl+p\cf0\b0 - to bring up context peeking gui which provides an integrated way of reviewing the context of any lines in the shortlisted result.\par
\cf3\b WheelDown\cf0\b0 - to find the next match (downward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b WheelUp\cf0\b0 - to find the next match (upward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b Alt+v\cf0\b0 - to paste clipboard content into the big text/edit box.\par
\cf3\b Ctrl+o\cf0\b0 - to open a file.\par
\cf3\b Ctrl+r\cf0\b0 - to reload the file.\par
\cf3\b Rightclick\cf0\b0 "Back" button - to glance committed levels and select one to fall back to.\par
\cf3\b Esc\cf0\b0 - to quit/exit/leave. same as closing the window.\par
\cf3\b Tab\cf0\b0 - to change focus between the text/edit boxes (just try it.)\par
\par
these below only work when the \ul big\ulnone text/edit box is in focus:\par
\pard\li1440\sa200\sl276\slmult1\cf3\b f\cf0\b0 - to find the next match (downward) from the caret position.\par
\cf3\b Shift+f\cf0\b0 - to find the next match (upward) from the caret position.\par
\i (note: "the line" refers to the current line, that's where the caret is on.)\i0\par
\cf3\b Doubleclick\cf0\b0 - to copy the line/selection.\par
\cf3\b Enter\cf0\b0 - to copy the line/selection.\par
\cf3\b Space\cf0\b0 - to page down\par
\cf3\b Shift+Space\cf0\b0 - to page up\par
\cf3\b s\cf0\b0 - to move the caret to the beginning/start of the line.\par
\cf3\b e\cf0\b0 - to move the caret to the end of the line.\par
\cf3\b t\cf0\b0 - to move the caret to the top of the text.\par
\cf3\b b\cf0\b0 - to move the caret to the bottom of the text.\par
\cf3\b + or =\cf0\b0 - to increase font size (same as \cf3\b Ctrl+WheelUp\cf0\b0 ).\par
\cf3\b minus "-"\cf0\b0 - to decrease font size (same as \cf3\b Ctrl+WheelDown\cf0\b0 ).\par
\i (side note: "caret" may be known as "cursor" to some people.)\i0\par
\pard\sa200\sl276\slmult1\par
\tab these below only work when the \ul small\ulnone text/edit box is in focus:\par
\pard\li1440\sa200\sl276\slmult1\cf3\b Enter\cf0\b0 - to commit a level (which makes the current result becoming the base/source of the next level.) same as clicking the button Go.\par
\pard\sa200\sl276\slmult1\par
\pard\li720\sa200\sl276\slmult1\cf3\b Backtick (``)\cf0\b0 - since users mostly use this tool to locate the specific line of text and copy it for whatever subsequent actions to be taken, which typically involves Tab and then Enter (if the first line is the one wanted), backtick is an alternative which can supersede both keys by just hit backtick twice instead.\par
\pard\sa200\sl276\slmult1\par
The \b improvised shorthand\b0 feature:\par
\pard\li720\sa200\sl276\slmult1 this feature can be triggered through "\cf2\b\\/\cf0\b0 " (a \b backslash\b0 followed by a \b slash\b0 ), a "regex like" syntax style, which toggle it on or off. so, enter "\cf2\b\\/tr\cf0\b0 " will bring you those lines contained "\cf4\i the road\cf0\i0 ", "\cf4\i two roads\cf0\i0 ", as well as "\cf4\i them really\cf0\i0 " out of the poem, whereas enter "\cf2\b oo \\/a?a\cf0\b0 " or "\cf2\b\\/a?a\\/ oo\cf0\b0 " will return you these two lines "\cf4\i And looked down one as far as I could\cf0\i0 " and "\cf4\i Then took the other, as just as fair,\cf0\i0 " in which, the "\cf2\b ?\cf0\b0 " represents any valid character regex recognized it as "word" element. Besides, the space has been cared so that the toggle works across it. for instance, enter "\cf2\b\\/tr yw\cf0\b0 " or "\cf2\b\\/yw tr\cf0\b0 " will show this line "\cf4\i Two roads diverged in a yellow wood,\cf0\i0 " where the space is still a separator as always, even though the shorthand feature is toggled on.\par
\pard\sa200\sl276\slmult1\par
\tab three more elements of the shorthand syntax:\par
\par
\pard\fi-360\li1800\sa200\sl276\slmult1 1, \b extra qualifier\b0 (within a single word);\par
2, \b escape character\b0 (between words);\par
3, a single \b character\b0 representing any "\b non-word\b0 " one (between words).\par
\pard\sa200\sl276\slmult1\par
\pard\li720\sa200\sl276\slmult1 the most basic usage of improvised shorthand is to match the specific "phrase" by just entering the first letter of each word constituted it (for instance, "\cf2\b sameto\cf0\b0 " can match "\cf4\i some are more equal than others\cf0\i0 ") yet sometimes we may want to further narrow down the result. if "\cf2\b slh\cf0\b0 " brings you both "\cf4\i she likes him\cf0\i0 " and "\cf4\i she loves him\cf0\i0 ", an extra qualifier to pinpoint one may be useful. it could simply be a "v" for this example hence "\cf2\b slv/h\cf0\b0 " (in which, the "/" after the "v" tells the system that it's just an extra qualifier to the "l", not for a word starts with "v",) returns you "\cf4\i she loves him\cf0\i0 " only. likewise, you may sometimes want to tell the system exactly what the word should be ending with, for instance, if "\cf2\b ioy\cf0\b0 " brings you both "\cf4\i i owe you\cf0\i0 " and "\cf4\i i own you\cf0\i0 ", "\cf2\b ioe//y\cf0\b0 " (in which, the "//" after the "e" tells the system that it's a word ending character, that is, "oe//" represents a word starts with "o" and ends with "e") returns you "\cf4\i i owe you\cf0\i0 " only. and no matter how rare (and impractical) it may be, you may have multiple of these qualifiers for a word, such as, "\cf2\b cm/c/e//d//\cf0\b0 " can match the word "\cf4\i complicated\cf0\i0 " whereas "\cf2\b td/i/u//s//\cf0\b0 " can match the word "\cf4\i tedious\cf0\i0 ".\par
\par
a \b backslash\b0 "\cf2\b\\\cf0\b0 " may be used to escape a single character after it. its target should be a "word" character because you don't need to escape otherwise. for all "non-word" character, just enter them directly except "\\" itself which requires a \b double backslash\b0 "\cf2\b\\\\\cf0\b0 " for a single one. for regex syntax such as "\\s", it becomes "\\\\s" (not "\\\\\\s" you may presume.) in other words, all escaped character will only be matched barely itself. for \ul consecutive\ulnone "word" characters that need to be escaped, enclose them in the \cf2\b\\Q\cf0\b0 \cf2\b\\E\cf0\b0 pair, similar idea as in regex. one thing to note though, escaped character may affect the word immediately after it, for instance, "\cf2\b z\\xy\cf0\b0 " may bring you "\cf4\i zebra xylophone\cf0\i0 " rather than "\cf4\i zombie x yesterday\cf0\i0 ".\par
\par
an \b apostrophe\b0 "\cf2\b\f1 '\cf0\b0\f0 " may be used to represent any "non-word" character. that is, same as "\\\\W" (the regex syntax "\\W" for a "non-word" character). it may be useful at the (beginning and/or ending) ends of the "phrase" if it can further narrow down the result or you simply want it to be a part of the match.\par
\pard\sa200\sl276\slmult1\par
The \b matches highlighting\b0 feature:\par
\pard\li720\sa200\sl276\slmult1 the \ul default behavior\ulnone is to highlight no more than a thousand matches (which can improve the response time when too many matches are found.) it can nonetheless be overridden by a long press of your left mouse button on one of the available gui buttons (i.e. go or refresh or back), whereas long press means press it down and hold on for \ul one second or longer\ulnone . therefore, highlighting will cover the whole thing even if the total number of matches is over \ul one thousand\ulnone . this \ul long-press-to-override\ulnone is not a toggle, it's just an \ul one-off\ulnone thing, so do it every time you want more than the default.\par
\pard\sa200\sl276\slmult1\par
End of this help page.\par
}
)
Return HelpPage
}
} ;end of class
Last edited by SundayProgrammer on 11 Jul 2021, 00:14, edited 4 times in total.
- Kellyzkorner_NJ
- Posts: 84
- Joined: 20 Oct 2017, 18:33
Re: Text Filter
Hi, that's great! Thanks for keeping an eye on out that.SundayProgrammer wrote: ↑20 Jun 2021, 23:47i think i have found the "Oops..." problem of my "wm_activate" function, which requires myself or any developers using this to note about. that is, at the moment when a window is created, its title doesn't meet the "wm_activate" checking. and it only becomes "met" (the checking) thereafter by changing/updating its title which won't trigger "wm_activate" to update the global variable "_cwi_".SundayProgrammer wrote: ↑07 Jun 2021, 13:09hi @Kellyzkorner_NJ, thank you for letting me know the error. i myself did hit this a few times during testing, but can never repeat it immediately. are you having this problem consistently?
by the way, the _cwi_ (current window id) global variable is set by the wm_activate function via onmessage. the "other windows" message simply means the active window is other than those created from the "tf" object (the text filter and its associated windows).
two ways to fix it: either make sure the window title meets the "wm_activate" checking at the moment when the window is born, or execute "wm_activate(1)" after its window title becomes "met".
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
the script is updated. → viewtopic.php?p=406242#p406242 ← click this link
star-two-a made three tweaks.
star-two-a made three tweaks.
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
the script is updated. → viewtopic.php?p=406242#p406242 ← click this link
star-two-b added a feature to load the text in reverse order, by line.
star-two-b added a feature to load the text in reverse order, by line.
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
the script is updated. → viewtopic.php?p=406242#p406242 ← click this link
star-two-c two adjustments are made, and a trivial feature is added.
star-two-c two adjustments are made, and a trivial feature is added.
Re: Text Filter
I feel like this would be better if you could make a simple function or class to use this feature, also please update the initial post where the example script is still not updated.
I have also learned that not eveyone will enjoy the given GUI, they prefer to create their own one or just add a feature to their own GUIs.
that's just my 2 cents great work, I can see you are dedicated.
I have also learned that not eveyone will enjoy the given GUI, they prefer to create their own one or just add a feature to their own GUIs.
that's just my 2 cents great work, I can see you are dedicated.
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
i'm not. very kind, thank you.
not sure what exactly you referring to:
about "this feature" << the trivial one from star-two-c ?
about "initial post ... example script" << the one in the very first post of this topic/thread ?
i'm actually interested to know what feature people like/dislike. (it will be a bonus to me.)
btw, i wonder where did you learn it from ? i wanted to learn it too.
i will absolutely be delighted if people can share with me how their own gui looks like. (hoped people have the time and feel okay to do it.)
Re: Text Filter
This is one of my projects I use frequently, I think I also posted a very simple example GUI here on the forum.
https://ibb.co/6t5ypyW
This search system is not very complex but not as simple as using If InStr() as you can see. It can also search via youtube, google, amazon just by typing a prefix (in my case: "y ", "g ", "a ") ofcourse this has nothing to do with your script, just making my point of why people prefer a simple function or class so that they can use as an add-on to their scripts.
https://ibb.co/6t5ypyW
This search system is not very complex but not as simple as using If InStr() as you can see. It can also search via youtube, google, amazon just by typing a prefix (in my case: "y ", "g ", "a ") ofcourse this has nothing to do with your script, just making my point of why people prefer a simple function or class so that they can use as an add-on to their scripts.
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
thank you. although i did not click the link, my best guess is, it's a screenshot of your project. would you mind to paste/upload it directly ? anyhow, thank you.fenchai wrote: ↑14 Jul 2021, 10:47This is one of my projects I use frequently, I think I also posted a very simple example GUI here on the forum.
https://ibb.co/6t5ypyW
This search system is not very complex but not as simple as using If InStr() as you can see. It can also search via youtube, google, amazon just by typing a prefix (in my case: "y ", "g ", "a ") ofcourse this has nothing to do with your script, just making my point of why people prefer a simple function or class so that they can use as an add-on to their scripts.
Re: Text Filter
sure,
cool trick, thanks
cool trick, thanks
Last edited by fenchai on 15 Jul 2021, 08:56, edited 1 time in total.
Re: Text Filter
Our img-tags won't work with links to html pages acting as a container. To use the img-tags, you have to use a direct link ending on .jpg or .png.
Often, right-clicking the picture and selecting 'open picture in separate tab', or alike, can get you the needed link. In this case, you'd get https://i.ibb.co/HPQKMKH/Snipaste-2021-07-14-10-42-41.png:
Afaik, uploding pictures directly to the forum should work again, too.
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
star-three
added a feature for non-alphabetic language (such as 漢字) which enables users to directly enter ime code to search for its corresponding word(s). i call it "user defined matching".
as a consequence, an external file, the udmtable.txt is added (along with the script) for this feature.
currently, two sets of ime code are available in the udmtable. and i think it should not be too difficult for you to add your own/favorites.
the feature currently assumed the target word is all "one character" long. the script can nonetheless be easily adjusted to cater for variable length with a slight modification.
two consecutive apostrophe is the mark for the beginning/ending of any ime code search term. you may also use a single apostrophe in the middle to add extra search term for the same word.
examples:
- ''fung'' then ''fung4'' then ''fung''hei''
- ''leun4'' ''gong''
- ''sqf'' then ''imsqf''
- e''hdr''f
i prepared 10 screenshots of the examples above, but it seems to me that there is a ceiling of 3 attachments only. so, may be i spread them in separate posts after this.
that's it for now.
added a feature for non-alphabetic language (such as 漢字) which enables users to directly enter ime code to search for its corresponding word(s). i call it "user defined matching".
as a consequence, an external file, the udmtable.txt is added (along with the script) for this feature.
the feature currently assumed the target word is all "one character" long. the script can nonetheless be easily adjusted to cater for variable length with a slight modification.
two consecutive apostrophe is the mark for the beginning/ending of any ime code search term. you may also use a single apostrophe in the middle to add extra search term for the same word.
examples:
- ''fung'' then ''fung4'' then ''fung''hei''
- ''leun4'' ''gong''
- ''sqf'' then ''imsqf''
[spoiler3=''sqf'']
[/spoiler3][spoiler3=''imsqf'']
- ''si'' then ''si6'' then ''si6'a'' [/spoiler3]- e''hdr''f
i prepared 10 screenshots of the examples above, but it seems to me that there is a ceiling of 3 attachments only. so, may be i spread them in separate posts after this.
that's it for now.
Code: Select all
SetWorkingDir %A_ScriptDir%
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
theArticle=
(
是新生,是醒覺,夢想永遠在世上
壹傳媒結業,評論人擱筆,專頁紛紛消失。七日內,香港萬馬齊喑,新聞千人一面,這時候,我們還可以做什麼?
前兩日,老朋友打電話來,也問我今後做什麼。寫專欄前,我其實有幾份工作,其一是兼職侍應洗碗——那時候,剛和朋友合資經營一間「另類」餐廳,一腳踢,故事說來話長,有機會再寫。
問我做什麼,我於是隨口答:「冇得寫,最多咪洗碗。」聰明的你,該看得出我是說笑,但朋友果然夠朋友,竟認真沉思片刻,然後鄭重回應:「洗碗呀⋯⋯er⋯⋯咁我都信你識洗碗嘅,不過嘥你時間囉。」
我馬上怒吼:「頂你,咩叫『咁我都信你嘅』?如果我話噚晚見到外星人,你答『咁我都信你嘅』就情有可原。但洗碗咋喎,你使唔使講個『信』字呀?你不如話『我可以大膽咁講,你係識洗碗嘅』吖笨。」
雖然反駁得字字鏗鏘,但我其實很心虛:我真是懂得洗碗嗎?記得幼稚園老師常向家母投訴,指控我連剪刀也不懂用,疑心我弱智。十多年前出於好奇,我到工聯會學開鎖,上到第二堂就把鎖弄壞,連老師也開不到。我真係識洗碗?其實我都唔可以咁大膽講。
「我可以做什麼?」除了我,相信最近很多人,不管是移民抑或留下的,都在問。其實我早有答案。二〇一九年我寫過一篇專欄,講方展博如何打敗丁蟹,參照《大時代》劇情,探討人在最壞的時代該做什麼,結論是三件事:
一、唔好死;二、等運到;三,找到自己的世界,投入其中,瘋狂做自己最擅長、最有興趣的事,令自己不斷進步、天天變強。方展博做到這三件事,所以活下來,得到最後勝利。
「唔好死」是本能,「等運到」是無為,大家很容易參透,不必細表。但怎樣才能「找到自己的世界」呢?這問題不是今天獨有,自從盤古初開,人生於世,就一直要面對這個涉及存在的難題。
方展博沒解釋怎知道哪裏是自己的世界,但觀眾可分析出來:他一踏足交易所,即兩眼放光,樂而忘返,彷彿有用不盡的精力——能帶給你無限熱情的,就是你的世界。躺平,什麼也不做,睡到自然醒,你可能覺得這種生活很寫意很ok,但聽過有人會為此興奮嗎?躺平只是眼光光,絕不會兩眼放光。
有熱情的人都很努力,但不知道自己在努力。如果你要很努力地努力,你並沒找到自己的世界。在自己的世界不知疲倦,除了因為熱血沸騰,也因為你在做自己擅長的事,即是說,你在發揮才華,做別人覺得艱難、你卻一蹴而就的事。
沒找到自己的世界,即沒發現自己的才華。這確是難題。我不想無底線地講勵志話,所以必須跟你說:人人都有才華,也可培養才華,但歸根究底,你還是需要一點運氣,方能發現才華。你有,不等於別人看到,甚至不等於你自己知道。
以我為例,在《蘋果日報》由零開始,天天筆耕,朋友問我:「怎可以這樣天天寫?有題材嗎?」都覺得不可思議,我也難以置信。我若說自己沒寫作才華,未免虛偽,但我可以誓神劈願說:寫專欄前,我完全沒發現自己有這能力。我是意外被拋進自己的世界的。
按常理,我不可能在一份香港最多人看的報紙,跟那些成名多年的作家一起寫專欄。我向來不投稿、不識人、甚至懶寫字,難道緣分來了,自然就會成為作家嗎?不是說笑,「緣分」確是關鍵。
我跟專欄結下不解緣,不在編輯或黎生找我寫稿的瞬間,而是在很多年前,我一個人手執稀奇古怪的書,在我家附近海濱公園度過的許多春朝秋夕。當時我瘋狂看課外書,一天十六小時也不倦,比看備考的教科書還認真得多。
黎智英先生曾問我怎學拉丁文,我不想解釋太多,就答在外國的大學唸過。這是事實,但不是事實全部,甚至不是重點。重點是:早在入大學前,我已對着大海學懂了。那段看海的日子,很輕狂,也是我最迷惘的歲月。我不知道將來做什麼,只想做那一刻我最想做的事。
聽來很怪,那時我最想做的事,就是由朝到晚看書,不問值得不值得。吸收知識,尤其是不受課程限制的知識,有種吃禁果的快感,那是我做得最快樂的事。正因年少瘋狂,讓我儲備不少知識,寫專欄時才能從不同維度切入,即使談論哪怕最無聊的時事,也能帶出一些稍有意思的道理。
要找到自己的世界,很難,要碰運氣。你不能控制運氣,但你可以控制自己,透過學習,提高找到那世界的機率。學習除了孜孜矻矻唸書考試,還有很多形式。看一本好書、一齣好戲、一首好詩,只要能啟發你,都是學習。
你的世界是什麼,就做什麼。以我估計,我的世界應該是寫作,不是洗碗或賣卜(雖然朋友都叫我「神棍」)。但在沒稿費的情況下,我不知能撐多久,所以必須開Patreon(Facebook專欄我會繼續公開寫,兩件事無關)。有讀者早已催促我開,但寫什麼呢?我不想分析時局(還有意義嗎?),只想分享知識。
我想起歌德說過:「我們應該每天至少聽一首短歌,唸一首好詩,看一幅好畫,可能的話,說幾句有道理的話。」(Man sollte alle Tage wenigstens ein kleines Lied hören, ein gutes Gedicht lesen, ein treffliches Gemälde sehen und, wenn es möglich zu machen wäre, einige vernünftige Worte sprechen.)
這就是我的宗旨,要給大家介紹美好的事,講些有理的話。從前在《蘋果》寫文,有框框限制,很多創新意念也沒法實現。比如說,我很想每日跟大家講一首古詩,可長可短,學中文之餘,可順勢培養審美能力,甚至邏輯推理能力——對,要賞析一首詩,需要推理。
我也想每星期介紹好看的電影和劇,可新可舊;想用一種有別於江湖術士的方式,有系統有根據地討論術數文化;想談佛理、講耶穌;想介紹精彩的西洋文學,由英文講到拉丁文;想用有趣的方法教文言文;想創作故事,甚至寫武俠小說⋯⋯我要寫十個專欄!
以上夢想,我希望在Patreon實現,但我更希望達成的,是大家在這個崩壞的時代,一起努力變成更好的人。
__________________
馮睎乾十三維度Patreon
)
; tf.start("Load Clipboard")
; msgbox
; tf.start("Load File log.txt")
; msgbox
stf.start(theArticle)
; msgbox
; tf.start() ;from what's leftoff in the object's memory
;multiple instances can be coexisting as below
; w1 := new tf, w1.start("Load Clipboard")
; w2 := new tf, w2.start("Load File log.txt")
; w3 := new tf, w3.start(theArticle)
; msgbox
; w3.start() ;from what's leftoff in the object's memory
Return
Class stf extends tf {
FlexRxR(ByRef Hays, Nee) {
global udmTable
v := this.ov
If Resu := RegExReplace(Hays, this.Maker(Nee))
Return (Resu, this[v].r := Nee)
Loop, Parse, Nee, % (A_Space, r := "")
If StrLen(A_LoopField)
If aPos := RegExMatch(A_LoopField, "''.+''", m)
{ r .= SubStr(A_LoopField, 1, aPos - 1), rr := SubStr(A_LoopField, aPos + StrLen(m)), tt := SubStr(A_LoopField, aPos + 2, StrLen(m) - 4)
ss := StrReplace(tt, "''", "`n")
Loop, Parse, ss, `n
{ s := StrReplace(A_LoopField, "'", A_Space)
If Resu := RegExReplace(udmTable, this.Maker(s))
{ t := "["
Loop, Parse, Resu, `n
t .= SubStr(A_LoopField, 1, 1) ;RegExMatch(A_LoopField, "\s") - 1
r .= t "]"
}Else r .= A_LoopField
}r .= rr A_Space
}Else r .= A_LoopField A_Space
If SubStr(r, 0) = A_Space
r := SubStr(r, 1, StrLen(r) - 1)
If Resu := RegExReplace(Hays, this.Maker(r))
Return (Resu, this[v].r := r)
last_index := 0, s := Nee
While, pos := RegExMatch(s, "\([^)]+\)|\[[^\]]+\]", m)
s := SubStr(s, 1, pos - 1) Chr(168) Chr(168 + A_Index) Chr(168) SubStr(s, pos + StrLen(m)), s%A_Index% := m, last_index := A_Index
Loop, Parse, s
{ If A_Index > 1
r .= t A_LoopField
Else r := A_LoopField
t := RegExMatch(A_LoopField, "[a-z]") ? "\w{0,3}" : ""
}
Loop, % last_index
i := last_index - A_Index + 1, r := StrReplace(r, Chr(168) Chr(168 + i) Chr(168), s%i%)
If Resu := RegExReplace(Hays, this.Maker(r))
Return (Resu, this[v].r := r)
Loop, Parse, Nee
{ If A_Index > 1
r .= t A_LoopField
Else r := A_LoopField
t := RegExMatch(A_LoopField, "\w") ? "[\w'\-+]*" : ""
}
If Resu := RegExReplace(Hays, this.Maker(r))
Return (Resu, this[v].r := r)
Loop, Parse, Nee, % ("", r := "")
r .= RegExMatch(A_LoopField, "\w") ? "(?=[\w'\-+]*" A_LoopField ")" : ""
If StrLen(r)
r .= "\b[\w'\-+]*\b"
Else Return ""
If Resu := RegExReplace(Hays, this.Maker(r))
Return (Resu, this[v].r := r)
Else Return ("", this[v].r := "")
}
} ;end of class
FocusedControl() {
ControlGetFocus, foco, A
Return foco
}
#If, WinActive("The Text Filter") and FocusedControl() = "Edit1"
`::
Tab::ControlFocus, RICHEDIT50W1, A
#If, WinActive("The Text Filter") and FocusedControl() = "RICHEDIT50W1"
Tab::ControlFocus, Edit1, A
Space::PgDn
+Space::PgUp
s::Home
e::End
t::^Home
b::^End
-::%_cwi_%.DecrFontSize()
+::
=::%_cwi_%.IncrFontSize()
`::
Enter::%_cwi_%.TakeThisLine()
f::%_cwi_%.FindNextMatch()
+f::%_cwi_%.FindNextMatch(1)
#If, WinActive("TreeView Of Assorted Matches") and FocusedControl() = "SysTreeView321"
`::
Enter::%_cwi_%.tvButtonEnter()
#If, WinActive("Context Peeking") and FocusedControl() = "RICHEDIT50W1"
~WheelUp::
~WheelDown::%_cwi_%.WheelSearchMode()
#IfWinActive, The Text Filter
F1::%_cwi_%.ToggleHelpPage(_cwi_)
~WheelUp::
~WheelDown::%_cwi_%.WheelSearchMode()
!a::%_cwi_%.ShowAssMatches()
^t::%_cwi_%.AssTreeView(_cwi_)
^p::%_cwi_%.ContextPeek(_cwi_)
!v::Gosub, PasteHaySub
^o::Gosub, OpenFileSub
^r::%_cwi_%.ReloadFile()
#If, WinActive("The Text Filter") and (_bundledRB_ not = "disabled")
~RButton::%_cwi_%.RClickMenu()
#IfWinActive, ahk_class #32770
~LButton::EventHandler(0, 0, 0x201, 0)
~LButton up::EventHandler(0, 0, 0x202, 0)
#IfWinActive
PasteHaySub:
%_cwi_%[%_cwi_%.ov].eFlag := True
If _uii_ := %_cwi_%.PasteIntoHaystack()
{ If _rev_ := RegExMatch(_uii_, "^r\)")
_uii_ := RegExReplace(_uii_, "^r\)")
If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load Clipboard", _rev_)
Else If not InStr(_uii_, "=")
%_uii_% := new tf, %_uii_%.start("Load Clipboard", _rev_)
}
%_cwi_%[%_cwi_%.ov].eFlag := False
Return
OpenFileSub:
%_cwi_%[%_cwi_%.ov].eFlag := True
If _OpFi_ := %_cwi_%.OpenFile()
{ If _rev_ := RegExMatch(_OpFi_, "^r\)")
_OpFi_ := RegExReplace(_OpFi_, "^r\)")
RegExMatch(_OpFi_, "^[\w=]+(?=\t)", _uii_), RegExMatch(_OpFi_, "\t\K.+$", _usf_)
If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load File " _usf_, _rev_)
Else If not InStr(_uii_, "=")
%_uii_% := new tf, %_uii_%.start("Load File " _usf_, _rev_)
}
%_cwi_%[%_cwi_%.ov].eFlag := False
Return
WM_ACTIVATE(wParam) {
global _cwi_
If (wParam > 0)
If WinActive("The Text Filter") or WinActive("TreeView Of Assorted Matches") or WinActive("Context Peeking") or WinActive("Edit Variables")
{ WinGetTitle, t, A
If RegExMatch(t, "\| *?(\w*?) *?\|", m) and StrLen(m1)
_cwi_ := m1
Else _cwi_ := "Oops..."
}Else _cwi_ := "Other Windows"
}
EventHandler(wParam, lParam, msg, hwnd) {
static lbdowntime := 0, dx, dy
global lbduration := 0
If msg = 0x201 ;WM_LBUTTONDOWN
{ MouseGetPos, dx, dy
lbdowntime := A_TickCount
}Else If msg = 0x202 ;WM_LBUTTONUP
If (lbduration := A_TickCount - lbdowntime) > 1000
{ MouseGetPos, ux, uy,, moc
If (moc = "RICHEDIT50W1") and Abs(ux - dx) < 10 and Abs(uy - dy) < 10
MsgBox,, Prompt, Hang On..., 1
}
Return
}
Class tf {
static o := {}
v := {}
start(Param := "", Reverse := 0) {
global udmTable
OnMessage(0x6, "WM_ACTIVATE")
OnMessage(0x201, "EventHandler") ;WM_LBUTTONDOWN
OnMessage(0x202, "EventHandler") ;WM_LBUTTONUP
this.id := this.GetObjVarNam(), v := this.ov := (this.id = this.__class ? "o" : "v")
this[v].Version := "Star-Three"
If IsFunc(this.FlexRxR) and FileExist("udmTable.txt")
FileRead, udmTable, udmTable.txt
If StrLen(Param)
{ this[v].SelectedFile := ""
If Param = Load Clipboard
this[v].Haystack := Clipboard
Else If SubStr(Param, 1, 9) = "Load File"
this[v].Haystack := this.FileRead((Reverse ? "<R>" : "") SubStr(Param, 11))
Else this[v].Haystack := Param
this[v].Haystack := StrReplace(this[v].Haystack, "`r`n", "`n")
If Reverse
theHays := this[v].Haystack, this.ReverseByLine(theHays), this[v].Haystack := theHays
this[v].Fayt := this[v].Case := this[v].Wwrap := True, this[v].Whole := this[v].Linum := False, this[v].n := 1, this[v].Hs[0] := this[v].GetAddress("Haystack"), this[v].Hs[1] := this[v].Haystack
}
this.SlimGui(this.id), this.CleanUp(this.id)
}
FileRead(theFile) {
FileRead, theHays, % (SubStr(theFile, 1, 3) = "<R>" ? SubStr(theFile, 4) : theFile, this[this.ov].SelectedFile := theFile)
Return theHays
}
HsP(n) {
If (n > 1)
Return this[this.ov].Hs[n - 1]
Else Return StrGet(this[this.ov].Hs[0])
}
NeeP(n) {
If (n > 1)
Return this[this.ov].Needle[n - 1]
Else Return ""
}
GetObjVarNam() {
r := "(\w+?):.+?\{address: " Format("0x{:X}", &this) "\}"
Return RegExMatch(this.ListGlobalVars(), r, m) ? m1 : ""
}
SlimGui(id) {
static Fayt
Gui, %id%:New, +Labeltf.sGui_On
Gui, +Resize +MinSize +MaximizeBox
Gui, Font, s18, Consolas
Gui, Add, Edit, xm w280 vFayt
OnSuch := this.Fayt_OnTyping.Bind(this)
GuiControl +g, Edit1, % OnSuch
Gui, Add, Button, x+10 ys h37 w85 Center, 0
OnSuch := this.Refresh_OnClick.Bind(this)
GuiControl +g, Button1, % OnSuch
Gui, Font, s10, Arial
Gui, Add, Button, x+10 w40 ys h37 Default, A
OnSuch := this.A_OnClick.Bind(this)
GuiControl +g, Button2, % OnSuch
Gui, Add, Button, x+0 w40 ys h37, T
OnSuch := this.T_OnClick.Bind(this)
GuiControl +g, Button3, % OnSuch
Gui, Add, Button, x+0 w40 ys h37, C
OnSuch := this.C_OnClick.Bind(this)
GuiControl +g, Button4, % OnSuch
Gui, Add, Button, x+0 w40 ys h37, F
OnSuch := this.F_OnClick.Bind(this)
GuiControl +g, Button5, % OnSuch
begWwrap := this[this.ov].Wwrap ? "+Wrap" : "+HScroll"
Gui, Font, s18, Consolas
Gui, Add, Custom, ClassRICHEDIT50W Section xm h300 w534 %begWwrap% +VScroll +hwndHRE +0x804 ;ES_READONLY = 0x800, ES_MULTILINE = 0x4
this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
OnSuch := this.RE_OnEvent.Bind(this)
GuiControl +g, %HRE%, % OnSuch
Gui, Show,, The Text Filter (Slim)
this.RenewGui(), WM_ACTIVATE(1) ;show content
}
sGui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
GuiControl, Move, Button5, % "x" (A_GuiWidth - 62)
GuiControl, Move, Button4, % "x" (A_GuiWidth - 102)
GuiControl, Move, Button3, % "x" (A_GuiWidth - 142)
GuiControl, Move, Edit1, % "w" (A_GuiWidth - 309)
GuiControl, Move, Button2, % "x" (A_GuiWidth - 182)
GuiControl, Move, Button1, % "x" (A_GuiWidth - 277)
}
sGui_OnEscape() {
%A_Gui%.GuiClose(A_Gui)
}
sGui_OnClose() {
%A_Gui%.GuiClose(A_Gui)
}
Fayt_OnTyping() {
v := this.ov, n := this[v].n
If IsFunc(this.eciwbeg)
{ this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
If not theNeedle = this[v].Needle[n]
ControlSetText, Edit1, % theNeedle
}
Gui, Submit, NoHide
this[v].Needle[n] := theNeedle := this.Fpat()
If StrLen(theNeedle)
this[v].Hs[n] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
Else this[v].Hs[n] := this.HsP(n)
this.RenewGui(theNeedle)
}
A_OnClick() {
this.ShowAssMatches()
ControlFocus, Edit1, A
}
T_OnClick() {
this.AssTreeView(this.id)
ControlFocus, Edit1, A
}
C_OnClick() {
v := this.ov
If not this[v].Linum
{ MsgBox, 4, Request Response, Context Peeking Needs Line Numbering`n`nTurn it on now ?
IfMsgBox, No
Goto, EndingThis
this[v].Linum := True, this.Linum_Sub1(), this.Linum_Sub2(), this.RenewGui(this.Fpat())
}
this.ContextPeek(this.id)
EndingThis:
ControlFocus, Edit1, A
}
F_OnClick() {
v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
this.GuiClose(this.id)
this.BuildGui(this.id)
GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
ControlSetText, Edit1, % this[v].Needle[n], A
this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
Send, {End}
}
SwitchToSlim() {
v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
this.GuiClose(this.id)
this.SlimGui(this.id)
ControlSetText, Edit1, % this[v].Needle[n], A
this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
Send, {End}
}
BuildGui(id) {
global NeedleCB
static Fayt, Case, Whole, Linum, Wwrap
v := this.ov
Gui, %id%:New, +Labeltf.Gui_On
Gui, +Delimiter`n
Gui, +Resize +MinSize +MaximizeBox
Gui, Font, s10, Arial New
Gui, Add, Text,, O p t i o n s:
begFayt := this[v].Fayt ? "Checked" : ""
Gui, Add, Checkbox, ym vFayt %begFayt% Tabstop, Instant Filter (aka Find As You Type)
OnSuch := this.Fayt_OnToggle.Bind(this)
GuiControl +g, Button1, % OnSuch
begCase := this[v].Case ? "Checked" : ""
Gui, Add, Checkbox, ym vCase %begCase% Tabstop, Case Insensitive
OnSuch := this.Case_OnToggle.Bind(this)
GuiControl +g, Button2, % OnSuch
begWhole := this[v].Whole ? "Checked" : ""
Gui, Add, Checkbox, ym vWhole %begWhole% Tabstop, Whole Word
OnSuch := this.Whole_OnToggle.Bind(this)
GuiControl +g, Button3, % OnSuch
begLinum := this[v].Linum ? "Checked" : ""
Gui, Add, Checkbox, ym vLinum %begLinum% Tabstop, Line Number
OnSuch := this.Linum_OnToggle.Bind(this)
GuiControl +g, Button4, % OnSuch
beg_Wrap := this[v].Wwrap ? "Checked" : ""
Gui, Add, Checkbox, ym vWwrap %beg_Wrap% Tabstop, Word Wrap
OnSuch := this.Wwrap_OnToggle.Bind(this)
GuiControl +g, Button5, % OnSuch
Gui, Font, s18, Arial New
Gui, Add, Text, xm Section, Filter:
w := A_ScreenWidth - 330
Gui, Add, ComboBox, w%w% ys vNeedleCB +hwndhEdit1
OnSuch := this.Fpat_OnTyping.Bind(this)
GuiControl +g, %hEdit1%, % OnSuch
Gui, Add, Button, h38 ys Default, Go
OnSuch := this.Go_OnClick.Bind(this)
GuiControl +g, Button6, % OnSuch
Gui, Font, s10, Arial New
Gui, Add, Button, h38 ys, Refresh
OnSuch := this.Refresh_OnClick.Bind(this)
GuiControl +g, Button7, % OnSuch
Gui, Font, s18, Arial New
Gui, Add, Button, h38 ys, Back
OnSuch := this.Back_OnClick.Bind(this)
GuiControl +g, Button8, % OnSuch
h := A_ScreenHeight - 143, w := A_ScreenWidth - 30, begWwrap := this[v].Wwrap ? "+Wrap" : "+HScroll"
Gui, Font, s18, Consolas
Gui, Add, Custom, ClassRICHEDIT50W x10 h%h% w%w% %begWwrap% +VScroll +hwndHRE +0x804 ;ES_READONLY = 0x800, ES_MULTILINE = 0x4
this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
OnSuch := this.RE_OnEvent.Bind(this)
GuiControl +g, %HRE%, % OnSuch
h := A_ScreenHeight - 64, w := A_ScreenWidth - 6
Gui, Show, h%h% w%w%, The Text Filter
this.RenewGui(), WM_ACTIVATE(1) ;show content
}
RE_OnEvent() {
global lbduration
v := this.ov
If not WinExist("The Text Filter")
Return
If (this[v].REseleT = this.RE.Selection.Text)
Return
If GetKeyState("RButton", "P")
Return
Sleep, 500 ;this "sleep" exists with reason
If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
Return
If not this[v].eFlag and this[v].Linum and WinActive("The Text Filter") and WinExist("Context Peeking | " this.id) and StrLen(this.RE.Selection.Text)
{ this[v].eFlag := True
n := this[v].n
slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, SelBegChar := this.RE.Range(slcs, slcs + 1).Text, SelEndChar := this.RE.Range(slce - 1, slce).Text, Hays := this.RE.Range(0, 999999999).Text
If InStr(A_Priorkey, "WheelUp")
this.RE.Range(slcs, slcs).Select
Else maybe := InStr("`r`n", SelEndChar) ? 1 : 0, this.RE.Range(slce - maybe, slce - maybe).Select
Sleep, 500
maybe := InStr("`r`n", SelBegChar) and (SelEndChar = A_Space) ? 2 : 1, mpos := this.ULoNLoCR(Hays, slcs + maybe)
slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
this.RE_PeekContext(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
}Else If not this[v].eFlag and WinActive("The Text Filter") and StrLen(this.RE.Selection.Text) and Clipboard not = this.RE.Selection.Text
{ this[v].eFlag := True, slcs := this.RE.Selection.Start
If InStr("`r`n", SubStr(this.RE.Selection.Text, 0))
this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
Else
{ MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
IfMsgBox, Yes
{ Clipboard := this.RE.Selection.Text
Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
If lbduration > 1000
{ ControlSetText, Edit1, % Trim(Clipboard)
ControlGetText, TextExists, Static1, % "ahk_id " WinExist("The Text Filter")
If TextExists
this.Fpat_OnTyping()
}
}IfMsgBox, No
this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
Sleep, 500 ;this "sleep" exists with reason
}
this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
}
}
RE_PeekContext(theOne) {
cpLnum := RegExReplace(theOne, "^\t? *?(\d+?):.*$", "$1")
If cpLnum is not digit
Return
v := this.ov, Hays := this[v].HaystackN, cpLend := RegExMatch(RegExReplace(Hays, "`n",,, cpLnum - 1), "`n") + cpLnum - 1, mpos := this.ULoNLoCR(Hays, cpLend), cpLbeg := mpos - 1, this[v].xFlag := True, this.CP.Range(cpLbeg, cpLend).Select, this.cpScroIntoView()
timer := ObjBindMethod(this, "OffxFlag")
SetTimer, % timer, -1000
}
OffxFlag() {
this[this.ov].xFlag := False
}
Gui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 95) " w" (A_GuiWidth - 14)
}
Gui_OnEscape() {
%A_Gui%.GuiClose(A_Gui)
}
Gui_OnClose() {
%A_Gui%.GuiClose(A_Gui)
}
GuiClose(id) {
Gui, %id%:Destroy
%id%.CleanUp(id)
}
CleanUp(id) {
IfExist, tf_%id%Work.rtf
FileDelete, tf_%id%Work.rtf
IfExist, tfHelp.rtf
FileDelete, tfHelp.rtf
}
GetTomDoc(HRE) { ;written by "@just me"
Static IID_ITextDocument := "{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}"
DocObj := 0
If DllCall("SendMessage", "Ptr", HRE, "UInt", 0x043C, "Ptr", 0, "PtrP", IRichEditOle, "UInt") ;EM_GETOLEINTERFACE
{ DocObj := ComObject(9, ComObjQuery(IRichEditOle, IID_ITextDocument), 1) ; ITextDocument
ObjRelease(IRichEditOle)
}
Return DocObj
}
Fayt_OnToggle() {
v := this.ov, n := this[v].n
If not (this[v].Fayt := this.Fayt())
If (this[v].Hs[n] != this.HsP(n))
{ this[v].Needle[n] := this.Fpat(), theHaystack := this[v].Hs[n]
n := (this[v].n += 1), this[v].Hs[n] := theHaystack
this.UpdateTitle()
}
ControlFocus, Edit1, A
this.Fpat_OnTyping()
}
Case_OnToggle() {
this[this.ov].Case := this.Case()
ControlFocus, Edit1, A
this.Fpat_OnTyping()
}
Whole_OnToggle() {
this[this.ov].Whole := this.Whole()
ControlFocus, Edit1, A
this.Fpat_OnTyping()
}
Linum_OnToggle() {
v := this.ov
If this[v].Linum := this.Linum()
this.Linum_Sub1()
Else this[v].Hs[0] := this[v].GetAddress("Haystack")
this.Linum_Sub2()
this.RenewGui(this.Fpat())
}
Linum_Sub1() {
v := this.ov
Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Line Numbering, Segoe UI
lsl := StrLen(this.LineCount())
HsN =
Loop, Parse, % this[v].Haystack, `n`r
HsN .= SubStr(this.StrRepeat(A_Space, lsl) A_Index, 1 - lsl) ":" A_Space A_LoopField "`n"
Progress, Off
this[v].HaystackN := HsN, this[v].Hs[0] := this[v].GetAddress("HaystackN")
}
Linum_Sub2() {
v := this.ov
Loop, % this[v].n
this[v].Hs[A_Index] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(A_Index), this[v].Needle[A_Index]) : RegExReplace(this.HsP(A_Index), this.Maker(this[v].Needle[A_Index]))
}
Wwrap_OnToggle() {
v := this.ov, this[v].Wwrap := this.Wwrap(), n := this[v].n, this[v].Needle[n] := this.Fpat()
this.BuildGui(this.id)
GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
ControlSetText, Edit1, % this[v].Needle[n], A
this.RenewGui(this[v].Needle[n])
Send, {End}
}
Fpat_OnTyping() {
v := this.ov, n := this[v].n
If IsFunc(this.eciwbeg)
{ this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
If not theNeedle = this[v].Needle[n]
ControlSetText, Edit1, % theNeedle
}
If not this[v].Fayt and not this[v].CommitLevel
Return
Gui, Submit, NoHide
this[v].Needle[n] := theNeedle := this.Fpat()
If not StrLen(theNeedle) and this[v].CommitLevel
{ this[v].CommitLevel := False, this.Back_OnClick()
Progress, Off
Return
}
theHaystack := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
If this[v].CommitLevel
{ If not StrLen(this[v].NeedleHistory)
this[v].NeedleHistory := theNeedle, Added := True
Else If not RegExMatch(this[v].NeedleHistory, (this[v].Case ? "i" : "") "m`a)^\Q" theNeedle "\E$")
this[v].NeedleHistory := theNeedle "`n" this[v].NeedleHistory, Added := True
Else Added := False
If Added
{ GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
ControlSetText, Edit1, % theNeedle
}
If (theHaystack = this.HsP(n))
Progress, zh0 w450 c10 fs18, `nResult No Change Thus Not Anew Level`n,, Prompt, Segoe UI
Else
{ If not this[v].Fayt
this[v].Hs[n] := theHaystack
If (this.LineCount(n) < 2) and not (theNeedle == this.NeeP(n))
Progress, zh0 w450 c10 fs18, `nUltimate/Empty Result Reached`nThus Level Not Advanced`n,, Prompt, Segoe UI
Else
{ n := (this[v].n += 1), this[v].Hs[n] := theHaystack
Send, ^a
}
}
this[v].CommitLevel := False
Sleep, 500
Progress, Off
}Else this[v].Hs[n] := theHaystack
this.RenewGui(theNeedle)
If not this[v].Fayt and not StrLen(this[v].Hs[n])
{ Progress, zh0 w450 c10 fs18, `nEmpty Result Reached`n`nFalling Back Now`n,, Prompt, Segoe UI
Sleep, 1000
this[v].Hs[n] := this.HsP(n)
ControlSetText, Edit1, % this.NeeP(n)
this.RenewGui(this.Fpat())
Send, ^a
Progress, Off
}
}
Maker(t) {
v := this.ov, t := this.tw4sh(t), r := (this[v].Case ? "i" : "") "m`a)^(?!"
Loop, Parse, t, % A_Space
If SubStr(A_LoopField, 1, 1) = "-"
r .= "(?!.*(" (this[v].Whole ? "\b" : "") SubStr(A_LoopField, 2) (this[v].Whole ? "\b" : "") "))"
Else r .= "(?=.*(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") "))"
r .= ").*\R?"
Return r
}
Go_OnClick() {
ControlFocus, Edit1, A
Progress, zh0 w380 c10 fs18, `nCommitting This Level`n,, Prompt, Segoe UI
this[this.ov].CommitLevel := True, this.Fpat_OnTyping()
}
Refresh_OnClick() {
this.RenewGui(this[this.ov].Needle[this[this.ov].n] := this.Fpat(), "retain")
}
Back_OnClick() {
ControlFocus, Edit1, A
v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat()
If (n = 1) and (this[v].Hs[n] != this.HsP(n))
this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
Else If (this[v].Hs[n] = this.HsP(n)) and (this[v].Needle[n] = this.NeeP(n))
If (n > 2)
n := (this[v].n -= 2)
Else If (n = 2)
n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
Else n := this[v].n := 0
Else n := (this[v].n -= 1)
If n
{ ControlSetText, Edit1, % this[v].Needle[n]
this.RenewGui(this[v].Needle[n])
Send, ^a
If (n = 1) and (this[v].Hs[n] = this.HsP(n))
{ Progress, zh0 w380 c10 fs18, `nReturned To The Origin`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
}Else
{ Progress, zh0 w380 c10 fs18, `nReturned To Level %n%`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
}
}Else this.Gui_OnClose()
}
Fpat() {
GuiControlGet, Fpat,, Edit1
If not StrLen(Fpat)
ControlGetText, Fpat, Edit1
Return Fpat
}
Fayt() {
GuiControlGet, Fayt,, Button1
If not StrLen(Fayt)
ControlGetText, Fayt, Button1
Return Fayt
}
Case() {
GuiControlGet, Case,, Button2
If not StrLen(Case)
ControlGetText, Case, Button2
Return Case
}
Whole() {
GuiControlGet, Whole,, Button3
If not StrLen(Whole)
ControlGetText, Whole, Button3
Return Whole
}
Linum() {
GuiControlGet, Linum,, Button4
If not StrLen(Linum)
ControlGetText, Linum, Button4
Return Linum
}
Wwrap() {
GuiControlGet, Wwrap,, Button5
If not StrLen(Wwrap)
ControlGetText, Wwrap, Button5
Return Wwrap
}
RenewGui(theNee := "", AMt := "") {
global lbduration
v := this.ov, n := this[v].n
If this.Fpat() not = theNee
Goto, WorkInterrupt
this.ToggleReadOnly(this.HRE, this[v].Wwrap)
If not this[v].PriorRefreshTime is digit
this[v].PriorRefreshTime := 0
If (AMt = "retain") and lbduration < 1000 and A_TickCount - this[v].PriorRefreshTime > 1000
theHays := this.RE.Range(0, 999999999).Text, this[v].PriorRefreshTime := A_TickCount, this[v].combed := False
Else If StrLen(AMt) and (AMt not = "retain")
theHays := this[v][AMt]
Else If IsFunc(this.Comb) and this.LineCount(n) < 1000 and lbduration < 1000
theHays := this.Comb(this[v].Hs[n]), this[v].combed := True
Else theHays := this[v].Hs[n], this[v].combed := False
ControlSetText, RICHEDIT50W1, %theHays%, A
indent := (StrLen(this.LineCount()) + 2) * 10, this.RE.Range(0, StrLen(theHays)).SetIndents(-indent, indent, 0)
If this.Fpat() not = theNee
Goto, WIP_Interrupt
r := this.MakerC(IsFunc(this.FlexRxR) ? (this[v].combed ? this[v].combed_r : this[v].r) : theNee)
If StrLen(theNee) and StrLen(r) and RegExMatch(theHays, r)
{ Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Matches Highlighting, Segoe UI
mpos := 1, mlen := 0
While, (mpos := RegExMatch(theHays, r, nm, mpos + mlen)) and (A_Index < 1000 or lbduration > 1000)
mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).Font.BackColor := 0x00FFFF, npos := mpos
lbduration := 0
Progress, Off
}
If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
{ Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assorted Matches Formatting, Segoe UI
mpos := 1, mlen := 0
While, (mpos := RegExMatch(theHays, "\R\d+\. .+?\R\K.+?(?=\R\d+\. .+|\R*$)", nm, mpos + mlen))
mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).SetIndents(-indent, indent * 2, 0), npos := mpos
Progress, Off
}
WIP_Interrupt:
this.ToggleReadOnly(this.HRE, this[v].Wwrap)
ControlFocus, Edit1, A
this.UpdateTitle()
WorkInterrupt:
GuiControlGet, TextExists,, Static2
If not TextExists
{ If StrLen(theNee)and StrLen(r) and RegExMatch(theHays, r)
RegExReplace(theHays, r,, mc)
Else mc := 0
ControlSetText, Button1, %mc%, A
}
If this.Fpat() not = theNee
If TextExists
this.Fpat_OnTyping()
Else this.Fayt_OnTyping()
}
UpdateTitle() {
WinSetTitle, The Text Filter, % ("", v := this.ov, Version := this[v].Version, id := this.id, n := this[v].n, lc := this.LineCount(n), SelectedFile := this[v].SelectedFile), The Text Filter (Version: %Version%) | %id% | Level %n% | Line Count: %lc% | %SelectedFile%
}
LineCount(n := 0) {
If n is digit
theHays := this.HsP(n + 1)
Else theHays := n
StrReplace(theHays, "`n",, lc), lc += StrLen(theHays) and SubStr(theHays, 0) != "`n" ? 1 : 0
Return lc
}
ToggleReadOnly(HRE, Wwrap) {
ControlGet, Style, Style,,, ahk_id %HRE%
If not (Style & 0x800)
SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HRE% ;tune Down BackgroundColor
SendMessage, 1101, 1, (Style & 0x800) ? (Wwrap ? 0x44 : 0xC4) : (Wwrap ? 0x844 : 0x8C4),, ahk_id %HRE% ;ES_READONLY = 0x800
If (Style & 0x800)
SendMessage, 0x443, 0, 0xEEFFFF,, ahk_id %HRE% ;light Up BackgroundColor
}
MakerC(theNee) {
theNee := this.tw4sh(theNee), r := "", v := this.ov
Loop, Parse, theNee, % A_Space
If SubStr(A_LoopField, 1, 1) != "-"
r .= "(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") ")|"
If StrLen(r)
{ If SubStr(r, 0) = "|"
r := SubStr(r, 1, StrLen(r) - 1)
r := (this[v].Case ? "i" : "") "m`a)" r
}
Return r
}
IncrFontSize() {
MouseGetPos, mpx, mpy,, moc
If (moc not = "RICHEDIT50W1")
MouseMove, 400, 200
Send, ^{WheelUp}
If (moc not = "RICHEDIT50W1")
MouseMove, mpx, mpy
}
DecrFontSize() {
MouseGetPos, mpx, mpy,, moc
If (moc not = "RICHEDIT50W1")
MouseMove, 400, 200
Send, ^{WheelDown}
If (moc not = "RICHEDIT50W1")
MouseMove, mpx, mpy
}
TakeThisLine(id := "RE") {
slcs := this[id].Selection.Start, slce := this[id].Selection.End, Hays := this[id].Range(0, 999999999).Text
If (slce > slcs)
{ Clipboard := this[id].Selection.Text
Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
Return
}
mpos := this.ULoNLoCR(Hays, slce + 1)
slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
this.FinalTouch(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
}
ULoNLoCR(hays, mpos) {
While, mpos > 1 and not InStr("`r`n", SubStr(hays, mpos - 1, 1))
mpos--
Return mpos
}
DLoNLoCR(hays, mpos) {
pmax := StrLen(hays)
While, mpos <= pmax and not InStr("`r`n", SubStr(hays, mpos, 1))
mpos++
Return mpos
}
FinalTouch(theOne) {
Clipboard := RegExReplace(theOne, "^\t?(?: *?\d+?: )?(.*)$", "$1")
If IsFunc(this.altTakeThisLine)
this.altTakeThisLine()
Else MsgBox,,, Has Put This Line Into Clipboard, 3
}
FindNextMatch(Reverse := 0) {
If StrLen(sPat := this.Fpat())
r := this.MakerC(IsFunc(this.FlexRxR) ? this[this.ov].r : sPat)
Else r := "nothing to be matched this"
slcs := this.RE.Selection.Start, slce := this.RE.Selection.End
If (slce > slcs) and (RegExMatch(A_ThisHotkey, "^\+?f$") and StrLen(sPat) ? False : not RegExMatch(this.RE.Selection.Text, r))
r := this.MakerS(this.RE.Selection.Text)
If StrLen(r) and RegExMatch(Hays := this.RE.Range(0, 999999999).Text, r)
{ StartHere:
slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, slcs++, slce++
cp := Reverse ? slcs : slce
If Reverse
{ If cp > 1
{ mpos := 0, pmax := cp - 1
Loop
{ npos := RegExMatch(Hays, r, pm, mpos + 1)
If npos between 1 and %pmax%
mpos := npos, nm := pm
Else Break
}
found := (npos > pmax) and mpos > 0
}
If not found
{ mpos := cp - 1, pmax := StrLen(Hays)
Loop
{ npos := RegExMatch(Hays, r, pm, mpos + 1)
If npos between %cp% and %pmax%
mpos := npos, nm := pm
Else Break
}
}
}Else mpos := RegExMatch(Hays, r, nm, cp)
mpos--
If mpos >= 0
{ cp := mpos + StrLen(nm)
this.RE.Range(mpos, cp).Select
}Else If (mpos < 0) and not Reverse
{ this.RE.Range(0, 0).Select
Goto, StartHere
}
}
}
MakerS(st) {
Return (StrLen(st), v := this.ov) ? (this[v].Case ? "i)" : "") (this[v].Whole ? "\b" : "") this.escrx(st) (this[v].Whole ? "\b" : "") : ""
}
WheelSearchMode() {
MouseGetPos,,,, moc
If not StrLen(moc) or not InStr("Edit1|RICHEDIT50W1", moc)
{ IfWinNotActive, The Text Filter
{ WinActivate % "ahk_id " this[this.ov].ParWin
WinWaitActive
}
ControlFocus, RICHEDIT50W1, A
this.FindNextMatch(InStr(A_ThisHotkey, "WheelUp"))
}
}
ShowAssMatches() {
If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
{ sPat := this.Fpat()
If this.RE.Range(19, 31).Text = "Alphabetical"
this.RenewGui(sPat, "AssHays")
Else this.RenewGui(sPat, "AAssHays")
Return
}
z := this.ov, n := this[z].n
If not StrLen(this[z].Hs[n]) or not StrLen(sPat := this.Fpat()) or not StrLen(r := this.MakerC(sPat))
Return
r := IsFunc(this.FlexRxR) ? this.MakerC(this[z].r) : r
Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assortment, Segoe UI
UniqMatches := [], Seq := 0, this[z].combed := IsFunc(this.Comb) and this.LineCount(n) < 1000
Loop, Parse, % this[z].Hs[n], `n`r
{ mpos = 1
worknm:
npos := RegExMatch(A_LoopField, r, nm, mpos), C_LoopField := this[z].combed ? Trim(this.Comb(A_LoopField)) : ""
If npos
{ If UniqMatches.HasKey(nm)
Ums := UniqMatches[nm], AssHays%Ums% .= InStr(AssHays%Ums%, A_LoopField) ? "" : ("`n" A_LoopField, cAssHays%Ums% .= this[z].combed ? "`n" C_LoopField : "")
Else
Seq++, UniqMatches[nm] := Seq, AssHays%Seq% := nm "`n" A_LoopField, cAssHays%Seq% := this[z].combed ? nm "`n" C_LoopField : ""
mpos := npos + StrLen(nm)
Goto, worknm
}
}
If Seq
{ UniqHays := tvAAssHays := cAAssHays := "", umNoSort := []
For k, v in UniqMatches
UniqHays .= "`n" this.StrRepeat(A_Space, 3) A_Index ".`t" k, tvAAssHays .= "`n" A_Index ". " AssHays%v%, cAAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%v% : "", umNoSort[v] ? umNoSort[v].Insert(k) : umNoSort[v] := k
AAssHays := "Assorted Matches:`t(Alphabetical Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAAssHays : tvAAssHays)
UniqHays := tvAssHays := cAssHays := ""
For k, v in umNoSort
UniqHays .= "`n" this.StrRepeat(A_Space, 3) k ".`t" v, tvAssHays .= "`n" A_Index ". " AssHays%k%, cAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%k% : ""
AssHays := "Assorted Matches:`t(Chronological Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAssHays : tvAssHays)
this[z].AssHays := AssHays, this[z].AAssHays := AAssHays, this[z].tvAssHays := tvAssHays, this[z].tvAAssHays := tvAAssHays
this.RenewGui(sPat, "AssHays")
}
Progress, Off
}
AssTreeView(id) {
If this.RE.Range(0, 19).Text not = "Assorted Matches:`t("
Return
parwin := this[v].ParWin := WinExist("A")
Gui, tv%id%:New, +Owner%parwin%
Gui, +Resize +MinSize +MaximizeBox
Gui, +Labeltf.tvGui_On
Gui, Font, s18, Consolas
Gui, Add, Text,, % this.RE.Range(19, 31).Text = "Alphabetical" ? "Assorted Matches: (Alphabetical Order)" : "Assorted Matches: (Chronological Order)"
;Gui, Add, Button, Hidden Default, Enter
Gui, Add, TreeView, AltSubmit Section xm w545
OnSuch := this.tvEventHdlr.Bind(this)
GuiControl +g, SysTreeView321, % OnSuch
Seq := 0, aHays := this.RE.Range(19, 31).Text = "Alphabetical" ? this[this.ov].tvAAssHays : this[this.ov].tvAssHays, lc := this.LineCount(aHays) - 1
Loop, Parse, aHays, `n`r
If StrLen(A_LoopField)
If RegExMatch(A_LoopField, "^ *\d+\.[ \t]")
Seq++, P%Seq% := TV_Add(A_LoopField), Num := 0
Else Num++, P%Seq%C%Num% := TV_Add(A_LoopField, P%Seq%)
Gui, Show, x97 y539 h283, TreeView Of Assorted Matches | %id% | Line Count: %lc%
GuiControl, Focus, SysTreeView321
}
tvGui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, SysTreeView321, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
}
tvGui_OnEscape() {
Gui, %A_Gui%:Destroy
}
tvGui_OnClose() {
Gui, %A_Gui%:Destroy
}
tvEventHdlr() {
If InStr("DoubleClick|S|K|Normal", A_GuiEvent)
TV_GetText(theOne, TV_GetSelection())
this[this.ov].theOne := theOne
If A_GuiEvent = DoubleClick
IfWinExist, % "Context Peeking | " this.id
this.RE_PeekContext(theOne)
Else this.tvButtonEnter()
}
tvButtonEnter() {
this.FinalTouch(this[this.ov].theOne)
}
PasteIntoHaystack() {
global _cwi_
If StrLen(Clipboard)
{ InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
If not ErrorLevel and StrLen(Trim(id))
{ If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
id := RegExReplace(id, "[-/]\s*[rR]$")
If RegExMatch(id, "[^\w=]")
id := RegExReplace(id, "[^\w=]")
If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
Return (Reverse ? "r)" id : id)
If InStr(id, "=")
MsgBox, Invalid Input
Else If (id = _cwi_)
this.start("Load Clipboard", Reverse)
Else Return (Reverse ? "r)" id : id)
}
}Else MsgBox, Clipboard is empty
}
OpenFile() {
global _cwi_
FileSelectFile, SelectedFile
If StrLen(SelectedFile)
{ InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
If not ErrorLevel and StrLen(Trim(id))
{ If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
id := RegExReplace(id, "[-/]\s*[rR]$")
If RegExMatch(id, "[^\w=]")
id := RegExReplace(id, "[^\w=]")
ido := (Reverse ? "r)" id : id)
If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
Return ido "`t" SelectedFile
If InStr(id, "=")
MsgBox, Invalid Input
Else If (id = _cwi_)
this.start("Load File " SelectedFile, Reverse)
Else Return ido "`t" SelectedFile
}
}
}
ReloadFile() {
If StrLen(SelectedFile := this[this.ov].SelectedFile)
{ If Reverse := (SubStr(SelectedFile, 1, 3) = "<R>")
SelectedFile := SubStr(SelectedFile, 4)
this.start("Load File " SelectedFile, Reverse)
}
}
RClickMenu() {
global lbduration
MouseGetPos, xb4, yb4
While, GetKeyState("RButton", "P")
Continue
MouseGetPos, rbx, rby, mow, moc
If Abs(rbx - xb4) > 10 or Abs(rby - yb4) > 10
Return
If (mow = (HGUI := WinExist("A"))) and rby > 30
If (moc = "Button8")
this.ShowTrail()
Else If (moc not = "Edit1")
{ Menu, myMenu, Add
Menu, myMenu, DeleteAll
If IsFunc(this.EditVars)
{ Menu, myMenu, Add, Edit Variables, MenuHandler
Menu, myMenu, Add
}
Menu, myMenu, Add, Show Assorted Matches, MenuHandler
If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
Menu, myMenu, Add, Put Assorted Matches In TreeView, MenuHandler
If this[this.ov].Linum and not WinExist("Context Peeking | " this.id)
{ Menu, myMenu, Add
Menu, myMenu, Add, Context Peeking, MenuHandler
}
Menu, myMenu, Add
Menu, myMenu, Add, Increase Font Size, MenuHandler
Menu, myMenu, Add, Decrease Font Size, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, Paste Into The Base, MenuHandler
Menu, myMenu, Add, Open A File, MenuHandler
Menu, myMenu, Add, Reload The File, MenuHandler
Menu, myMenu, Add
ControlGetText, TextExists, Static1, ahk_id %HGUI%
If TextExists
Menu, myMenu, Add, Switch To Slim Gui, MenuHandler
Else Menu, myMenu, Add, Switch To Full-Blown Gui, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, List Global Variables, MenuHandler
If (moc = "RICHEDIT50W1")
{ Menu, myMenu, Add
Menu, myMenu, Add, Copy The Line/Selection, MenuHandler
Menu, myMenu, Add, Go To Rightmost Of The Line, MenuHandler
Menu, myMenu, Add, Go To Leftmost Of The Line, MenuHandler
Menu, myMenu, Add, Go To The Bottom, MenuHandler
Menu, myMenu, Add, Go To The Top, MenuHandler
Menu, myMenu, Add, Page Down, MenuHandler
Menu, myMenu, Add, Page Up, MenuHandler
}
Menu, myMenu, Add
Menu, myMenu, Add, Downward Find Next Match, MenuHandler
Menu, myMenu, Add, Upward Find Next Match, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, Override The 1K Default, MenuHandler
Menu, myMenu, Add
Menu, myMenu, Add, Show/Hide Help Page, MenuHandler
Menu, myMenu, Show
}
Return
MenuHandler:
WinWaitActive, ahk_id %HGUI%
If A_ThisMenuItem = Edit Variables
this.EditVars(this.id) ;basically for debugging purpose
Else If A_ThisMenuItem = Show Assorted Matches
this.ShowAssMatches()
Else If A_ThisMenuItem = Put Assorted Matches In TreeView
this.AssTreeView(this.id)
Else If A_ThisMenuItem = Context Peeking
this.ContextPeek(this.id)
Else If A_ThisMenuItem = Increase Font Size
this.IncrFontSize()
Else If A_ThisMenuItem = Decrease Font Size
this.DecrFontSize()
Else If A_ThisMenuItem = Paste Into The Base
Gosub, PasteHaySub
Else If A_ThisMenuItem = Open A File
Gosub, OpenFileSub
Else If A_ThisMenuItem = Reload The File
this.ReloadFile()
Else If A_ThisMenuItem = Switch To Slim Gui
this.SwitchToSlim()
Else If A_ThisMenuItem = Switch To Full-Blown Gui
this.F_OnClick()
Else If A_ThisMenuItem = List Global Variables
this.start(this.ListGlobalVars())
Else If A_ThisMenuItem = Copy The Line/Selection
{ If this.RE.Selection.End = this.RE.Selection.Start
MouseClick, Left, rbx, rby
this.TakeThisLine()
}Else If A_ThisMenuItem = Go To Rightmost Of The Line
{ MouseClick, Left, rbx, rby
Send, {End}
}Else If A_ThisMenuItem = Go To Leftmost Of The Line
{ MouseClick, Left, rbx, rby
Send, {Home}
}Else If A_ThisMenuItem = Go To The Bottom
{ MouseClick, Left, rbx, rby
Send, ^{End}
}Else If A_ThisMenuItem = Go To The Top
{ MouseClick, Left, rbx, rby
Send, ^{Home}
}Else If A_ThisMenuItem = Page Down
{ MouseClick, Left, rbx, rby
Send, {PgDn}
}Else If A_ThisMenuItem = Page Up
{ MouseClick, Left, rbx, rby
Send, {PgUp}
}Else If A_ThisMenuItem = Downward Find Next Match
{ ControlFocus, RICHEDIT50W1, A
this.FindNextMatch()
}Else If A_ThisMenuItem = Upward Find Next Match
{ ControlFocus, RICHEDIT50W1, A
this.FindNextMatch(1)
}Else If A_ThisMenuItem = Override The 1K Default
lbduration := 1234, this.RenewGui(this.Fpat(), "retain")
Else If A_ThisMenuItem = Show/Hide Help Page
this.ToggleHelpPage(this.id)
Return
}
ShowTrail() {
HGUI := WinExist("A"), v := this.ov, n := this[v].n
Menu, myTrail, Add
Menu, myTrail, DeleteAll
While, A_Index < n
{ tn := n - A_Index, theNeedle := this[v].Needle[tn], lc := this.LineCount(tn)
Menu, myTrail, Add, Level &%tn% remains %lc% lines after this filter: %theNeedle%, BtsLevel
}
lc := this.LineCount()
Menu, myTrail, Add, Origin %lc% lines (Level &0), BtsLevel
Menu, myTrail, Show
Return
BtsLevel:
WinWaitActive, ahk_id %HGUI%
n -= A_ThisMenuItemPos
If n < 1
n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
Else this[v].n := n
ControlSetText, Edit1, % this[v].Needle[n]
this.RenewGui(this[v].Needle[n])
Return
}
ToggleHelpPage(id) {
theFile = tf_%id%Work.rtf
If this.RE.Range(0, 17).Text = "H e l p _ P a g e"
IfExist, %theFile%
this.RE.Open(theFile, 0x01, 0)
Else this.RenewGui(this.Fpat())
Else
{ IfExist, %theFile%
this.RE.Save(0, 0, 0)
Else this.RE.Save(theFile, 0x01, 0)
helpfile = tfHelp.rtf
IfExist, % helpfile
FileDelete, % helpfile
FileAppend, % this.HelpPage(), % helpfile
this.RE.Open(helpfile, 0x01, 0)
}
}
ContextPeek(id) {
v := this.ov
If not this[v].Linum
Return
parwin := this[v].ParWin := WinExist("A")
Gui, cp%id%:New, +Owner%parwin%
Gui, +Resize +MinSize +MaximizeBox
Gui, +Labeltf.cpGui_On
Gui, Font, s12, Arial New
Gui, Add, Button,, Close
OnSuch := this.cpBclose.Bind(this)
GuiControl +g, Button1, % OnSuch
Gui, Add, Button, ys, Maximize
OnSuch := this.cpBmaxim.Bind(this)
GuiControl +g, Button2, % OnSuch
Gui, Add, Button, ys, Restore
OnSuch := this.cpBresto.Bind(this)
GuiControl +g, Button3, % OnSuch
Gui, Add, Button, ys, Minimize
OnSuch := this.cpBminim.Bind(this)
GuiControl +g, Button4, % OnSuch
Gui, Font, s18, Consolas
Gui, Add, Custom, ClassRICHEDIT50W xm Section +Wrap +VScroll +hwndHCP +0x804 ;ES_READONLY = 0x800, ES_MULTILINE = 0x4
this.HCP := HCP, this.CP := this.GetTomDoc(HCP)
OnSuch := this.cpEventHdlr.Bind(this)
GuiControl +g, RICHEDIT50W1, % OnSuch
x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6, lc := this.LineCount()
Gui, Show, x%x% y51 h%h% w%w%, Context Peeking | %id% | Line Count: %lc%
Progress, zh0 w300 c10 fs18, `nHang On...`n,, Loading Origin, Segoe UI
GuiControl,, RICHEDIT50W1, % this[v].HaystackN
GuiControl, Focus, RICHEDIT50W1
this.ToggleReadOnly(this.HCP, this[v].Wwrap)
indent := (StrLen(lc) + 2) * 10, this.CP.Range(0, StrLen(this[v].HaystackN)).SetIndents(-indent, indent, 0)
SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HCP% ;tune Down BackgroundColor
this.ToggleReadOnly(this.HCP, this[v].Wwrap)
Progress, Off
}
cpScroIntoView() {
GuiControlGet, gCPg, Pos, % this.HCP
this.CP.Selection.ScrollIntoView(0), slcs := this.CP.Selection.Start, slce := this.CP.Selection.End
this.CP.Range(cp := this.CfromP(this.HCP, 1, this.PfromC(this.HCP, slcs) + gCPgH / 2), cp).Select
WinActivate, % "Context Peeking | " this.id
WinWaitActive
this.CP.Range(slcs, slce).Select
this[this.ov].CPseleT := this.CP.Selection.Text
}
CfromP(hE, x := -1, y := -1) {
VarSetCapacity(RECT, 16, 0)
SendMessage 0xB2,, &RECT,, ahk_id %hE% ;EM_GETRECT
LefP := NumGet(RECT, 0, "Int"), TopP := NumGet(RECT, 4, "Int"), RigP := NumGet(RECT, 8, "Int"), BotP := NumGet(RECT, 12, "Int")
VarSetCapacity(PoL, 8, 0), NumPut(x < 0 ? RigP : x, PoL,, "Int"), NumPut(y < 0 ? BotP : y, PoL, 4, "Int")
SendMessage 0xD7,, &PoL,, ahk_id %hE% ;EM_CHARFROMPOS
Return ErrorLevel
}
PfromC(hE, i) {
VarSetCapacity(PoL, 8, 0)
SendMessage 0xD6, &PoL, i,, ahk_id %hE% ;EM_POSFROMCHAR
Return NumGet(PoL, 4, "Int")
}
cpGui_OnSize() {
If A_EventInfo = 1
Return
GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 65) " w" (A_GuiWidth - 30)
}
cpGui_OnEscape() {
Gui, %A_Gui%:Destroy
}
cpGui_OnClose() {
Gui, %A_Gui%:Destroy
}
cpBclose() {
Gui, %A_Gui%:Destroy
}
cpBmaxim() {
WinGet, wMM, MinMax, A
If wMM = 1 ;already maximized
WinRestore, A
Else WinMaximize, A
GuiControl, Focus, RICHEDIT50W1
}
cpBresto() {
static x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6
WinGet, wMM, MinMax, A
If wMM = 0 ;already restored
{ WinGetPos, GuiX,,,, A
If (GuiX + x >= A_ScreenWidth)
Gui, Show, x-5 y51 h%h% w%w%
Else Gui, Show, x%x% y51 h%h% w%w%
}Else WinRestore, A
GuiControl, Focus, RICHEDIT50W1
}
cpBminim() {
WinMinimize, A
}
cpEventHdlr() {
global lbduration
IfWinActive, Context Peeking
{ ControlGetFocus, foco, A
If (foco not = "RICHEDIT50W1")
{ MouseGetPos,,, mow, moc
If not (mow = WinExist("Context Peeking") and InStr(moc, "Button"))
GuiControl, Focus, RICHEDIT50W1
}
}
v := this.ov
If (this[v].CPseleT = this.CP.Selection.Text)
Return
If GetKeyState("RButton", "P")
Return
Sleep, 500 ;this "sleep" exists with reason
If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
Return
If not this[v].xFlag and WinActive("Context Peeking") and StrLen(this.CP.Selection.Text)
{ this[v].xFlag := True, slcs := this.CP.Selection.Start
If InStr("`r`n", SubStr(this.CP.Selection.Text, 0))
this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
Else
{ MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
IfMsgBox, Yes
{ Clipboard := this[v].CPseleT := this.CP.Selection.Text
Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
Sleep, 500
Progress, Off
If lbduration > 1000
{ WinMinimize
ControlSetText, Edit1, % Trim(Clipboard), % "ahk_id " this[v].ParWin
}
}IfMsgBox, No
this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
Sleep, 500 ;this "sleep" exists with reason
}
this[v].xFlag := False, this[v].CPseleT := this.CP.Selection.Text
}
}
tw4sh(t) {
tog := "\/", va := "?\\'\w", ph := "[^" va "\n]", tar := "\" tog ph "*?\K[" va "]", ph := "[^\w\n]"
If mpos:=RegExMatch(t, tar) ;contained toggle (on)
{ pb := "[^\w\n]", sh := "((?<=^|" ph ")", st := "(?=(\W|$)))"
skip_c := skip_w := yb := False
r := StrReplace(SubStr(t, 1, mpos - 1), tog) sh, rr := xx := ""
Loop
{ c := SubStr(t, mpos, 1), cc := SubStr(t, mpos + 1, 1)
If skip_c
skip_c--
Else If SubStr(t, mpos, StrLen(tog)) = tog ;toggle (off) encountered
{ this.flush(r, xx, pb, yb, st), rr := xx := ""
mpos += StrLen(tog), npos := mpos
If mpos:=RegExMatch(t, tar,, npos) ;found next toggle (on)
r .= StrReplace(SubStr(t, npos, mpos - npos), tog) sh, rr := xx := ""
Else
{ r .= SubStr(t, npos)
Break
}
Continue
}Else If RegExMatch(c, "\w") or (c = "?") ;valid character
{ If rr
If not skip_w and ((cc not = "/") or StrLen(xx))
this.flush(r, xx, pb, yb)
Else If (cc = "/") and not StrLen(xx)
{ If SubStr(t, mpos + 2, 1) = "/"
skip_w := skip_w ? skip_w : True, skip_c++
skip_c++
}Else{}
Else If StrLen(rr)
r .= xx sh, rr := xx := ""
r .= (c = "?") ? (skip_w ? "\w" : ("\w+?", yb++)) : c (skip_w ? "" : ("\w*?", yb++)), skip_w -= skip_w ? 1 : 0, rr := True
}Else If (c = A_Space) and rr
this.flush(r, xx, pb, yb, st), xx := A_Space, rr := 0
Else If (c = "'")
xx .= "\W"
Else If (c = "\") and skip_w not < 0
If (cc == "Q")
skip_c++, skip_w := -1, this.flush(r, xx, pb, yb)
Else If (cc == "E")
skip_c++, skip_w := False
Else If (cc = c)
xx .= c
Else If RegExMatch(cc, "\w")
skip_c++, xx .= cc
Else skip_c++, xx .= c cc
Else xx .= c
mpos++
If (mpos > StrLen(t)) ;exceeded
{ If rr
this.flush(r, xx, pb, yb, st), rr := xx := ""
Break
}
}
}Else r := t
Return r
}
flush(ByRef r, ByRef xx, pb, ByRef yb, st := "") {
mb := "[^,;\w\n.?!]+?", ss := SubStr(xx, -1), sc := (ss == "\W") or (ss == "\s") or (ss == "\t") or (ss == "\r") or (ss == "\n"), r .= xx ? (RegExMatch(SubStr(xx, 1, 1), "\w") ? mb : pb "*?") xx (st ? ")" : (RegExMatch(ss, "\\?\w$") and not sc ? "" : pb "*?")) : (st ? st : (yb ? (mb, yb--) : "")), xx := ""
}
StrRepeat(string, times) {
Loop, %times%
output .= string
Return output
}
escrx(h) {
e := "\().[]*+?{}^$|"
Loop, Parse, e
If InStr(h, A_LoopField)
h := StrReplace(h, A_LoopField, "\" A_LoopField)
Return h
}
ReverseByLine(ByRef text, delimiter := "`n") {
array := StrSplit(SubStr(text, 0) = delimiter ? SubStr(text, 1, StrLen(text) - 1) : text, delimiter), mi := array.MaxIndex()
Loop, % mi
If A_Index > 1
text .= array[mi - A_Index + 1] delimiter
Else text := array[mi] delimiter
}
ListGlobalVars() { ;written by Lexikos
static hwndEdit, pSFW, pSW, bkpSFW, bkpSW
If !hwndEdit
{ dhw := A_DetectHiddenWindows
DetectHiddenWindows, On
Process, Exist
ControlGet, hwndEdit, Hwnd,, Edit1, ahk_class AutoHotkey ahk_pid %ErrorLevel%
DetectHiddenWindows, %dhw%
astr := A_IsUnicode ? "astr":"str"
ptr := A_PtrSize=8 ? "ptr":"uint"
hmod := DllCall("GetModuleHandle", "str", "user32.dll")
pSFW := DllCall("GetProcAddress", ptr, hmod, astr, "SetForegroundWindow")
pSW := DllCall("GetProcAddress", ptr, hmod, astr, "ShowWindow")
DllCall("VirtualProtect", ptr, pSFW, ptr, 8, "uint", 0x40, "uint*", 0)
DllCall("VirtualProtect", ptr, pSW, ptr, 8, "uint", 0x40, "uint*", 0)
bkpSFW := NumGet(pSFW+0, 0, "int64")
bkpSW := NumGet(pSW+0, 0, "int64")
}
If (A_PtrSize=8)
{ NumPut(0x0000C300000001B8, pSFW+0, 0, "int64") ;return TRUE
NumPut(0x0000C300000001B8, pSW+0, 0, "int64") ;return TRUE
}Else
{ NumPut(0x0004C200000001B8, pSFW+0, 0, "int64") ;return TRUE
NumPut(0x0008C200000001B8, pSW+0, 0, "int64") ;return TRUE
}
ListVars
NumPut(bkpSFW, pSFW+0, 0, "int64")
NumPut(bkpSW, pSW+0, 0, "int64")
ControlGetText, text,, ahk_id %hwndEdit%
RegExMatch(text, "sm)(?<=^Global Variables \(alphabetical\)`r`n-{50}`r`n).*", text)
Return text
}
HelpPage() {
HelpPage=
(
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil\fcharset0 Consolas;}}
{\colortbl ;\red255\green0\blue0;\red155\green0\blue211;\red0\green77\blue187;\red0\green176\blue80;\red0\green0\blue255;}
{\*\generator Riched20 10.0.19041}\viewkind4\uc1
\pard\sa200\sl276\slmult1\b\fs36\lang9 H e l p _ P a g e\b0\par
\par
\cf1\b F1\cf0\b0 - to toggle this help page\par
\par
\b Basic syntax by example:\b0\par
\pard\li720\sa200\sl276\slmult1 coexisting words/strings/patterns -unwanted\par
for instance, \cf2\b\f1 d.*d -the and -oo \\ws\cf0\b0\f0\par
(the 5 segments (space separated) above can go all at once, and yet, they can also be entered one by one. that's the so-called multilevel approach, instead.)\par
\pard\sa200\sl276\slmult1\par
\b Feature keys:\b0\par
\pard\li720\sa200\sl276\slmult1\cf3\b Alt+a\cf0\b0 - to show assorted matches and toggle between chronological and alphabetical order.\par
\cf3\b Ctrl+t\cf0\b0 - to put assorted matches into a treeview gui which may ease the exploration when the list is long and involved multiple groups.\par
\cf3\b Ctrl+p\cf0\b0 - to bring up context peeking gui which provides an integrated way of reviewing the context of any lines in the shortlisted result.\par
\cf3\b WheelDown\cf0\b0 - to find the next match (downward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b WheelUp\cf0\b0 - to find the next match (upward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b Alt+v\cf0\b0 - to paste clipboard content into the big text/edit box.\par
\cf3\b Ctrl+o\cf0\b0 - to open a file.\par
\cf3\b Ctrl+r\cf0\b0 - to reload the file.\par
\cf3\b Rightclick\cf0\b0 "Back" button - to glance committed levels and select one to fall back to.\par
\cf3\b Esc\cf0\b0 - to quit/exit/leave. same as closing the window.\par
\cf3\b Tab\cf0\b0 - to change focus between the text/edit boxes (just try it.)\par
\par
these below only work when the \ul big\ulnone text/edit box is in focus:\par
\pard\li1440\sa200\sl276\slmult1\cf3\b f\cf0\b0 - to find the next match (downward) from the caret position.\par
\cf3\b Shift+f\cf0\b0 - to find the next match (upward) from the caret position.\par
\i (note: "the line" refers to the current line, that's where the caret is on.)\i0\par
\cf3\b Doubleclick\cf0\b0 - to copy the line/selection.\par
\cf3\b Enter\cf0\b0 - to copy the line/selection.\par
\cf3\b Space\cf0\b0 - to page down\par
\cf3\b Shift+Space\cf0\b0 - to page up\par
\cf3\b s\cf0\b0 - to move the caret to the beginning/start of the line.\par
\cf3\b e\cf0\b0 - to move the caret to the end of the line.\par
\cf3\b t\cf0\b0 - to move the caret to the top of the text.\par
\cf3\b b\cf0\b0 - to move the caret to the bottom of the text.\par
\cf3\b + or =\cf0\b0 - to increase font size (same as \cf3\b Ctrl+WheelUp\cf0\b0 ).\par
\cf3\b minus "-"\cf0\b0 - to decrease font size (same as \cf3\b Ctrl+WheelDown\cf0\b0 ).\par
\i (side note: "caret" may be known as "cursor" to some people.)\i0\par
\pard\sa200\sl276\slmult1\par
\tab these below only work when the \ul small\ulnone text/edit box is in focus:\par
\pard\li1440\sa200\sl276\slmult1\cf3\b Enter\cf0\b0 - to commit a level (which makes the current result becoming the base/source of the next level.) same as clicking the button Go.\par
\pard\sa200\sl276\slmult1\par
\pard\li720\sa200\sl276\slmult1\cf3\b Backtick (``)\cf0\b0 - since users mostly use this tool to locate the specific line of text and copy it for whatever subsequent actions to be taken, which typically involves Tab and then Enter (if the first line is the one wanted), backtick is an alternative which can supersede both keys by just hit backtick twice instead.\par
\pard\sa200\sl276\slmult1\par
The \b improvised shorthand\b0 feature:\par
\pard\li720\sa200\sl276\slmult1 this feature can be triggered through "\cf2\b\\/\cf0\b0 " (a \b backslash\b0 followed by a \b slash\b0 ), a "regex like" syntax style, which toggle it on or off. so, enter "\cf2\b\\/tr\cf0\b0 " will bring you those lines contained "\cf4\i the road\cf0\i0 ", "\cf4\i two roads\cf0\i0 ", as well as "\cf4\i them really\cf0\i0 " out of the poem, whereas enter "\cf2\b oo \\/a?a\cf0\b0 " or "\cf2\b\\/a?a\\/ oo\cf0\b0 " will return you these two lines "\cf4\i And looked down one as far as I could\cf0\i0 " and "\cf4\i Then took the other, as just as fair,\cf0\i0 " in which, the "\cf2\b ?\cf0\b0 " represents any valid character regex recognized it as "word" element. Besides, the space has been cared so that the toggle works across it. for instance, enter "\cf2\b\\/tr yw\cf0\b0 " or "\cf2\b\\/yw tr\cf0\b0 " will show this line "\cf4\i Two roads diverged in a yellow wood,\cf0\i0 " where the space is still a separator as always, even though the shorthand feature is toggled on.\par
\pard\sa200\sl276\slmult1\par
\tab three more elements of the shorthand syntax:\par
\par
\pard\fi-360\li1800\sa200\sl276\slmult1 1, \b extra qualifier\b0 (within a single word);\par
2, \b escape character\b0 (between words);\par
3, a single \b character\b0 representing any "\b non-word\b0 " one (between words).\par
\pard\sa200\sl276\slmult1\par
\pard\li720\sa200\sl276\slmult1 the most basic usage of improvised shorthand is to match the specific "phrase" by just entering the first letter of each word constituted it (for instance, "\cf2\b sameto\cf0\b0 " can match "\cf4\i some are more equal than others\cf0\i0 ") yet sometimes we may want to further narrow down the result. if "\cf2\b slh\cf0\b0 " brings you both "\cf4\i she likes him\cf0\i0 " and "\cf4\i she loves him\cf0\i0 ", an extra qualifier to pinpoint one may be useful. it could simply be a "v" for this example hence "\cf2\b slv/h\cf0\b0 " (in which, the "/" after the "v" tells the system that it's just an extra qualifier to the "l", not for a word starts with "v",) returns you "\cf4\i she loves him\cf0\i0 " only. likewise, you may sometimes want to tell the system exactly what the word should be ending with, for instance, if "\cf2\b ioy\cf0\b0 " brings you both "\cf4\i i owe you\cf0\i0 " and "\cf4\i i own you\cf0\i0 ", "\cf2\b ioe//y\cf0\b0 " (in which, the "//" after the "e" tells the system that it's a word ending character, that is, "oe//" represents a word starts with "o" and ends with "e") returns you "\cf4\i i owe you\cf0\i0 " only. and no matter how rare (and impractical) it may be, you may have multiple of these qualifiers for a word, such as, "\cf2\b cm/c/e//d//\cf0\b0 " can match the word "\cf4\i complicated\cf0\i0 " whereas "\cf2\b td/i/u//s//\cf0\b0 " can match the word "\cf4\i tedious\cf0\i0 ".\par
\par
a \b backslash\b0 "\cf2\b\\\cf0\b0 " may be used to escape a single character after it. its target should be a "word" character because you don't need to escape otherwise. for all "non-word" character, just enter them directly except "\\" itself which requires a \b double backslash\b0 "\cf2\b\\\\\cf0\b0 " for a single one. for regex syntax such as "\\s", it becomes "\\\\s" (not "\\\\\\s" you may presume.) in other words, all escaped character will only be matched barely itself. for \ul consecutive\ulnone "word" characters that need to be escaped, enclose them in the \cf2\b\\Q\cf0\b0 \cf2\b\\E\cf0\b0 pair, similar idea as in regex. one thing to note though, escaped character may affect the word immediately after it, for instance, "\cf2\b z\\xy\cf0\b0 " may bring you "\cf4\i zebra xylophone\cf0\i0 " rather than "\cf4\i zombie x yesterday\cf0\i0 ".\par
\par
an \b apostrophe\b0 "\cf2\b\f1 '\cf0\b0\f0 " may be used to represent any "non-word" character. that is, same as "\\\\W" (the regex syntax "\\W" for a "non-word" character). it may be useful at the (beginning and/or ending) ends of the "phrase" if it can further narrow down the result or you simply want it to be a part of the match.\par
\pard\sa200\sl276\slmult1\par
The \b matches highlighting\b0 feature:\par
\pard\li720\sa200\sl276\slmult1 the \ul default behavior\ulnone is to highlight no more than a thousand matches (which can improve the response time when too many matches are found.) it can nonetheless be overridden by a long press of your left mouse button on one of the available gui buttons (i.e. go or refresh or back), whereas long press means press it down and hold on for \ul one second or longer\ulnone . therefore, highlighting will cover the whole thing even if the total number of matches is over \ul one thousand\ulnone . this \ul long-press-to-override\ulnone is not a toggle, it's just an \ul one-off\ulnone thing, so do it every time you want more than the default.\par
\pard\sa200\sl276\slmult1\par
End of this help page.\par
}
)
Return HelpPage
}
} ;end of class
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
- Kellyzkorner_NJ
- Posts: 84
- Joined: 20 Oct 2017, 18:33
Re: Text Filter
@SundayProgrammer I was wondering if your last iteration of this fantastic script is to translate, converting to letters? I'm sorry for being thick about this if I'm wrong. Thanks again for this, I use it often.
-
- Posts: 143
- Joined: 25 Dec 2020, 12:26
Re: Text Filter
@Kellyzkorner_NJ i'm glad you you like it, and thank you for letting me know. i myself use it everyday.Kellyzkorner_NJ wrote: ↑29 Sep 2021, 11:20@SundayProgrammer I was wondering if your last iteration of this fantastic script is to translate, converting to letters? I'm sorry for being thick about this if I'm wrong. Thanks again for this, I use it often.
for the "last iteration", it's about being all the way stay in english, yet, can search text in other languages directly. (a) no need to change language, back and forth, at operating system level. (b) nor need to go through the "normal" inputting process which usually involved looking up the right one from a matched word list (a typical "'ime" way of doing thing), word by word, until the whole search term is completely entered in that language. and (c) don't even need to bother installing a language pack if that language pack hasn't yet been installed in the machine, one is using for the task.
- Kellyzkorner_NJ
- Posts: 84
- Joined: 20 Oct 2017, 18:33
Re: Text Filter
@SundayProgrammer Thanks very much for the explanation.
Kelly
Kelly
Return to “Scripts and Functions (v1)”
Who is online
Users browsing this forum: No registered users and 47 guests