Advertisement
pk3456

RegexTester(RE)

Nov 18th, 2023
1,268
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #Requires AutoHotkey v2.0
  2. #SingleInstance Force
  3. #Include RichEdit.ahk
  4.  
  5. ;Default Values
  6.     defText := 'History`n`nThe first public beta of AutoHotkey was released on November 10, 2003[10] after author Chris Mallett`'s proposal to integrate hotkey support into AutoIt v2 failed to generate response from the AutoIt community.[11][12] So the author began his own program from scratch basing the syntax on AutoIt v2 and using AutoIt v3 for some commands and the compiler.[13] Later, AutoIt v3 switched from GPL to closed source because of "other projects repeatedly taking AutoIt code" and "setting themselves up as competitors."[14]`n`nIn 2010, AutoHotkey v1.1 (originally called AutoHotkey_L) became the platform for ongoing development of AutoHotkey.[15] Another port of the program is AutoHotkey.dll.[16]`n`nhttps://en.wikipedia.org/wiki/AutoHotkey`n'
  7.     defRegex := "A[^\s]*?y"
  8.  
  9. ;Gui Stuff
  10.     font := "Consolas", w := 800, _w := 200 ;button width
  11.     gGui := Gui(, "Regular Expression Tester for AutoHotkey v2"), gGui.SetFont(, font)
  12.     gGui.Add("Text", , "RegEx String:"),    regex  := gGui.Add("Edit", "-wrap r1 w" w, defRegex)    ;setup regex box
  13.     gGui.Add("Text", , "Text:"),            text   := RichEdit(gGui, "r35 w" w)                     ;setup RichEdit box
  14.     text.SetText(defText)
  15.     gGui.Add("Text", , "Results:"),         result := gGui.Add("Edit", "+readonly r15 w" w)         ;setup result box
  16.     n2r := gGui.Add("CheckBox", "checked", "Convert ``n (\n) to ``r (\r)")
  17.     n2r.GetPos(,, &n2rPosW)
  18.     n2r.move(w - gGui.MarginX - n2rPosW, gGui.MarginY)
  19.     gcToolTip.Add(n2r, "Enabling this option is recommended`nbecause this RichEdit box only uses ``r (\r).")
  20.     btn := gGui.Add("Button", "yp0 w" _w " x" w / 2 + gGui.MarginX - _w / 2 " Default", "Test RegEx (F5)") ;test button
  21.     gGui.OnEvent("Close", (*)=>(text:="",ExitApp())),   btn.OnEvent("Click", (*)=>doRegEx())    ;Run doRegEx() whenever changes are detected
  22.     gGui.show(), doRegEx()
  23.  
  24. f5::doRegEx()
  25. ;*To do: add navigation to next/prev match, add replace box, replace by function?
  26.  
  27. ;called by RegExFunc in RichEdit for each match ... to do: add RTF directly
  28. onMatch(oRE, _, sp, len) => oRE.SetSel(sp - 1, sp + len - 1) && oRE.SetFont({BkColor:"YELLOW"})
  29.  
  30. ;perform RegEx, highlight and print results
  31. doRegEx() {
  32.     global gui, regex, text, result, n2r
  33.     rstr := regex.value, result.value := "" ;reset the result box
  34.  
  35.     ;replace escaped `(backticks)
  36.     list := n2r.value ? Map("``n","`r", "\n","\r", "``t","`t", "``r","`r") : Map("``n","`n", "``t","`t", "``r","`r")
  37.     for k, v in list
  38.         qreplace(&rstr, k, v)
  39.  
  40.     ;attempt RegExMatch
  41.     try
  42.         if pos := RegExMatch(text.GetText(), rstr, &m) { ;if we have a match
  43.  
  44.             ;highlight matches - to do: restore scroll position.                *To do: use RTF directly
  45.             sel := text.GetSel()                                                ;save caret position
  46.             match := RegExFunc(text, rstr, (param*) => onMatch(text, param*))   ;highlight matches with onMatch()
  47.             text.SetSel(sel.S, sel.E)                                           ;restore caret position
  48.  
  49.             ;prepare matchedText for result output
  50.             for k, v in match
  51.                 matchedText .= (k==1 ? "" : chr(0x2DDF)) . v
  52.             matchedText := Sort(matchedText, "F mySort D" chr(0x2DDF))          ;sort lengthwise and alphabetically
  53.             _match := StrSplit(matchedText, chr(0x2DDF)), _mDict := Map()       ;count duplicates
  54.             for k, v in _match                                                  ;
  55.                 _mDict.Has(v) ? _mDict[v] += 1 : _mDict[v] := 1                 ;*To do: can probably make this better
  56.             matchedText := Sort(matchedText, "U F mySort D" chr(0x2DDF))        ;remove duplicates and keep sort order by re-sorting
  57.             _match := StrSplit(matchedText, chr(0x2DDF)), matchedText := ""     ;
  58.             for k, v in _match                                                  ;prep output
  59.                 _v := "`t" StrReplace(v, "`r", "`n`t")
  60.                 , matchedText .= format("{:-12}{:}", (k == 1 ? "" : "`n") "[" k "] x " . _mDict[v],  _v)
  61.  
  62.             ;print results
  63.             result.value .=   "First match at: " . pos . "`n"
  64.                             . "Total matches : " . match.Length . "`n"
  65.                             . "Unique matches: " . _match.Length . "`n" . matchedText . "`n`n"
  66.                             . "Number of captured subpatterns: " . m.Count . "`n"
  67.             Loop m.Count
  68.                 result.value .= "[" A_Index "]" . (m.Name(A_Index) ? " (" m.Name(A_Index) ")" : "")     ;if it has a name show it
  69.                 . " pos: " m.Pos(A_Index) . ", len: " m.Len(A_Index) " => " . Match[A_Index] "`n"
  70.  
  71.             if m.Mark   ;untested, included for completeness sake
  72.                 result.value .= "Name of last encountered (*MARK:NAME): " m.Mark "`n"
  73.         }
  74.         else result.value .= "No matches found.`n", text.text := text.text ;reset format
  75.  
  76.     ;RegExMatch exceptions : straight from AutoHotkey documentation
  77.     catch as e
  78.         result.value := e.message != "PCRE execution error." ? e.message : 'PCRE execution error. (' e.extra ')`n`nLikely errors: "too many possible empty-string matches" (-22), "recursion too deep" (-21), and "reached match limit" (-8). If these happen, try to redesign the pattern to be more restrictive, such as replacing each * with a ?, +, or a limit like {0,3} wherever feasible.'
  79.  
  80.     ;helper functions
  81.     mySort(a, b) => StrLen(a) != StrLen(b) ? StrLen(a) - StrLen(b) : ((a > b) + !(a = b) - 1.5) * (a != b) * 2 ;sort by length then by alphabetical order
  82.     qreplace(&str, a, b) => str := StrReplace(str, a, b)    ;by reference StrReplace wrapper
  83. }
  84.  
  85. ;helper class for adding gui tooltips
  86. class gcToolTip {
  87.     static gTT := Map()
  88.     static Add(guictrl, tt, to := 4000) { ;gui, tooltip, timeout
  89.         (this.gTT.Count == 0) && OnMessage(0x200, (param*) => this.WM_MOUSEMOVE(param*))
  90.         this.gTT[guictrl.Hwnd] := {tooltip:tt, timeout:to}
  91.     }
  92.     static WM_MOUSEMOVE(_, __, ___, Hwnd) {
  93.         static PrevHwnd := 0
  94.         if (Hwnd != PrevHwnd)
  95.             PrevHwnd := Hwnd, ToolTip(), this.gTT.Has(Hwnd) && ToolTip(this.gTT[Hwnd].tooltip)
  96.     }
  97. }
  98.  
  99. RegExFunc(richedit, needle, function) {
  100.     if isObject(function) && function.isBuiltIn != "" {
  101.         textLen := richedit.GetTextLen(), text := richedit.GetText(), sp := 0, len := 1, match := []
  102.         while sp < textLen && sp := RegExMatch(text, needle, &m, sp + len)
  103.             len := m.len > 0 ? m.len : 1
  104.             , _match := SubStr(text, sp, m.Len)
  105.             , match.push(_match)
  106.             , function.Call(_match, sp, len)
  107.         return match
  108.     }
  109.     else
  110.         return false
  111. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement