AutoCorrect for v2

Post your working scripts, libraries and tools.
dorito
Posts: 4
Joined: 14 Nov 2023, 05:10

Re: AutoCorrect for v2

15 Nov 2023, 06:46

@kunkel321 Thanks for the guidance. I have now replaced the line "FileCopy "AutoCorrect.ahk", "AutoCorrect_backup.ahk", 1" with the lines...

Code: Select all

  backupFilename := "AutoCorrect_" A_YYYY "-" A_MM "-" A_DD "_" A_Hour "-" A_Min "-" A_Sec ".ahk" ; This will make it AutoCorrect_YYYY-MM-DD_HH24-MI-SS.ahk
  FileCopy "AutoCorrect.ahk", backupFilename, 1
[Mod edit: + code tags.]

And now it all works as I want, with a full history of files of all the changes appended to the AutoCorrect.ahk script, saved to the same folder. Many thanks. :-)

Regards,
Parminder
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

15 Nov 2023, 08:45

Awesome! As a side note: If you wanted to have your backup files in their own subfolder, you could probably have something like:

Code: Select all

FileCopy "AutoCorrect.ahk", A_ScriptDir "\MyBackupFolder\" backupFilename, 1
Or

Code: Select all

  backupFilename := A_ScriptDir "\MyBackupFolder\AutoCorrect_" A_YYYY "-" A_MM "-" A_DD "_" A_Hour "-" A_Min "-" A_Sec ".ahk" ; This will make it AutoCorrect_YYYY-MM-DD_HH24-MI-SS.ahk
  FileCopy "AutoCorrect.ahk", backupFilename, 1
name := "ste(phen|ve) kunkel"
dorito
Posts: 4
Joined: 14 Nov 2023, 05:10

Re: AutoCorrect for v2

15 Nov 2023, 09:15

Oops - I didn't realise there was a page 2 of this thread. I was wondering why I kept seeing your same post at the bottom of the page even though I had submitted an update.
I've ended up putting in the same response in twice (I do hope the admins are savvy to this and remove my second post - the one you've responded to.).

@kunkel321 That's a great idea. I think I will put the date-time backup files into a sub-folder. This will keep it all neat and tidy. Cheers. 👍
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

15 Feb 2024, 14:38

Here is the latest version of AutoCorrect for v2.
AutoCorrect2Share2-22-2024.zip
(1.93 MiB) Downloaded 409 times
2-22-2024 Update: I got the validation working more accurately. It's still not perfect, but is highly useful (in my opinion). I got tired of the tiny Windows Message Box, so I made a big colorful dialog for the validity messages. Following the lead of Descolada's _HS() function, I got rid of the last two paramters of f()'s function calls. Added a couple of more options on the AutoCorrectLog.ahk tool. I need to update the manual again...
screenshot
Spoiler
HotString Helper has had a major upgrade and there is a user manual pdf file in the zip. Thanks @andymbody for feedback on the manual and code. Thanks is due to many others as well... Too many to list, but several are mentioned in the manual.

As with previous versions, the included AutoCorrect for v2.exe is not a compiled version of the script. It is simply a duplicate of AutoHotkey.exe, that has been renamed to match the same-named .ahk file (which must be in the same folder). Update/replace it with newer versions of AutoHotkey.exe, as they are released by Lexikos.

The manual mostly covers Hotstring Helper 2.0 and the AutoCorrect script as a whole, but at the last minute I decided to #Include the latest version of my DateTool
viewtopic.php?f=82&t=123895
There is no manual for the DateTool (aka DatePiker-H) however. Just comment-out the single relevant line of code near the top, if you don't want to use it. EDIT: FYI, I call "my DateTool" but the important parts were all made by user Just Me...
The hotkey is Alt+Shift+D

There are a bunch of other scriptlets that are under the Hotstring Helper code. They are not needed for Hotstring Helper or AutoCorrect to run, so I block-commented them out. Delete as desired, or tinker with them if you want.

The AutoCorrect and the DateTool .ahk files each have a context-specific hotkey (Ctrl+s) that saves and reloads the file as you are working on it, so that your changes are immediately usable.
Last edited by kunkel321 on 01 Apr 2024, 09:02, edited 8 times in total.
name := "ste(phen|ve) kunkel"
Jasonosaj
Posts: 58
Joined: 02 Feb 2022, 15:02
Location: California

Re: AutoCorrect for v2

16 Feb 2024, 16:48

@kunkel321 I've been using a modified version of the _HS() function by @Descolada. My hotstrings are all in ::trigger::_HS("replacement",% backspaceCount) format. Do you have any recommendations for how to reconcile with the new format?
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

16 Feb 2024, 18:50

Jasonosaj wrote:
16 Feb 2024, 16:48
@kunkel321 I've been using a modified version of the _HS() function by @Descolada. My hotstrings are all in ::trigger::_HS("replacement",% backspaceCount) format. Do you have any recommendations for how to reconcile with the new format?
Hmm... I could probably make a version of HotString Helper 2.0 that saves hotstrings in the right format. My f() function wouldn't work, but you wouldn't need it anyway, since Descolada's _HS() function works much the same way. The _HS() function doesn't accommodate logging, but it does have some other features not available in f(), so probably a fair trade LOL..

No doubt you noticed that I already "borrow" Descolada's InputBuffer Class in the f(). :D

If we want an _HS() version of hh2, we'll need to see if @andymbody will make a related version of the big regex for us... fyi Andy, Descolada's thing is here: viewtopic.php?f=83&t=122865

For anyone curious about the regex... "Jim-156" is here: viewtopic.php?f=82&t=125100#p555937
name := "ste(phen|ve) kunkel"
User avatar
andymbody
Posts: 1034
Joined: 02 Jul 2017, 23:47

Re: AutoCorrect for v2

16 Feb 2024, 18:51

Jasonosaj wrote:
16 Feb 2024, 16:48
My hotstrings are all in ::trigger::_HS("replacement",% backspaceCount) format. Do you have any recommendations for how to reconcile with the new format?
kunkel321 wrote:
16 Feb 2024, 18:50
If we want an _HS() version of hh2, we'll need to see if andymbody will make a related version of the big regex for us...
Correct me if I am wrong @kunkel321, will this resolve this question? It should now allow any function name. Is this all that needs to be addressed in the needle? I have not tested it.
hsRegex := "(?Jim)^:(?<Opts>[^:]+)*:(?<Trig>[^:]+)::(?:\w+\((?<Repl>[^,)]*)[^)]*\)|(?<Repl>[^;\v]+))?(?<fCom>\h*;\h*(?:\bFIXES\h*\d+\h*WORDS?\b)?(?:\h;)?\h*(?<mCom>.*))?$"

@Jasonosaj can you replace this line with this needle to see if it works?
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

16 Feb 2024, 19:19

@andymbody Thanks for the super-fast response! :lol:

It seems like that might do the trick for Jasonosaj's purposes. I think the _HS() function has a couple of different parameter options that should be accommodated too though. I'll need to refresh myself with the code. Jason has a percent sign in there, but I don't remember that... Have to look.
name := "ste(phen|ve) kunkel"
User avatar
andymbody
Posts: 1034
Joined: 02 Jul 2017, 23:47

Re: AutoCorrect for v2

16 Feb 2024, 19:27

kunkel321 wrote:
16 Feb 2024, 19:19
It seems like that might do the trick for Jasonosaj's purposes. I think the _HS() function has a couple of different parameter options that should be accommodated too though. I'll need to refresh myself with the code. Jason has a percent sign in there, but I don't remember that... Have to look.
Jim-152.
I think it should support the percent. And I shortened it a tad. I'm not sure why we had all those extra characters in the first Repl, but I removed them. If 152 doesn't work, try the one above, which will be 158. If neither work, let me know and I will dig into Descolada's script.
(?Jim)^:(?<Opts>[^:]+)*:(?<Trig>[^:]+)::(?:\w+\((?<Repl>[^)]*)\)|(?<Repl>[^;\v]+))?(?<fCom>\h*;\h*(?:\bFIXES\h*\d+\h*WORDS?\b)?(?:\h;)?\h*(?<mCom>.*))?$
Jasonosaj
Posts: 58
Joined: 02 Feb 2022, 15:02
Location: California

Re: AutoCorrect for v2

16 Feb 2024, 22:02

kunkel321 wrote:
16 Feb 2024, 18:50
Jasonosaj wrote:
16 Feb 2024, 16:48
@kunkel321 I've been using a modified version of the _HS() function by @Descolada. My hotstrings are all in ::trigger::_HS("replacement",% backspaceCount) format. Do you have any recommendations for how to reconcile with the new format?
Hmm... I could probably make a version of HotString Helper 2.0 that saves hotstrings in the right format. My f() function wouldn't work, but you wouldn't need it anyway, since Descolada's _HS() function works much the same way. The _HS() function doesn't accommodate logging, but it does have some other features not available in f(), so probably a fair trade LOL..

No doubt you noticed that I already "borrow" Descolada's InputBuffer Class in the f(). :D

If we want an _HS() version of hh2, we'll need to see if @andymbody will make a related version of the big regex for us... fyi Andy, Descolada's thing is here: viewtopic.php?f=83&t=122865

For anyone curious about the regex... "Jim-156" is here: viewtopic.php?f=82&t=125100#p555937
I probably created more confusion that I was trying to avoid in providing an example... Actual replacement strings do not have a percent sign in the second param. To avoid further confusion, my amendments to _HS() are:

Code: Select all


_HS(replacement?, opts?) {
	static HSInputBuffer := InputBuffer(), DefaultOmit := false, DefaultSendMode := A_SendMode, DefaultKeyDelay := 0, DefaultTextMode := "", DefaultBS := 0xFFFFFFFF, DefaultCaseSense := false

	; Save global variables ASAP to avoid these being modified if _HS is interrupted
	local Omit, TextMode, PrevKeyDelay := A_KeyDelay, PrevKeyDurationPlay := A_KeyDurationPlay, PrevSendMode := A_SendMode, ThisHotkey := A_ThisHotkey, EndChar := A_EndChar, replacementCase := "Lower" 

	; Only options without replacement text changes the global/default options
	if IsSet(opts) && !IsSet(replacement) {
		; SendMode is reset if no SendMode is specifically provided
		DefaultSendMode := InStr(opts, "SE") ? "Event" : InStr(opts, "SI") ? "InputThenPlay" : InStr(opts, "SP") ? "Play" : "Input"
		if InStr(opts, "O")
			DefaultOmit := !InStr(opts, "O0")
		if RegExMatch(opts, "i)K *([-0-9]+)", &KeyDelay)
			DefaultKeyDelay := Integer(KeyDelay[1])
		if InStr(opts, "T")
			DefaultTextMode := InStr(opts, "T0") ? "" : "{Text}"
		else if InStr(opts, "R")
			DefaultTextMode := InStr(opts, "R0") ? "" : "{Raw}"
		if InStr(opts, "B") {
			DefaultBS := RegExMatch(opts, "i)B *([-0-9]+)", &BSCount) ? Integer(BSCount[1]) : 0xFFFFFFFF
		}
		
		return
	}

	if !IsSet(replacement)
		return

	if (IsSet(opts) && InStr(opts, "B")) {
		RegExMatch(opts, "i)B *([-0-9]+)", &BSCount)
		trigLen := BSCount[1]
	} Else {
		thisHotkeyTrigger := SubStr(thisHotkey, inStr(thisHotkey, ":",,,2)+1) ; use everything to right of 2nd colon. 
		TrigLen := StrLen(thisHotkeyTrigger) + StrLen(endchar) ; determine number of backspaces needed.
	}
		
	SendInput("{Shift down}{Left " TrigLen "}{Shift up}") ; get thisHotkey text
	SendInput("{Ctrl down}c{Ctrl up}") ; get thisHotkey text
	SendInput("{Right " TrigLen "}")
	ClipWait(2) ; <-- does this even to anything?
	
	If IsUpper(SubStr(A_Clipboard, 1, 1)) { ; assess leftmost char
		replacementCase := "Sentence"
	} 
	If IsUpper(SubStr(A_Clipboard, 2, 1)) { ; assess 2nd char
		replacementCase := "Upper"
	} 
	
	; Musn't use Critical here, otherwise InputBuffer callbacks won't work
	; Start capturing input for the rare case where keys are sent during options parsing
	HSInputBuffer.Start()
	
	TextMode := DefaultTextMode, BS := DefaultBS, Omit := DefaultOmit
	SendMode DefaultSendMode
	if InStr(DefaultSendMode, "Play")
		SetKeyDelay , DefaultKeyDelay, "Play"
	else
		SetKeyDelay DefaultKeyDelay

	; The only opts currently accepted is "B" or "B0" to enable/disable backspacing, since this can't 
	; be changed with local hotstring options
	if IsSet(opts) && InStr(opts, "B")
		BS := RegExMatch(opts, "i)B *([-0-9]+)", &BSCount) ? Integer(BSCount[1]) : 0xFFFFFFFF

	; Load local hotstring options, but don't check for backspacing
	if RegExMatch(ThisHotkey, "^:(.+):", &opts) { 
		opts := opts[1]
		SendMode(InStr(opts, "SE") ? "Event" : InStr(opts, "SI") ? "InputThenPlay" : InStr(opts, "SP") ? "Play" : DefaultSendMode)
		if RegExMatch(opts, "i)K *([-0-9]+)", &KeyDelay) {
			KeyDelay := Integer(KeyDelay[1])
			if InStr(A_SendMode, "Play")
				SetKeyDelay , KeyDelay, "Play"
			else
				SetKeyDelay KeyDelay
		}
		TextMode := InStr(opts, "T") ? (InStr(opts, "T0") ? "" : "{Text}") : InStr(opts, "R") ? (InStr(opts, "R0") ? "" : "{Raw}") : DefaultTextMode
		if InStr(opts, "O")
			Omit := !InStr(opts, "O0")
		if InStr(opts, "C")
			DefaultCaseSense := true
	}

	; If case sensitivity is enabled, compare the case of the input string with the hotstring
	if (DefaultCaseSense && ThisHotkey != A_ThisHotkey) {
		Send(A_ThisHotkey)
		HSInputBuffer.Stop()
		return
	}

	; If backspacing is enabled, get the activation string length using Unicode character length 
	; since graphemes need one backspace to be deleted but regular StrLen would report more than one
	if (BS) {
		MaxBS := StrLen(RegExReplace(RegExReplace(ThisHotkey, ":.*?:"), "s)((?>\P{M}(\p{M}|\x{200D}))+\P{M})|\X", "_")) + (Omit ? 0 : StrLen(EndChar))
		, BS := BS = 0xFFFFFFFF ? MaxBS : BS > 0 ? BS : MaxBS + BS
	}

	replacement := (replacementCase = "Upper") ? StrUpper(replacement) : (replacementCase = "Sentence") ? StrUpper(SubStr(replacement,1,1)) . SubStr(replacement,2) : replacement
		
	; Send backspacing + TextMode + replacement string + optionally EndChar. SendLevel isn't changed 
	; because AFAIK normal hotstrings don't add the replacements to the end of the hotstring recognizer
	Send((BS ? "{BS " BS "}" : "") TextMode replacement (Omit || TextMode ? "" : "{Raw}" EndChar))

	if (Omit && TextMode)
		Send("{Raw}" EndChar)

	; Release the buffer, but restore Send settings *after* it (since it also uses Send)
	HSInputBuffer.Stop()

	if InStr(A_SendMode, "Play")
		SetKeyDelay , PrevKeyDurationPlay, "Play"
	else
		SetKeyDelay PrevKeyDelay

	SendMode PrevSendMode
}


[Mod edit: Replaced c-tags (for inline code) with [code][/code] tags. ]
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

17 Feb 2024, 11:01

I have you point out that I'm pretty sick with the crud, so my apologies for being half-brain dead... :mrgreen:

Having said that,
Andy, or others, If you want to try out Jason's version of the _HS function,
Spoiler
Note the last example item

Code: Select all

; Backspacing can be limited to n backspaces with Bn
:*:because of it's::_HS("s", "B2")
In my f() function, the Hotstring Options are between the first colons, but Descolada's _HS() puts them as the second parameter of the function... And it's an optional function.

...will comment more in next reply later...
name := "ste(phen|ve) kunkel"
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

17 Feb 2024, 17:05

Okay... So one of the abilities of hh2, is that it can capture a hotstring, whether formatted as a normal string, or formatted in an f(). (Uses Andy's regex for this.)

Once captured (and changed as needed), hh2 can then save the trigger string and replacement string back to a hotstring. It can save it as a normally formatted hotstring, or as an f() formatted hotstring.

So the formatting of the hotstring (whether default AHK formatting, or f() formatting) can be done and undone via hh2.

I’m guessing that you (Jason) utilize the “Rarefication” functionality, because of the example you first posted. The thing is, there will be “data loss” when converting from default AHK, to _HS() format…
Checkout these examples:

Code: Select all

; Plain old hotstring
::because of it's::because of its

; Rarified versions 
:B0X:because of it's::SendInput "{BS 2}s", A_EndChar 
:B0*:because of it's::{BS 2}s

; Formatted for f() function
:B0X*:because of it's::f("because of its", A_ThisHotkey, A_EndChar) 

; Formatted for _HS() function
; Backspacing can be limited to n backspaces with Bn
:*:because of it's::_HS("s", "B2")

With both functions -- f() and _HS() – the first param is the replacement text string. The f() uses the entire string, then trims the redundant left characters at runtime. With the _HS function though, the characters need to be trimmed when then function call is coded. So the rest of the replacement string is lost. …As I type this though, it occurs to me that we could remake the original replacement string, by reading the second param…

Jason, have you already Rarefied your hotstrings? If not, you are welcome to combine this code:
viewtopic.php?f=83&t=122531#p544153
with your code here:
viewtopic.php?f=83&t=122865#p550265

Tangent warning: I learned the word “rarefy” as to mean like trimming something down, or making it simpler. The WordWeb definition is mostly consistent with that, but check out meaning #4….. “Make more complex.” That seems like the opposite to me. Oh well.
Adjective: rarefied
1. Having low density
2. Of high moral or intellectual value; elevated in nature or style
Verb: rarefy
1. Lessen the density or solidity of
2. Make more subtle or refined
3. (chemistry) weaken the consistency of (a chemical substance)
4. Make more complex, intricate, or rich
I asked ai for a better word, and it suggested “streamlined.” That seemed too long though. LOL
name := "ste(phen|ve) kunkel"
Jasonosaj
Posts: 58
Joined: 02 Feb 2022, 15:02
Location: California

Re: AutoCorrect for v2

17 Feb 2024, 17:30

1I created a function that nominally converts the _HS() calls to the f() call format (see end of this post). My next hurdle will be evaluating the extent to which the converted hot strings are duplicative, unnecessary, or in conflict with the rarefied strings in your (much better) script. How did you approach that process, @kunkel321 ?

Examples of the converted strings are:

Code: Select all


:X*:a flagella::_f("a flagellum", A_ThisHotKey, A_EndChar)
:X*:a forward by::_f("a foreword by", A_ThisHotKey, A_EndChar)
:X*:a freshmen::_f("a freshman", A_ThisHotKey, A_EndChar)
:X*:a fungi::_f("a fungus", A_ThisHotKey, A_EndChar)
:X*:a gunmen::_f("a gunman", A_ThisHotKey, A_EndChar)
:X*:a line up::_f("a line-up", A_ThisHotKey, A_EndChar)
:X*:a lock out::_f("a lockout", A_ThisHotKey, A_EndChar)
:X*:a lock up::_f("a lockup", A_ThisHotKey, A_EndChar)
:X*:a lose::_f("a loss", A_ThisHotKey, A_EndChar)
:X*:a match up::_f("a match-up", A_ThisHotKey, A_EndChar)
:X*:a media for::_f("a medium for", A_ThisHotKey, A_EndChar)
:X*:a nuclei::_f("a nucleus", A_ThisHotKey, A_EndChar)
:X*:a numbers of::_f("a numberof", A_ThisHotKey, A_EndChar)
:X*:a paparazzi::_f("a paparazzo", A_ThisHotKey, A_EndChar)
:X*:a parentheses::_f("a parenthesis", A_ThisHotKey, A_EndChar)
:X*:a phenomena::_f("a phenomenon", A_ThisHotKey, A_EndChar)
:X*:a protozoa::_f("a protozoon", A_ThisHotKey, A_EndChar)
:X*:a radii::_f("a radius", A_ThisHotKey, A_EndChar)
:X*:a run in::_f("a run-in", A_ThisHotKey, A_EndChar)
:X*:a set back::_f("a set-back", A_ThisHotKey, A_EndChar)
:X*:a set up::_f("a setup", A_ThisHotKey, A_EndChar)
:X*:a spermatozoa::_f("a spermatozoon", A_ThisHotKey, A_EndChar)
:X*:a statesmen::_f("a statesman", A_ThisHotKey, A_EndChar)
:X*:a strata::_f("a stratum", A_ThisHotKey, A_EndChar)
:X*:a taxa::_f("a taxon", A_ThisHotKey, A_EndChar)
:X*:a toss up::_f("a toss-up", A_ThisHotKey, A_EndChar)
:X*:a two months::_f("a two-month", A_ThisHotKey, A_EndChar)
:X*:a women::_f("a woman", A_ThisHotKey, A_EndChar)
:X*:a work out::_f("a workout", A_ThisHotKey, A_EndChar)
:X*:about it's::_f("about its", A_ThisHotKey, A_EndChar)
:X*:about they're::_f("about their", A_ThisHotKey, A_EndChar)

Code: Select all


outputFile := A_ScriptDir "\outputfile.txt"
If (!FileExist(outputFile))
    FileAppend, , %outputFile%

        ; Loop through each line in the file
        Loop, Read, %A_ScriptFullPath%
        {
            line := A_LoopReadLine
            
            ; Check if the line contains a function call to _HS()
            if (RegExMatch(line, ".*_HS\(""(.+)"", ""B(\d+)""\)", match))
            {
                ; Extract the parameters from the match
                replacement_original := match1
                integer := match2
                ; Calculate the substring of the trigger
                ;trigger := SubStr(line, InStr(line, ":", 2) + 1, InStr(line, ":", 3) - InStr(line, ":", 2) - 1)
                
                ; Construct the output string
                options_Start := 1
                options_End := InStr(Line,":",,1,2) - 1
                options := SubStr(line, 2, options_End - options_Start)
                replacement_options := ""
                If (InStr(options,"c"))
                    replacement_options .= "c"
                If (InStr(options,"*" ))
                    replacement_options .= "*"
                replacement_options := ":X" . replacement_options . ":"
            
                trigger_start := InStr(line,":",,1,2) +1
                trigger_end := InStr(line,":",,1,3)
                trigger := SubStr(line, trigger_start , trigger_end - trigger_start)
                replacement_new := substr(trigger,1,StrLen(trigger) - integer) . replacement_original

                output := replacement_options . trigger . "::_f(""" . replacement_new . """, A_ThisHotKey, A_EndChar)"
                
                ; Append the output string to the text file
                FileAppend, %output%`n, %outputFile%
            }
        }

Descolada
Posts: 1431
Joined: 23 Dec 2021, 02:30

Re: AutoCorrect for v2

18 Feb 2024, 11:33

@kunkel321, I've now modified _HS to be more in line with your f() in the sense that the entire trigger string won't be deleted, but only the matching starting part. Thus :*:a flagella::_HS("a flagellum") is now equivalent to :*:a flagella::_HS("um", "B1").

_HS still doesn't conform to AHKs rules for case-sense, so BTW won't be turned to BY THE WAY. Since we don't have access to the hotstring recognizer, we'd either have to read AHK process memory (unreliable) or copy the trigger word to clipboard as @Jasonosaj did (also unreliable). Perhaps there is some other more reliable way available?
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

18 Feb 2024, 13:12

Thanks All, For the feedback.

Replying to @Jasonosaj: You figured out how to "regenerate" the full replacement string, very nice!
Do note a couple of things:
-You'll want the B0 option in the individual hotstrings. Or just have a switch at the top #Hotstring B0 like Descolada does... Either will work..
- I might be missing it, but is your conversion code checking for question mark options : ? : ?
- Lastly, there is an erroneous underscore in _f() but that's all good.

Next comment is Ughhh.... :facepalm: I used the Validation function from HotString Helper 2.0 (hh2), to try to make a script for you to find duplicate or conflicting hotstrings, but in the process I think I found a bug in the hh2 Validation function... The code is below. I'm pretty sure I'm using regexMatch() incorrectly, and it is over-identifying conflicts. The item : ? : and a as a trigger, is matching foobare and biswap, though it shouldn't be.

EDIT: Buggy code block removed. See improved version below...

Also, just to clarity, I'll mention that what we're calling "Rarification" is different from the concept of "multi-match" word-beginning/-middle/-endings. With the "AutoCorrect for v2" library I posted, it is able to "potentially" match 300k+ possible typos because of all the multi-match items. The rarification process just reduces the number of Backspaces and replacement characters that have to be typed when a particular autocorrection is made.

Re @Descolada: Very cool. Thanks for the adjustment to your own script. It's worth noting the f() function also doesn't "officially" do case conformation. The rarification process does have the same affect some of the time... For example there is the item teh --> the. Typing teh or Teh will trigger the same autocorrect entry (because there is no :C: option). Because of the rarification process, the response of f() will be {BS 2}he. The first letter doesn't actually get removed. Unfortunately, if the entire string gets backspaced-away, then the capitalization will be lost.

Anyhow... For interested readers: `Descolada's _HS() function and the above f() one both do similar things, but each has unique abilities. f() does logging (see manual from above zip), but _HS will honor several (most?) of AutoHotkey's hotstring options. So if you want your function to do raw text playback, key delays, etc, use _HS(). I'd argue that both options have an advantage over standard default AHK-formatted hotstrings... And that advantage is that both functions utilize Descolada's InputBuffer Class. Here: viewtopic.php?f=83&t=122865
name := "ste(phen|ve) kunkel"
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

19 Feb 2024, 11:09

Okay, I think I have this thing functional... At some point I'll maybe post it in its own v2 script share thread. It is essentially a more-thorough, and v2, version of the "Dead Hotstring Locator" here:
viewtopic.php?f=6&t=115742

Important points:
-It is slooow... There's an outter loop that runs once per line of code, and an inner loop that runs once per line of code, for each of the outer loop's loops. Additionally, each hotstring gets compared against up to 4 possible logic statements. I have just over 5k autocorrect entries, so that's 5k x 5k = 25 million loops, and many of those get passed through multiple If checks. My script of 5k takes just under 5 minutes.
-There's a progress bar so you know it's actually running!
-You can make it a tiny bit faster by skipping any lines of code above where your list of autocorrect items start. For example, if you are using the above posted HotString Helper 2.0, you can skip nearly 1k lines of code... There's no point scanning all of those.
-It's likely that you also have a group of "nullifier" items at the top of your autocorrect library. I recommend setting your start point below those. Those (by definition) are meant to be matches to certain word-end items, so they will get flagged if you scan them.
-If you have a large section of non-autocorrect code at the bottom of your script, you can specify that line number too.
-If you simply copy-n-paste the below ahk code into your editor, I recommend saving the ahk file to a known location on your computer... The output reports will get saved in the same location.
-@Jasonosaj if you have 2 autocorrect libraries that you want to compare, paste them into the same ahk file, then scan that file.
-The report will give you the line numbers of where the items are, but my own experience is that it's easier to find the items it you paste each trigger string into the find dialog of your editor.
-Please note that the script can't identify "tripplets." If there are three identical triggers, they will appear, not as one tripplicate set, but as three duplicate sets.
-EDIT: It also occurs to me that the checks are not in the form of If... If... If.... Instead they are If... Else If... Else If. This should make the scan quicker, but it means that, if an item has multiple conflicts, you'll need to fix one conflict, then scan again so see the next, because the script can only identify one conflict at a time.

2-20-2024 EDIT: Code now addresses "duplicate but okay because word beginning/end" issue mention at bottom of this reply.

Code: Select all

#SingleInstance
#Requires AutoHotkey v2+
; A script to find duplicate and conflicting beg/mid/end hotstring triggers. By kunkel321 2-20-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 5 minutes for 5k lines of autocorrect items. 

; fullList := '
; (
; 	::foobar::
; 	:?:foobar::
; 	;::bizwap::
; 	;:?:bizwap::
; )'


; !!! IMPORTANT !!! Set first three variables.
; ACitemsStartAt := 0 ; <--- Skip this many lines at top of code.  Recommend not scanning 'nullifier' items at top of list. 
; ACitemsEndAt := 9999 ; <--- stop comparing after this line number. 

ACitemsStartAt := 1752 ; <--- Skip this many lines at top of code.  Recommend not scanning 'nullifier' items at top of list. 
ACitemsEndAt := 6763 ; <--- stop comparing after this line number. 
targetFile := "S:\AutoHotkey\MasterScript\MasterScript.ahk"  ; <--- Your AutoCorrect.ahk file path here.
fullList := Fileread(targetFile) 

^Esc::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) "..." ; 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 "`t" oLoop "`n"
					DupReport .= "-and: " iIdx "`t`t" i.Trig "`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 "`t" oLoop "`n"
					MidReport .= "-and: " iIdx "`t" strReplace(strReplace(i.Opts, "B0", ""),"X", "") "`t" i.Trig "`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 "`t" oLoop "`n"
					BegReport .= "-and: " iIdx "`t" strReplace(strReplace(i.Opts, "B0", ""),"X", "") "`t" i.Trig "`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 "`t" oLoop "`n"
					EndReport .= "-and: " iIdx "`t" strReplace(strReplace(i.Opts, "B0", ""),"X", "") "`t" i.Trig "`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 := ElapsedTime "`nLine`tOpt`tTrigger`tFull item`n=================================`n" DupReport BegReport MidReport EndReport 
Location := A_ScriptDir "\Report" A_Now ".txt"
FileAppend FullReport, Location ; Save to text file, then open the file. 
sleep 1000
Run Location
; msgbox FullReport

SoundBeep 1800, 700
SoundBeep 1200, 200
FYI scanning the AutoCorrect for v2 script that is attached in the zip above, yields the following 142 pairs of conflicting items. As discussed in the zipped manual, many of the word-ending items can both be used, as long as they are in the correct order (longer one first).

I want to update the Validity checker part of hotstring helper, then I'll clean up the autocorrect library more.

Code: Select all

Found 142 item pairs in 4-min 47-sec.
Line	Opt	Trigger	Full item
=================================
Duplicates:
---------------------------------------
Line: 5425		ineing	:B0X?*:ineing::f("ining", A_ThisHotkey, A_EndChar) ; Fixes 193 words
-and: 5426		ineing	:B0X?*:ineing::f("ining", A_ThisHotkey, A_EndChar) ; Fixes 193 words

Beginnings:
---------------------------------------
Line: 1775	*	a English	:B0X*:a English::f("an English", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 1800	*	a en	:B0X*:a en::f("an en", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 1777	*	a Internet	:B0X*:a Internet::f("an Internet", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 1823	*	a in	:B0X*:a in::f("an in", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 1924	*	aircrafts'	:B0X*:aircrafts'::f("aircraft's", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 1925	*	aircrafts	:B0X*:aircrafts::f("aircraft", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 1951	*	alot	:B0X*:alot::f("a lot", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 4635	?*	alott	:B0X?*:alott::f("allott", A_ThisHotkey, A_EndChar) ; Fixes 8 words

---------------------------------------
Line: 1987	*	an histor	:B0X*:an histor::f("a histor", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 1988	*	an historian	:B0X*:an historian::f("a historian", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2005	*	an seven	:B0X*:an seven::f("a seven", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2006	*	an seventh	:B0X*:an seventh::f("a seventh", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2018	*	andd	:B0X*:andd::f("and", A_ThisHotkey, A_EndChar) ; Fixes 73 words
-and: 6454	?	andd	:B0X?:andd::f("and", A_ThisHotkey, A_EndChar) ; Fixes 251 words

---------------------------------------
Line: 2107	*	atn	:B0X*:atn::f("ant", A_ThisHotkey, A_EndChar) ; Fixes 704 words
-and: 6463	?	atn	:B0X?:atn::f("ant", A_ThisHotkey, A_EndChar) ; Fixes 506 words

---------------------------------------
Line: 2129	*	aywa	:B0X*:aywa::f("away", A_ThisHotkey, A_EndChar) ; Fixes 4 words
-and: 6468	?	aywa	:B0X?:aywa::f("away", A_ThisHotkey, A_EndChar) ; Fixes 24 words

---------------------------------------
Line: 2259	*	bve	:B0X*:bve::f("be", A_ThisHotkey, A_EndChar) ; Fixes 1565 words
-and: 6480	?	bve	:B0X?:bve::f("be", A_ThisHotkey, A_EndChar) ; Fixes 127 words

---------------------------------------
Line: 2284	*	cant	:B0X*:cant::f("can't", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2285	*	cantalop	:B0X*:cantalop::f("cantaloup", A_ThisHotkey, A_EndChar) ; Fixes 4 words

---------------------------------------
Line: 2405	*	decomposit	:B0X*:decomposit::f("decompose", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2406	*	decomposited	:B0X*:decomposited::f("decomposed", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2405	*	decomposit	:B0X*:decomposit::f("decompose", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2407	*	decompositing	:B0X*:decompositing::f("decomposing", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2405	*	decomposit	:B0X*:decomposit::f("decompose", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2408	*	decomposits	:B0X*:decomposits::f("decomposes", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2420	*	deside	:B0X*:deside::f("decide", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5028	?*	desided	:B0X?*:desided::f("decided", A_ThisHotkey, A_EndChar) ; Fixes 7 words.

---------------------------------------
Line: 2464	*	discus a	:B0X*:discus a::f("discuss a", A_ThisHotkey A_EndChar) ; Fixes 1 word
-and: 2465	*	discus all	:B0X*:discus all::f("discuss all", A_ThisHotkey A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2464	*	discus a	:B0X*:discus a::f("discuss a", A_ThisHotkey A_EndChar) ; Fixes 1 word
-and: 2466	*	discus any	:B0X*:discus any::f("discuss any", A_ThisHotkey A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2473	*	dispell	:B0X*:dispell::f("dispel", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2474	*	dispells	:B0X*:dispells::f("dispels", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2580	*	expell	:B0X*:expell::f("expel", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2581	*	expells	:B0X*:expells::f("expels", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2666	*	frome	:B0X*:frome::f("from", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5308	?*	fromed	:B0X?*:fromed::f("formed", A_ThisHotkey, A_EndChar) ; Fixes 34 words

---------------------------------------
Line: 2718	*	guatamala	:B0X*:guatamala::f("Guatemala", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2719	*	guatamalan	:B0X*:guatamalan::f("Guatemalan", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2723	*	guilia	:B0X*:guilia::f("Giulia", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2724	*	guiliani	:B0X*:guiliani::f("Giuliani", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2760	*	had ran	:B0X*:had ran::f("had run", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2761	*	had rang	:B0X*:had rang::f("had rung", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2795	*	happend	:B0X*:happend::f("happened", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2796	*	happended	:B0X*:happended::f("happened", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 2886	*	hge	:B0X*:hge::f("he", A_ThisHotkey, A_EndChar) ; Fixes 1607 words
-and: 6557	?	hge	:B0X?:hge::f("he", A_ThisHotkey, A_EndChar) ; Fixes 147 words

---------------------------------------
Line: 2888	*	hier	:B0X*:hier::f("heir", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5373	?*	hierach	:B0X?*:hierach::f("hierarch", A_ThisHotkey, A_EndChar) ; Fixes 14 words

---------------------------------------
Line: 2888	*	hier	:B0X*:hier::f("heir", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5374	?*	hierarcic	:B0X?*:hierarcic::f("hierarchic", A_ThisHotkey, A_EndChar) ; Fixes 6 words

---------------------------------------
Line: 2919	*	hsa	:B0X*:hsa::f("has", A_ThisHotkey, A_EndChar) ; Fixes 64 words
-and: 6560	?	hsa	:B0X?:hsa::f("has", A_ThisHotkey, A_EndChar) ; Fixes 62 words

---------------------------------------
Line: 2920	*	hte	:B0X*:hte::f("the", A_ThisHotkey, A_EndChar) ; Fixes 402 words
-and: 6562	?	hte	:B0X?:hte::f("the", A_ThisHotkey, A_EndChar) ; Fixes 44 words

---------------------------------------
Line: 2922	*	humer	:B0X*:humer::f("humor", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5383	?*	humerous	:B0X?*:humerous::f("humorous", A_ThisHotkey, A_EndChar) ; Fixes 6 words

---------------------------------------
Line: 2952	*	ift he	:B0X*:ift he::f("if the", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 2953	*	ift hey	:B0X*:ift hey::f("if they", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3074	*	it's entire	:B0X*:it's entire::f("its entire", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 3075	*	it's entirety	:B0X*:it's entirety::f("its entirety", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3089	*	itr	:B0X*:itr::f("it", A_ThisHotkey, A_EndChar) ; Fixes 101 words, but misspells itraconazole (Antifungal drug). 
-and: 6582	?	itr	:B0X?:itr::f("it", A_ThisHotkey, A_EndChar) ; Fixes 366 words, but misspells Savitr (Important Hindu god) 

---------------------------------------
Line: 3125	*	layed off	:B0X*:layed off::f("laid off", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 3126	*	layed	:B0X*:layed::f("laid", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3162	*	lightyear	:B0X*:lightyear::f("light year", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 3163	*	lightyears	:B0X*:lightyears::f("light years", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3180	*	lsit	:B0X*:lsit::f("list", A_ThisHotkey, A_EndChar) ; Fixes 30 words
-and: 6598	?	lsit	:B0X?:lsit::f("list", A_ThisHotkey, A_EndChar) ; Fixes 244 words

---------------------------------------
Line: 3217	*	menat	:B0X*:menat::f("meant", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5592	?*	menatr	:B0X?*:menatr::f("mentar", A_ThisHotkey, A_EndChar) ; Fixes 71 words

---------------------------------------
Line: 3327	*	ocur	:B0X*:ocur::f("occur", A_ThisHotkey, A_EndChar) ; Fixes 8 words
-and: 5719	?*	ocurran	:B0X?*:ocurran::f("occurren", A_ThisHotkey, A_EndChar) ; Fixes 8 words

---------------------------------------
Line: 3374	*	over hear	:B0X*:over hear::f("overhear", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 3375	*	over heard	:B0X*:over heard::f("overheard", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3376	*	over look	:B0X*:over look::f("overlook", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 3377	*	over looked	:B0X*:over looked::f("overlooked", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3376	*	over look	:B0X*:over look::f("overlook", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 3378	*	over looking	:B0X*:over looking::f("overlooking", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3730	*	stpo	:B0X*:stpo::f("stop", A_ThisHotkey, A_EndChar) ; Fixes 33 words
-and: 6697	?	stpo	:B0X?:stpo::f("stop", A_ThisHotkey, A_EndChar) ; Fixes 8 words

---------------------------------------
Line: 3802	*	thanks@!	:B0X*:thanks@!::f("thanks!", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 3803	*	thanks@	:B0X*:thanks@::f("thanks!", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 3876	*	thn	:B0X*:thn::f("then", A_ThisHotkey, A_EndChar) ; Fixes 9 words ; Fixes 1 word
-and: 3877	*	thna	:B0X*:thna::f("than", A_ThisHotkey, A_EndChar) ; Fixes 35 words

---------------------------------------
Line: 3876	*	thn	:B0X*:thn::f("then", A_ThisHotkey, A_EndChar) ; Fixes 9 words ; Fixes 1 word
-and: 3878	*	thne	:B0X*:thne::f("then", A_ThisHotkey, A_EndChar) ; Fixes 9 words

---------------------------------------
Line: 3876	*	thn	:B0X*:thn::f("then", A_ThisHotkey, A_EndChar) ; Fixes 9 words ; Fixes 1 word
-and: 6260	?*	thnig	:B0X?*:thnig::f("thing", A_ThisHotkey, A_EndChar) ; Fixes 103 words

---------------------------------------
Line: 3876	*	thn	:B0X*:thn::f("then", A_ThisHotkey, A_EndChar) ; Fixes 9 words ; Fixes 1 word
-and: 6709	?	thn	:B0X?:thn::f("then", A_ThisHotkey, A_EndChar) ; Fixes 11 words

---------------------------------------
Line: 3876	*	thn	:B0X*:thn::f("then", A_ThisHotkey, A_EndChar) ; Fixes 9 words ; Fixes 1 word
-and: 6710	?	thne	:B0X?:thne::f("then", A_ThisHotkey, A_EndChar) ; Fixes 11 words

---------------------------------------
Line: 3878	*	thne	:B0X*:thne::f("then", A_ThisHotkey, A_EndChar) ; Fixes 9 words
-and: 6710	?	thne	:B0X?:thne::f("then", A_ThisHotkey, A_EndChar) ; Fixes 11 words

---------------------------------------
Line: 3896	*	tiem	:B0X*:tiem::f("time", A_ThisHotkey, A_EndChar) ; Fixes 49 words
-and: 6715	?	tiem	:B0X?:tiem::f("time", A_ThisHotkey, A_EndChar) ; Fixes 44 words

---------------------------------------
Line: 3899	*	timne	:B0X*:timne::f("time", A_ThisHotkey, A_EndChar) ; Fixes 49 words
-and: 6716	?	timne	:B0X?:timne::f("time", A_ThisHotkey, A_EndChar) ; Fixes 44 words

---------------------------------------
Line: 4012	*	tust	:B0X*:tust::f("trust", A_ThisHotkey, A_EndChar) ; Fixes 33 words
-and: 6726	?	tust	:B0X?:tust::f("trust", A_ThisHotkey, A_EndChar) ; Fixes 7 words

---------------------------------------
Line: 4019	*	tyo	:B0X*:tyo::f("to", A_ThisHotkey, A_EndChar) ; Fixes 1110 words
-and: 6728	?	tyo	:B0X?:tyo::f("to", A_ThisHotkey, A_EndChar) ; Fixes 185 words

---------------------------------------
Line: 4307	*C	ehr	:B0X*C:ehr::f("her", A_ThisHotkey, A_EndChar) ; Fixes 233 words, Made case sensitive so not to misspell Ehrenberg (a Russian novelist) or Ehrlich (a German scientist)
-and: 6527	?	ehre	:B0X?:ehre::f("here", A_ThisHotkey, A_EndChar) ; Fixes 49 words

---------------------------------------
Line: 4310	*C	hsi	:B0X*C:hsi::f("his", A_ThisHotkey, A_EndChar) ; Fixes 95 words, Case-sensitive to not misspell Hsian (a city in China)
-and: 6561	?	hsi	:B0X?:hsi::f("his", A_ThisHotkey, A_EndChar) ; Fixes 59 words

Middles:
---------------------------------------
Line: 2229	*	bigining	:B0X*:bigining::f("beginning", A_ThisHotkey, A_EndChar) ; Fixes 3 words
-and: 5401	?*	igini	:B0X?*:igini::f("igni", A_ThisHotkey, A_EndChar) ; Fixes 127 words

---------------------------------------
Line: 2550	*	evenhtual	:B0X*:evenhtual::f("eventual", A_ThisHotkey, A_EndChar) ; Fixes 4 words
-and: 5669	?*	nht	:B0X?*:nht::f("nth", A_ThisHotkey, A_EndChar) ; Jack's fixes 769 words

---------------------------------------
Line: 2640	*	flemmish	:B0X*:flemmish::f("Flemish", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5143	?*	emmis	:B0X?*:emmis::f("emis", A_ThisHotkey, A_EndChar) ; Fixes 214 words

---------------------------------------
Line: 2865	*	headquater	:B0X*:headquater::f("headquarter", A_ThisHotkey, A_EndChar) ; Fixes 4 words
-and: 4597	?*	adquate	:B0X?*:adquate::f("adequate", A_ThisHotkey, A_EndChar) ; Fixes 6 words

---------------------------------------
Line: 2887	*	hieght	:B0X*:hieght::f("height", A_ThisHotkey, A_EndChar) ; Fixes 6 words
-and: 5397	?*	iegh	:B0X?*:iegh::f("eigh", A_ThisHotkey, A_EndChar) ; Fixes 186 words

---------------------------------------
Line: 2958	*	illegitma	:B0X*:illegitma::f("illegitima", A_ThisHotkey, A_EndChar) ; Fixes 6 words
-and: 5520	?*	legitm	:B0X?*:legitm::f("legitim", A_ThisHotkey, A_EndChar) ; Fixes 67 words

---------------------------------------
Line: 3042	*	ireleven	:B0X*:ireleven::f("irrelevan", A_ThisHotkey, A_EndChar) ; Fixes 6 words
-and: 5996	?*	releven	:B0X?*:releven::f("relevan", A_ThisHotkey, A_EndChar) ; Fixes 12 words

---------------------------------------
Line: 3043	*	iresistabl	:B0X*:iresistabl::f("irresistibl", A_ThisHotkey, A_EndChar) ; Fixes 3 words
-and: 6012	?*	resistab	:B0X?*:resistab::f("resistib", A_ThisHotkey, A_EndChar) ; Fixes 10 words

---------------------------------------
Line: 3239	*	mischeivous	:B0X*:mischeivous::f("mischievous", A_ThisHotkey, A_EndChar) ; Fixes 3 words
-and: 5367	?*	heiv	:B0X?*:heiv::f("hiev", A_ThisHotkey, A_EndChar) ; Fixes 49 words

---------------------------------------
Line: 3243	*	misdemenor	:B0X*:misdemenor::f("misdemeanor", A_ThisHotkey, A_EndChar) ; Fixes 2 words
-and: 5013	?*	demeno	:B0X?*:demeno::f("demeano", A_ThisHotkey, A_EndChar) ; Fixes 8 words

---------------------------------------
Line: 3244	*	misfourtunes	:B0X*:misfourtunes::f("misfortunes", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5304	?*	fourtun	:B0X?*:fourtun::f("fortun", A_ThisHotkey, A_EndChar) ; Fixes 18 words

---------------------------------------
Line: 3339	*	ommision	:B0X*:ommision::f("omission", A_ThisHotkey, A_EndChar) ; Fixes 2 words
-and: 5607	?*	mision	:B0X?*:mision::f("mission", A_ThisHotkey, A_EndChar) ; Fixes 63 words

---------------------------------------
Line: 3410	*	peculure	:B0X*:peculure::f("peculiar", A_ThisHotkey, A_EndChar) ; Fixes 5 words
-and: 4986	?*	culure	:B0X?*:culure::f("culture", A_ThisHotkey, A_EndChar) ; Fixes 48 words

---------------------------------------
Line: 3539	*	recommed	:B0X*:recommed::f("recommend", A_ThisHotkey, A_EndChar) ; Fixes 12 words
-and: 4880	?*	commed	:B0X?*:commed::f("comed", A_ThisHotkey, A_EndChar) ; Fixes 18 words

---------------------------------------
Line: 3585	*	resturaunt	:B0X*:resturaunt::f("restaurant", A_ThisHotkey, A_EndChar) ; Fixes 6 words
-and: 6333	?*	uraunt	:B0X?*:uraunt::f("urant", A_ThisHotkey, A_EndChar) ; Fixes 34 words

---------------------------------------
Line: 3627	*	seceeded	:B0X*:seceeded::f("seceded", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5108	?*	eceed	:B0X?*:eceed::f("ecede", A_ThisHotkey, A_EndChar) ; Fixes 35 words

---------------------------------------
Line: 3836	*	theives	:B0X*:theives::f("thieves", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5367	?*	heiv	:B0X?*:heiv::f("hiev", A_ThisHotkey, A_EndChar) ; Fixes 49 words

---------------------------------------
Line: 3978	*	tomorow	:B0X*:tomorow::f("tomorrow", A_ThisHotkey, A_EndChar) ; Fixes 2 words
-and: 5624	?*	morow	:B0X?*:morow::f("morrow", A_ThisHotkey, A_EndChar) ; Fixes 4 words

---------------------------------------
Line: 4030	*	unconfortability	:B0X*:unconfortability::f("discomfort", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 4910	?*	confort	:B0X?*:confort::f("comfort", A_ThisHotkey, A_EndChar) ; Fixes 21 words

---------------------------------------
Line: 4051	*	unkow	:B0X*:unkow::f("unknow", A_ThisHotkey, A_EndChar) ; Fixes 14 words
-and: 5683	?*	nkow	:B0X?*:nkow::f("know", A_ThisHotkey, A_EndChar) ; Fixes 66 words, but misspells Minkowski (German mathematician)

---------------------------------------
Line: 4300	*?	femmin	:B0X*?:femmin::f("femin", A_ThisHotkey, A_EndChar) ; Fixes 80 words 
-and: 5251	?*	femmi	:B0X?*:femmi::f("femi", A_ThisHotkey, A_EndChar) ; Fixes 53 words

---------------------------------------
Line: 4300	*?	femmin	:B0X*?:femmin::f("femin", A_ThisHotkey, A_EndChar) ; Fixes 80 words 
-and: 5252	?*	femmin	:B0X?*:femmin::f("femin", A_ThisHotkey, A_EndChar) ; Fixes 80 words 

---------------------------------------
Line: 4697	?*	asr	:B0X?*:asr::f("ase", A_ThisHotkey, A_EndChar) ; Fixes 698 words, but misspells Basra (An oil city in Iraq) 
-and: 5105	?*	easr	:B0X?*:easr::f("ears", A_ThisHotkey, A_EndChar) ; Fixes 102 words

---------------------------------------
Line: 4701	?*	assoicat	:B0X?*:assoicat::f("associat", A_ThisHotkey, A_EndChar) ; Fixes 34 words
-and: 6122	?*	soica	:B0X?*:soica::f("socia", A_ThisHotkey, A_EndChar) ; Fixes 115 words

---------------------------------------
Line: 4756	?*	blihs	:B0X?*:blihs::f("blish", A_ThisHotkey, A_EndChar) ; Fixes 56 words
-and: 5405	?*	ihs	:B0X?*:ihs::f("his", A_ThisHotkey, A_EndChar) ; Fixes 618 words

---------------------------------------
Line: 4830	?*	charecter	:B0X?*:charecter::f("character", A_ThisHotkey, A_EndChar) ; Fixes 38 words
-and: 5985	?*	recter	:B0X?*:recter::f("rector", A_ThisHotkey, A_EndChar) ; Fixes 26 words

---------------------------------------
Line: 4844	?*	ciev	:B0X?*:ciev::f("ceiv", A_ThisHotkey, A_EndChar) ; Fixes 82 words
-and: 4904	?*	concieve	:B0X?*:concieve::f("conceive", A_ThisHotkey, A_EndChar) ; Fixes 13 words

---------------------------------------
Line: 4876	?*	comemmorat	:B0X?*:comemmorat::f("commemorat", A_ThisHotkey, A_EndChar) ; Fixes 12 words
-and: 5590	?*	memmor	:B0X?*:memmor::f("memor", A_ThisHotkey, A_EndChar) ; Fixes 70 words

---------------------------------------
Line: 4890	?*	comnt	:B0X?*:comnt::f("cont", A_ThisHotkey, A_EndChar) ; Fixes 587 words
-and: 6426	?*C	mnt	:B0X?*C:mnt::f("ment", A_ThisHotkey, A_EndChar) ; Fixes 1763 words.  Case-sensitive, to not misspell TMNT (Teenage Mutant Ninja Turtles)

---------------------------------------
Line: 4913	?*	consdider	:B0X?*:consdider::f("consider", A_ThisHotkey, A_EndChar) ; Fixes 31 words
-and: 6072	?*	sdide	:B0X?*:sdide::f("side", A_ThisHotkey, A_EndChar) ; Fixes 317 words

---------------------------------------
Line: 4971	?*	crti	:B0X?*:crti::f("criti", A_ThisHotkey, A_EndChar) ; Fixes 59 words
-and: 4972	?*	crticis	:B0X?*:crticis::f("criticis", A_ThisHotkey, A_EndChar) ; Fixes 13 words

---------------------------------------
Line: 4979	?*	cticious	:B0X?*:cticious::f("ctitious", A_ThisHotkey, A_EndChar) ; Fixes 14 words
-and: 6267	?*	ticio	:B0X?*:ticio::f("titio", A_ThisHotkey, A_EndChar) ; Fixes 68 words

---------------------------------------
Line: 5083	?*	docuemnt	:B0X?*:docuemnt::f("document", A_ThisHotkey, A_EndChar) ; Fixes 26 words
-and: 6426	?*C	mnt	:B0X?*C:mnt::f("ment", A_ThisHotkey, A_EndChar) ; Fixes 1763 words.  Case-sensitive, to not misspell TMNT (Teenage Mutant Ninja Turtles)

---------------------------------------
Line: 5084	?*	documetn	:B0X?*:documetn::f("document", A_ThisHotkey, A_EndChar) ; Fixes 26 words
-and: 5594	?*	metn	:B0X?*:metn::f("ment", A_ThisHotkey, A_EndChar) ; Fixes 1763 words

---------------------------------------
Line: 5104	?*	easen	:B0X?*:easen::f("easan", A_ThisHotkey, A_EndChar) ; Fixes 33 words
-and: 5853	?*	pleasent	:B0X?*:pleasent::f("pleasant", A_ThisHotkey, A_EndChar) ; Fixes 11 words

---------------------------------------
Line: 5108	?*	eceed	:B0X?*:eceed::f("ecede", A_ThisHotkey, A_EndChar) ; Fixes 35 words
-and: 6661	?	receeded	:B0X?:receeded::f("receded", A_ThisHotkey, A_EndChar) ; Fixes 2 words

---------------------------------------
Line: 5125	?*	eild	:B0X?*:eild::f("ield", A_ThisHotkey, A_EndChar) ; Fixes 147 words
-and: 6383	?*	weildl	:B0X?*:weildl::f("wield", A_ThisHotkey, A_EndChar) ; Fixes 15 words

---------------------------------------
Line: 5196	?*	essesital	:B0X?*:essesital::f("essential", A_ThisHotkey, A_EndChar) ; Fixes 18 words
-and: 6090	?*	sesi	:B0X?*:sesi::f("sessi", A_ThisHotkey, A_EndChar) ; Fixes 41 words

---------------------------------------
Line: 5251	?*	femmi	:B0X?*:femmi::f("femi", A_ThisHotkey, A_EndChar) ; Fixes 53 words
-and: 5252	?*	femmin	:B0X?*:femmin::f("femin", A_ThisHotkey, A_EndChar) ; Fixes 80 words 

---------------------------------------
Line: 5381	?*	http	:B0X?*:http:\\::f("http://", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 5382	?*	httpL	:B0X?*:httpL::f("http:", A_ThisHotkey, A_EndChar) ; Fixes 1 word

---------------------------------------
Line: 5442	?*	insitut	:B0X?*:insitut::f("institut", A_ThisHotkey, A_EndChar) ; Fixes 42 words
-and: 5695	?*	nsitu	:B0X?*:nsitu::f("nstitu", A_ThisHotkey, A_EndChar) ; Fixes 87 words

---------------------------------------
Line: 5481	?*	ivle	:B0X?*:ivle::f("ivel", A_ThisHotkey, A_EndChar) ; Fixes 589 words, but misspells braaivleis (Type of S. Affrican BBQ)
-and: 5910	?*	privledg	:B0X?*:privledg::f("privileg", A_ThisHotkey, A_EndChar) ; Fixes 7 words

---------------------------------------
Line: 5494	?*	juristiction	:B0X?*:juristiction::f("jurisdiction", A_ThisHotkey, A_EndChar) ; Fixes 4 words
-and: 6269	?*	tiction	:B0X?*:tiction::f("tinction", A_ThisHotkey, A_EndChar) ; Fixes 8 words

---------------------------------------
Line: 5594	?*	metn	:B0X?*:metn::f("ment", A_ThisHotkey, A_EndChar) ; Fixes 1763 words
-and: 6604	?	metns	:B0X?:metns::f("ments", A_ThisHotkey, A_EndChar) ; Fixes 577 words

---------------------------------------
Line: 5616	?*	mmorow	:B0X?*:mmorow::f("morrow", A_ThisHotkey, A_EndChar) ; Fixes 4 words
-and: 5624	?*	morow	:B0X?*:morow::f("morrow", A_ThisHotkey, A_EndChar) ; Fixes 4 words

---------------------------------------
Line: 5712	?*	obelm	:B0X?*:obelm::f("oblem", A_ThisHotkey, A_EndChar) ; Fixes 28 words
-and: 5913	?*	probelm	:B0X?*:probelm::f("problem", A_ThisHotkey, A_EndChar) ; Fixes 22 words

---------------------------------------
Line: 5808	?*	peice	:B0X?*:peice::f("piece", A_ThisHotkey, A_EndChar) ; Fixes 60 words
-and: 6140	?*	speices	:B0X?*:speices::f("species", A_ThisHotkey, A_EndChar) ; Fixes 8 words

---------------------------------------
Line: 5818	?*	penten	:B0X?*:penten::f("pentan", A_ThisHotkey, A_EndChar) ; Fixes 12 words
-and: 6005	?*	repentent	:B0X?*:repentent::f("repentant", A_ThisHotkey, A_EndChar) ; Fixes 5 words

---------------------------------------
Line: 6011	?*	residental	:B0X?*:residental::f("residential", A_ThisHotkey, A_EndChar) ; Fixes 7 words
-and: 6097	?*	sidenta	:B0X?*:sidenta::f("sidentia", A_ThisHotkey, A_EndChar) ; Fixes 9 words

---------------------------------------
Line: 6155	?*	ssurect	:B0X?*:ssurect::f("surrect", A_ThisHotkey, A_EndChar) ; Fixes 15 words
-and: 6200	?*	surect	:B0X?*:surect::f("surrect", A_ThisHotkey, A_EndChar) ; Fixes 15 words

---------------------------------------
Line: 6275	?*	tioj	:B0X?*:tioj::f("tion", A_ThisHotkey, A_EndChar) ; Fixes 7052 words
-and: 6276	?*	tiojn	:B0X?*:tiojn::f("tion", A_ThisHotkey, A_EndChar) ; Fixes 7052 words

Endings:
---------------------------------------
Line: 2865	*	headquater	:B0X*:headquater::f("headquarter", A_ThisHotkey, A_EndChar) ; Fixes 4 words
-and: 6655	?	quater	:B0X?:quater::f("quarter", A_ThisHotkey, A_EndChar) ; Fixes 4 words

---------------------------------------
Line: 2940	*	iconclas	:B0X*:iconclas::f("iconoclas", A_ThisHotkey, A_EndChar) ; Fixes 6 words
-and: 6486	?	clas	:B0X?:clas::f("class", A_ThisHotkey, A_EndChar) ; Fixes 8 words

---------------------------------------
Line: 3022	*	inteh	:B0X*:inteh::f("in the", A_ThisHotkey, A_EndChar) ; Fixes 1 word
-and: 6704	?	teh	:B0X?:teh::f("the", A_ThisHotkey, A_EndChar) ; Fixes 44 words

---------------------------------------
Line: 3198	*	managerial reign	:B0X*:managerial reign::f("managerial rein", A_ThisHotkey, A_EndChar) ; Fixes 2 word
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 3232	*	minsitr	:B0X*:minsitr::f("ministr", A_ThisHotkey, A_EndChar) ; Fixes 6 words
-and: 6582	?	itr	:B0X?:itr::f("it", A_ThisHotkey, A_EndChar) ; Fixes 366 words, but misspells Savitr (Important Hindu god) 

---------------------------------------
Line: 3475	*	presed	:B0X*:presed::f("presid", A_ThisHotkey, A_EndChar) ; Fixes 18 words
-and: 6665	?	resed	:B0X?:resed::f("ressed", A_ThisHotkey, A_EndChar) ; Fixes 50 words

---------------------------------------
Line: 3869	*	thge	:B0X*:thge::f("the", A_ThisHotkey, A_EndChar) ; Fixes 402 words
-and: 6557	?	hge	:B0X?:hge::f("he", A_ThisHotkey, A_EndChar) ; Fixes 147 words

---------------------------------------
Line: 3894	*	thsi	:B0X*:thsi::f("this", A_ThisHotkey, A_EndChar) ; Fixes 7 words
-and: 6561	?	hsi	:B0X?:hsi::f("his", A_ThisHotkey, A_EndChar) ; Fixes 59 words

---------------------------------------
Line: 4557	?*	abotu	:B0X?*:abotu::f("about", A_ThisHotkey, A_EndChar) ; Fixes 37 words
-and: 6641	?	otu	:B0X?:otu::f("out", A_ThisHotkey, A_EndChar) ; Fixes 97 words

---------------------------------------
Line: 4631	?*	allign	:B0X?*:allign::f("align", A_ThisHotkey, A_EndChar) ; Fixes 41 words
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 4685	?*	arign	:B0X?*:arign::f("aring", A_ThisHotkey, A_EndChar) ; Fixes 140 words
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 4693	?*	asign	:B0X?*:asign::f("assign", A_ThisHotkey, A_EndChar) ; Fixes 27
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 4732	?*	awya	:B0X?*:awya::f("away", A_ThisHotkey, A_EndChar) ; Fixes 46 words
-and: 6750	?	wya	:B0X?:wya::f("way", A_ThisHotkey, A_EndChar) ; Fixes 113 words

---------------------------------------
Line: 4734	?*	bakc	:B0X?*:bakc::f("back", A_ThisHotkey, A_EndChar) ; Fixes 410 words
-and: 6585	?	kc	:B0X?:kc::f("ck", A_ThisHotkey, A_EndChar) ; Fixes 610 words.  Misspells kc (thousand per second).

---------------------------------------
Line: 5009	?*	degred	:B0X?*:degred::f("degrad", A_ThisHotkey, A_EndChar) ; Fixes 31 words
-and: 6551	?	gred	:B0X?:gred::f("greed", A_ThisHotkey, A_EndChar) ; Fixes 6 words

---------------------------------------
Line: 5032	?*	desitn	:B0X?*:desitn::f("destin", A_ThisHotkey, A_EndChar) ; Fixes 30 words
-and: 6757	?C	itn	:B0X?C:itn::f("ith", A_ThisHotkey, A_EndChar) ; Fixes 70 words, Case sensitive, to not misspell ITN (Independent Television News) 

---------------------------------------
Line: 5037	?*	dessign	:B0X?*:dessign::f("design", A_ThisHotkey, A_EndChar) ; Fixes 51 words.
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 5066	?*	disign	:B0X?*:disign::f("design", A_ThisHotkey, A_EndChar) ; Fixes 51 words
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 5111	?*	ecomon	:B0X?*:ecomon::f("econom", A_ThisHotkey, A_EndChar) ; Fixes 50 words
-and: 6492	?	comon	:B0X?:comon::f("common", A_ThisHotkey, A_EndChar) ; Fixes 33 words

---------------------------------------
Line: 5192	?*	esorce	:B0X?*:esorce::f("esource", A_ThisHotkey, A_EndChar) ; Fixes 11 words
-and: 6690	?	sorce	:B0X?:sorce::f("source", A_ThisHotkey, A_EndChar) ; Fixes 5 words

---------------------------------------
Line: 5500	?*	konw	:B0X?*:konw::f("know", A_ThisHotkey, A_EndChar) ; Fixes 66 words
-and: 6637	?	onw	:B0X?:onw::f("one", A_ThisHotkey, A_EndChar) ; Fixes 341 words

---------------------------------------
Line: 5769	?*	orign	:B0X?*:orign::f("origin", A_ThisHotkey, A_EndChar) ; Fixes 37 words
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 6037	?*	rnign	:B0X?*:rnign::f("rning", A_ThisHotkey, A_EndChar) ; Fixes 77 words
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 6082	?*	sensur	:B0X?*:sensur::f("censur", A_ThisHotkey, A_EndChar) ; Fixes 12 words
-and: 6627	?	nsur	:B0X?:nsur::f("nsure", A_ThisHotkey, A_EndChar) ; Fixes 10 words

---------------------------------------
Line: 6133	?*	soverign	:B0X?*:soverign::f("sovereign", A_ThisHotkey, A_EndChar) ; Fixes 10 words
-and: 6573	?	ign	:B0X?:ign::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11384 words, but misspells a bunch (which are nullified above)

---------------------------------------
Line: 6231	?*	tatn	:B0X?*:tatn::f("tant", A_ThisHotkey, A_EndChar) ; Fixes 530 words
-and: 6463	?	atn	:B0X?:atn::f("ant", A_ThisHotkey, A_EndChar) ; Fixes 506 words

---------------------------------------
Line: 6254	?*	thakn	:B0X?*:thakn::f("thank", A_ThisHotkey, A_EndChar) ; Fixes 19 words 
-and: 6587	?	kn	:B0X?:kn::f("nk", A_ThisHotkey, A_EndChar) ; Fixes 168 words

---------------------------------------
Line: 6260	?*	thnig	:B0X?*:thnig::f("thing", A_ThisHotkey, A_EndChar) ; Fixes 103 words
-and: 6620	?	nig	:B0X?:nig::f("ing", A_ThisHotkey, A_EndChar) ; Fixes 11414 words.  Misspells pfennig (100 pfennigs formerly equaled 1 Deutsche Mark in Germany).

---------------------------------------
Line: 6261	?*	threatn	:B0X?*:threatn::f("threaten", A_ThisHotkey, A_EndChar) ; Fixes 10 words
-and: 6463	?	atn	:B0X?:atn::f("ant", A_ThisHotkey, A_EndChar) ; Fixes 506 words

---------------------------------------
Line: 6271	?*	tihkn	:B0X?*:tihkn::f("think", A_ThisHotkey, A_EndChar) ; Fixes 43 words
-and: 6587	?	kn	:B0X?:kn::f("nk", A_ThisHotkey, A_EndChar) ; Fixes 168 words

---------------------------------------
Line: 6366	?*	visiosn	:B0X?*:visiosn::f("vision", A_ThisHotkey, A_EndChar) ; Fixes 51 words
-and: 6577	?	iosn	:B0X?:iosn::f("ions", A_ThisHotkey, A_EndChar) ; Fixes 3055 words

---------------------------------------
Line: 6444	?	adresing	:B0X?:adresing::f("addressing", A_ThisHotkey, A_EndChar) ; Fixes 3 words
-and: 6666	?	resing	:B0X?:resing::f("ressing", A_ThisHotkey, A_EndChar) ; Fixes 40 words

---------------------------------------
Line: 6525	?	efull	:B0X?:efull::f("eful", A_ThisHotkey, A_EndChar) ; Fixes 74 words
-and: 6550	?	gratefull	:B0X?:gratefull::f("grateful", A_ThisHotkey, A_EndChar) ; Fixes 3 words

---------------------------------------
Line: 6535	?	ficaly	:B0X?:ficaly::f("fically", A_ThisHotkey, A_EndChar) ; Fixes 20 words
-and: 6568	?	icaly	:B0X?:icaly::f("ically", A_ThisHotkey, A_EndChar) ; Fixes 1432 words

---------------------------------------
Line: 6568	?	icaly	:B0X?:icaly::f("ically", A_ThisHotkey, A_EndChar) ; Fixes 1432 words
-and: 6686	?	sicaly	:B0X?:sicaly::f("sically", A_ThisHotkey, A_EndChar) ; Fixes 24 words

EDIT: A mildly interesting conundrum regarding "duplicate" items... Note the below items that are from the above report. They are not conflicting items, because each pair matches either the beginning -or- the end of a word... But not both. None of these can be made into "word middle" items because they'll result in mutliple misspellings. Here is a screencast demonstrating the effect.

https://app.screencast.com/l6Sf9Tw9eICZ3?tab=Details&conversation=VWUOFGYw43Hv5btiUlGmag

Code: Select all

Line: 2020	*	andd	:B0X*:andd::f("and") ; Fixes 73 words
-and: 6456	?	andd	:B0X?:andd::f("and") ; Fixes 251 words
---------------------------------------
Line: 2109	*	atn	:B0X*:atn::f("ant") ; Fixes 704 words
-and: 6465	?	atn	:B0X?:atn::f("ant") ; Fixes 506 words
---------------------------------------
Line: 2131	*	aywa	:B0X*:aywa::f("away") ; Fixes 4 words
-and: 6470	?	aywa	:B0X?:aywa::f("away") ; Fixes 24 words
---------------------------------------
Line: 2261	*	bve	:B0X*:bve::f("be") ; Fixes 1565 words
-and: 6482	?	bve	:B0X?:bve::f("be") ; Fixes 127 words
I'll work on making the above code (and the Hotstring Helper validity code) smart enough to not flag these.
2-20-2024 EDIT: Above code updated...
Last edited by kunkel321 on 20 Feb 2024, 11:07, edited 6 times in total.
name := "ste(phen|ve) kunkel"
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

19 Feb 2024, 12:26

Additional meanderings.... After studying @Descolada's _HS() function more, it occurs to me that _HS() captures the A_ThisHotkey and A_EndChar, even though they are not sent as function parameters. It seems obvious now, but all this time the f() function has been using those as the second and third params, even though it is not needed. I suppose I'll adjust f() accordingly. It does occur to me that sending them as parameters might get the content saved as variables a millisecond or so faster. It would make the function calls shorter though -- which would be nice.

Also, he smartly, analyzes the A_ThisHotkey for hotstring options such as Send Raw, or Key Delay, then sends the replacement string accordingly. I've never actually needed any other hotkey options other than * ? C B0 X, but I guess there's no harm supporting them.
name := "ste(phen|ve) kunkel"
Jasonosaj
Posts: 58
Joined: 02 Feb 2022, 15:02
Location: California

Re: AutoCorrect for v2

19 Feb 2024, 19:45

kunkel321 wrote:
19 Feb 2024, 12:26
Additional meanderings.... After studying @Descolada's _HS() function more, it occurs to me that _HS() captures the A_ThisHotkey and A_EndChar, even though they are not sent as function parameters. It seems obvious now, but all this time the f() function has been using those as the second and third params, even though it is not needed. I suppose I'll adjust f() accordingly. It does occur to me that sending them as parameters might get the content saved as variables a millisecond or so faster. It would make the function calls shorter though -- which would be nice.

Also, he smartly, analyzes the A_ThisHotkey for hotstring options such as Send Raw, or Key Delay, then sends the replacement string accordingly. I've never actually needed any other hotkey options other than * ? C B0 X, but I guess there's no harm supporting them.
I wondered about this when I was working through getting output strings to mirror the case of the trigger for case-insensitive hotstrings (I ended up cribbing from your method, @kunkel321). In terms of @Descolada's query concerning the problems with using the clipboard - preach. I spent a good deal of time searching the forums and documentation, prompting various coding models, and generally dicking around to try to understand what happens under AHK's hood between the time a hotstring is triggered and the resulting replacement string is sent, but came up with zilch. Other than prompting @Lexicos to see if there's a way to access the case of the hotstring trigger (ASCII code, I would imagine) I'm at a loss.
Descolada
Posts: 1431
Joined: 23 Dec 2021, 02:30

Re: AutoCorrect for v2

20 Feb 2024, 00:01

@Jasonosaj AFAIK there currently is no way to get the case of the hotstring trigger, which is why I created a pull request that implements a way to access the hotstring recognizer, which could then be used to extract the trigger along with its case.
User avatar
kunkel321
Posts: 1293
Joined: 30 Nov 2015, 21:19

Re: AutoCorrect for v2

20 Feb 2024, 08:19

Descolada wrote:
20 Feb 2024, 00:01
@Jasonosaj AFAIK there currently is no way to get the case of the hotstring trigger, which is why I created a pull request that implements a way to access the hotstring recognizer, which could then be used to extract the trigger along with its case.
Here's a super-kludgy work around. I doubt if it would be reliable enough to use though...
EDIT: Bah!!! That's no good. If you use ! or ? for endchars, you get ALL CAPS.

Code: Select all

#SingleInstance
#Requires AutoHotkey v2+

_f(replacement)
{	If GetKeyState('Shift')
		send strUpper(replacement)
	else
		send replacement
	send A_EndChar
}

:X:tgif::_f("thank goodness it's Friday")

/*
thank goodness it's Friday THANK GOODNESS IT'S FRIDAY 
Also, @Descolada , thanks for posting the pull request. Would it be helpful if Jason and I add comments to it, stating our support? Or is that just annoying to Lexikos?
name := "ste(phen|ve) kunkel"

Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: No registered users and 38 guests