This is not an update of the AutoCorrect for v2 (ac2) "package" but rather a couple of related tools.
It occurred to me that if people are using older versions of ac2, they might have added lots of cool new custom autocorrect entries via the HotString Helper tool. If those new custom hotstrings are still at the bottom of your ac2 file, then no problem... Copy-n-paste the new items over to the newer versions of ac2 as they are released...
However... Some folks might like to alpha-sort their hotstrings. (At least that's what I do--LOL) If that is the case, how can you "
bring over" your new custom items to the latest release of the ac2 script?
That's what this first script is for...
IMPORTANT:
- I left the file path to my own ac2 file (which I call "MasterScript") as an example, but delete that, and use your own scripts and related directory/paths.
- Remember to scan the .ahk files, not the same-named .exe files.
- If you kept the name "AutoCorrect for v2.ahk", then you might rename that to something like, "AutoCorrect for v2_OLD.ahk"
- Put the newer version and the older version in the same folder as this script, so that the folder contains the files:
Unique string finder.ahk
AutoCorrect for v2.ahk
AutoCorrect for v2_OLD.ahk
- If they are all in the same folder, you can probably just at the file names in the code, and not the whole directory path.
- If the Unique String Finder works correctly, It will create a text file with a list of the unique items, then it will open that text file and beep twice.
- Please note that this will not identify any unique Hotkeys or code that you added... Only hotstrings.
Code: Select all
#SingleInstance
#Requires AutoHotkey v2+
; A script to find duplicate hotstrings that are in one file but not another.
; Intended for updating AutoHotkey scripts. kunkel321 2-28-2024.
; Please ensure that is it pointing to two valid files.
; The "mainFile" is the file that you plan to use--it is your new AutoCorrect file.
; The "extraFile" is a different version of your file, that might have new custom hotstrings
; added, that are not in the new mainFile.
mainFile := "D:\AutoHotkey\MasterScript\MasterScript.ahk" ; <--- Your AutoCorrect.ahk file path here.
extraFile := "D:\AutoHotkey\MasterScript\MasterScriptPartialTemp.ahk"
^Esc::ExitApp ; <----- Emergency kill switch is Ctrl+Esc.
Try fullList := Fileread(mainFile) ; Make sure file exists and save contents for variable.
Catch {
MsgBox '====ERROR====`n`nThe file (' mainFile ')`nwas not found.`n`nRemember to set the three variables`nat the top of the script. Now exiting.'
ExitApp
}
Try extraList := Fileread(extraFile) ; Make sure file exists and save contents for variable.
Catch {
MsgBox '====ERROR====`n`nThe file (' extraFile ')`nwas not found.`n`nRemember to set the three variables`nat the top of the script. Now exiting.'
ExitApp
}
StartTime := A_TickCount
Opts:= "", Trig := ""
DupReport := "", Count := 0
TotalLines := StrSplit(fullList, "`n").Length ; Determines number of lines for Prog Bar range.
rep := Gui()
rep.Opt("-MinimizeBox +alwaysOnTop +Owner")
MyProgress := rep.Add("Progress", "w400 h30 cGreen Range0-" . TotalLines, "0")
rep.Title := MyProgress.Value
rep.Title := "Lines of file remaining: "
rep.Show()
; Loop through Main File contents, then remove any matching lines from the Extra File contents.
loop parse fullList, "`n" {
MyProgress.Value += 1
rep.Title := "Lines of file remaining: " (TotalLines - MyProgress.Value) "... Press Ctrl+Esc to Cancel" ; For progress bar.
extraList := strReplace(extraList, A_LoopField, "`nxxxxxx",,,1) ; Remove the item because it exists in both files.
}
; Loop through the Extra Files, and extract anything that wasn't replaced with "xxxxxx."
loop parse extraList, "`n" {
If (SubStr(trim(A_LoopField, " `t"), 1,1) = ":") ; Only include lines starting with ":"
{ DupReport .= A_LoopField "`n"
Count++
}
}
ElapsedTime := (A_TickCount - StartTime) / 1000 ; Calculate and format time taken.
ElapsedTime := "Found " Count " unique items in " Round(ElapsedTime / 60) "-min " Round(mod(ElapsedTime, 60)) "-sec."
rep.Destroy() ; Remove progress bar.
FullReport := DupReport
If FullReport = ""
FullReport := "No unique hotstrings found in " extraFile "."
FullReport := ElapsedTime "`n=================================`n" FullReport
Location := A_ScriptDir "\Uniques_Report" FormatTime(A_Now, "_MMM_dd_hh_mm") ".txt"
FileAppend FullReport, Location ; Save to text file, then open the file.
sleep 250
Run Location
SoundBeep 1800, 700
SoundBeep 1200, 200
ExitApp
The above script is pretty fast, but the below one is way more thorough and takes longer...
IMPORTANT: The above script compares TWO files, but the below one only looks in a single file. Again, change the name of the file to your own AutoCorrect.ahk (not exe) file. Also note, this script also appeared on this thread, a couple of pages back...
Code: Select all
#SingleInstance
#Requires AutoHotkey v2+
; A script to find duplicate and conflicting beg/mid/end hotstring triggers. By kunkel321 2-28-2024.
; It should work with hotstrings that are formatted with f(), _HS(), or plain AHK hotstrings.
; Note: When correcting/culling your autocorrect library, remember that sometimes conflicting
; autocorrect items can peacefully coexist... Read more in manual, attached here
; https://www.autohotkey.com/boards/viewtopic.php?f=83&t=120220&p=559727#p559328
; Warning: Sloooww script.... Takes about 6 minutes for 5k lines of autocorrect items.
; !!! IMPORTANT !!! Set first three variables.
ACitemsStartAt := 2025 ; <--- "AutoCorrect Items Start At this line number." Skip this many
; lines at top of code. Recommend not scanning 'nullifier' items, 'don't sort' items,
; nor '#HotIf' items. (Hopefully those are all at the top, above your main list.)
ACitemsEndAt := 6790 ; <--- stop comparing after this line number. No point scanning the non-English accented words.
targetFile := "D:\AutoHotkey\MasterScript\MasterScript.ahk" ; <--- Your AutoCorrect.ahk file path here.
^Esc::ExitApp ; <----- Emergency kill switch is Ctrl+Esc.
If !ACitemsStartAt
ACitemsStartAt := 0
If !ACitemsEndAt
ACitemsEndAt := 99999
Try fullList := Fileread(targetFile)
Catch {
MsgBox '====ERROR====`n`nThe file (' targetFile ')`nwas not found.`n`nRemember to set the three variables`nat the top of the script. Now exiting.'
ExitApp
}
StartTime := A_TickCount
Opts:= "", Trig := ""
DupReport := "", BegReport := "", MidReport := "", EndReport := "", Count := 0
Separator := "`n---------------------------------------`n"
hsRegex := "i):(?P<Opts>[^:]+)*:(?P<Trig>[^:]+)" ; part of andymbody's regex
TotalLines := StrSplit(fullList, "`n").Length ; Determines number of lines for Prog Bar range.
rep := Gui()
rep.Opt("-MinimizeBox +alwaysOnTop +Owner")
MyProgress := rep.Add("Progress", "w400 h30 cGreen Range0-" . TotalLines, "0")
rep.Title := MyProgress.Value
rep.Title := "Lines of file remaining: "
rep.Show()
loop parse fullList, "`n" {
MyProgress.Value += 1
rep.Title := "Lines of file remaining: " (TotalLines - MyProgress.Value) "... Press Ctrl+Esc to Cancel" ; For progress bar.
fullList := strReplace(fullList, A_LoopField, "xxxxxx",,,1) ; Redact the oLoop item we just checked, so we don't compare it again in a future inner loop.
If (A_Index < ACitemsStartAt) or (A_Index > ACitemsEndAt) or (SubStr(trim(A_LoopField, " `t"), 1,1) != ":")
Continue ; Skip if line number is too high/low, or line doesn't start with ":". Ignore leading whitespace.
oLoop := A_LoopField ; "o" for "outter"
oIdx := A_Index
if regexMatch(oLoop, hsRegex, &o) {
loop parse fullList, "`n" {
If (A_Index < ACitemsStartAt) or (A_Index > ACitemsEndAt) or (SubStr(trim(A_LoopField, " `t"), 1,1) != ":")
Continue ; Skip if line number is too high/low, or line doesn't start with ":". Ignore leading whitespace.
iLoop := A_LoopField ; "i" for "inner"
iIdx := A_Index
If regexMatch(iLoop, hsRegex, &i) {
;msgBox o.Opts " " o.Trig "`n---------`n" i.Opts " " i.Trig
If (o.Trig = i.Trig) and (o.Opts = i.Opts) { ; Duplicates
DupReport .= Separator
DupReport .= "Line: " oIdx "`t`t" o.Trig (strLen(o.Trig)<8?"`t`t":"`t") oLoop "`n"
DupReport .= "-and: " iIdx "`t`t" i.Trig (strLen(i.Trig)<8?"`t`t":"`t") iLoop "`n"
Count++
}
Else If (InStr(i.Trig, o.Trig) and inStr(o.Opts, "*") and inStr(o.Opts, "?"))
|| (InStr(o.Trig, i.Trig) and inStr(i.Opts, "*") and inStr(i.Opts, "?")) { ; Word-Middle Matches
MidReport .= Separator
MidReport .= "Line: " oIdx "`t" strReplace(strReplace(o.Opts, "B0", ""),"X", "") "`t" o.Trig (strLen(o.Trig)<8?"`t`t":"`t") oLoop "`n"
MidReport .= "-and: " iIdx "`t" strReplace(strReplace(i.Opts, "B0", ""),"X", "") "`t" i.Trig (strLen(i.Trig)<8?"`t`t":"`t") iLoop "`n"
Count++
}
Else If ((i.Trig = o.Trig) and inStr(i.Opts, "*") and inStr(o.Opts, "?"))
|| ((o.Trig = i.Trig) and inStr(i.Opts, "?") and inStr(o.Opts, "*")) ; Rule out: Same word, but beginning and end opts
Continue
Else If (inStr(i.Opts, "*") and i.Trig = subStr(o.Trig, 1, strLen(i.Trig)))
|| (inStr(o.Opts, "*") and o.Trig = subStr(i.Trig, 1, strLen(o.Trig))) { ; Word-Beginning Matches
BegReport .= Separator
BegReport .= "Line: " oIdx "`t" strReplace(strReplace(o.Opts, "B0", ""),"X", "") "`t" o.Trig (strLen(o.Trig)<8?"`t`t":"`t") oLoop "`n"
BegReport .= "-and: " iIdx "`t" strReplace(strReplace(i.Opts, "B0", ""),"X", "") "`t" i.Trig (strLen(i.Trig)<8?"`t`t":"`t") iLoop "`n"
Count++
}
Else If (inStr(i.Opts, "?") and i.Trig = subStr(o.Trig, -strLen(i.Trig)))
|| (inStr(o.Opts, "?") and o.Trig = subStr(i.Trig, -strLen(o.Trig))) { ; Word-Ending Matches
EndReport .= Separator
EndReport .= "Line: " oIdx "`t" strReplace(strReplace(o.Opts, "B0", ""),"X", "") "`t" o.Trig (strLen(o.Trig)<8?"`t`t":"`t") oLoop "`n"
EndReport .= "-and: " iIdx "`t" strReplace(strReplace(i.Opts, "B0", ""),"X", "") "`t" i.Trig (strLen(i.Trig)<8?"`t`t":"`t") iLoop "`n"
Count++
}
}
Else ; not a regex match, so go to next loop.
continue
}
}
;msgBox fullList
}
If (DupReport != "") ; Create headings only for needed parts.
DupReport := "Duplicates:" DupReport "`n"
If (BegReport != "")
BegReport := "Beginnings:" BegReport "`n"
If (MidReport != "")
MidReport := "Middles:" MidReport "`n"
If (EndReport != "")
EndReport := "Endings:" EndReport "`n"
ElapsedTime := (A_TickCount - StartTime) / 1000 ; Calculate and format time taken.
ElapsedTime := "Found " Count " item pairs in " Round(ElapsedTime / 60) "-min " Round(mod(ElapsedTime, 60)) "-sec."
rep.Destroy() ; Remove progress bar.
FullReport := DupReport BegReport MidReport EndReport
If FullReport = ""
FullReport := "No duplicate or conflicting hotstring pairs located."
FullReport := ElapsedTime "`nLine`tOpt`tTrigger`tFull item`n=================================`n" FullReport
Location := A_ScriptDir "\Conflict_Report" FormatTime(A_Now, "_MMM_dd_hh_mm") ".txt"
FileAppend FullReport, Location ; Save to text file, then open the file.
sleep 1000
Run Location
; msgbox FullReport
SoundBeep 1800, 700
SoundBeep 1200, 200
ExitApp