 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
maniac
Joined: 28 Aug 2009 Posts: 267
|
Posted: Mon Jan 11, 2010 3:11 pm Post subject: |
|
|
| hugov wrote: | | maniac wrote: | | The clipboard thing did not work right. It only seemed to sometimes paste in the value, other times it just left the text blank. I have left the clipboard code commented in case anyone wants to try playing with it. I changed it from ^v to {Ctrl Down}v{Ctrl Up} as I couldn't get ^v to work at all. | Try adding clipwait, 0 above the paste command. my guess is that it takes a short while before the clipboard gets the content so it pastes to fast.
Re speed: I think you will really start to notice the difference for very long lists e.g. 25000 lines but there is probably no difference when you have 100 words/lines in wordslist.txt |
OK, I found the issue, or part of it... apparently BlockInput keeps SendInput from working. Commenting out BlockInput let SendInput work, but it seems the old clipboard data is getting back into the Clipboard before SendInput has actually put the text to the document. If I comment out the code that restores the old clipboard data it types the values correctly. Any ideas?
Right, the list I was checking has over 100,000 lines, but it still didn't seem like much of a performance increase (I think there was a small one). I expected there to be more of a boost, the efficiency issues must be somewhere else.
Thanks!
Edit:
Changing SendInput to Send or SendPlay seems to work... should I just use one of those? |
|
| Back to top |
|
 |
SoLong&Thx4AllTheFish
Joined: 27 May 2007 Posts: 4999
|
Posted: Mon Jan 11, 2010 3:16 pm Post subject: |
|
|
Fiddle with clipwait or if that fails sleep 100, 250 etc | Code: | ; below doesn't seem to work right, it randomly sends blank values to SendInput
; ClipboardSave:=ClipboardAll
; Clipboard =
; Clipwait, 0
; Clipboard = %sending%
; SendInput, {BS %len%}{Ctrl Down}v{Ctrl Up} ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
; Clipboard =
; Clipwait, 0
; Clipboard = %ClipboardSave%
; Clipwait, 0 |
Re speed: it should help with start up/exit script not while running. _________________ AHK Wiki FAQ
TF : Text files & strings lib, TF Forum |
|
| Back to top |
|
 |
maniac
Joined: 28 Aug 2009 Posts: 267
|
Posted: Mon Jan 11, 2010 3:33 pm Post subject: |
|
|
Sleeping doesn't appeal to me as the number needed will vary per PC it's running on (and I don't want to make it sleep too long). I messed some with clipwait but I couldn't get it to fix it. The issue seems to be SendInput just simply isn't being sent early enough so the Clipboard is clearing first - it does have data in it. I don't see how ClipWait could address that.
I think I'm just going to forego the clipboard entirely as I realized that will mess with programs which track Clipboard History... I know several people who use those.
It seems SendPlay fixes the issues I've been having with keystrokes being interspersed (see http://www.autohotkey.com/forum/viewtopic.php?t=49398), so I think I'm going to change from SendInput to SendPlay for the time being (unless there is some reason I'm missing besides the performance that I shouldn't do that).
Yeah, I realize it will help with startup/exit, but it still takes minutes to start/exit. Some of the processing it has to do is expensive (ie converting strings to ascii, sort, strip sort characters). It's mainly exiting that kills it, it takes about 8x as long as starting the script (see last post pg 1 for the wordlist I'm testing).
Thanks!
new version (using SendPlay):
| Code: | ; Intellitype: typing aid
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
; - Jordi S
; Heavily modified by:
; Maniac
;___________________________________________
; CONFIGURATIONS
; Editor Window Recognition
; (make it blank to make the script seek all windows)
OnExit, SaveScript
ETitle =
;Minimum word length to make a guess
WLen = 3
keyagain=
key=
clearword=1
;Gosub,clearallvars ; clean vars from start
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
;_______________________________________
CoordMode, ToolTip, Relative
AutoTrim, Off
WordListDone = 0
;reads list of words from file
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
AddWordToList(A_LoopField)
}
ParseWords =
SetTimer, Winchanged, 100
GoSub, ReverseWordNums
WordlistDone = 1
Loop
{
;Editor window check
WinGetActiveTitle, ATitle
WinGet, A_id, ID, %ATitle%
IfNotInString, ATitle, %ETitle%
{
ToolTip
Setenv, Word,
WinWaitActive, %ETitle%
Continue
}
;Get one key at a time
Input, chr, L1 V,{enter}{space}.;`,:¿?¡!'"()]{}{}}{bs}{{}{esc}{tab}{Home}{End}{PgUp}{PdDn}{Up}{Dn}{Left}{Right}
EndKey = %errorlevel%
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
ifequal, OldCaretY,
OldCaretY = %A_CaretY%
ifnotequal, OldCaretY, %A_CaretY%
{
; add the word if switching lines
AddWordToList(Word)
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
OldCaretY=%A_CaretY%
;Backspace clears last letter
ifequal, EndKey, Endkey:BackSpace
{
StringLen, len, Word
IfNotEqual, len, 0
{
ifequal, len, 1
{
Gosub,clearallvars
} else {
StringTrimRight, Word, Word, 1
}
}
} else ifequal, EndKey, Max
{
Setenv, Word, %word%%chr%
} else {
;addword = %Word%
;Gosub, addwordtolist
AddWordToList(Word)
Gosub, clearallvars
}
;Wait till minimum letters
IF ( StrLen(Word) < wlen )
{
ToolTip,
Continue
}
;Match part-word with command
Num =
Match =
singlematch = 0
number = 0
StringLeft, baseword, Word, %wlen%
baseword := ConvertWordToAscii(baseword,1)
Loop
{
IfEqual, zword%baseword%%a_index%,, Break
IfEqual, number, 10
Break
if ( SubStr(zword%baseword%%a_index%, 1, StrLen(Word)) = Word )
{
number ++
singlematch := zword%baseword%%a_index%
match := match . Mod(number,10) . ". " . singlematch . "`n"
singlematch%number% = %singlematch%
Continue
}
}
;If no match then clear Tip
IfEqual, Match,
{
clearword=0
Gosub,clearallvars
Continue
}
;Show matched command
StringTrimRight, match, match, 1 ; Get rid of the last linefeed
WinGetActiveTitle, ATitle
WinGetPos, , PosY, , SizeY, %ATitle%
ToolTipSizeY := (number * 12)
ToolTipPosY := A_CaretY+14
if ((ToolTipSizeY + ToolTipPosY) > (PosY + SizeY))
ToolTipPosY := (A_CaretY - 14 - ToolTipSizeY)
IfNotEqual, Word,,ToolTip, %match%, %A_CaretX%, %ToolTipPosY%
; +14 Move tooltip down a little so as not to hide the caret.
}
; Timed function to detect change of focus (and remove tooltip when changing active window)
Winchanged:
WinGetActiveTitle, ATitle
WinGet, A_id3, ID, %ATitle%
IfNotEqual, A_id, %A_id3%
{
ToolTip ,
} else {
; If we are in the correct window, and OldCaretY is set, clear the tooltip if not in the same line
IfInString, ATitle, %ETitle%
{
IfNotEqual, OldCaretY,
{
IfNotEqual, OldCaretY, %A_CaretY%
{
ToolTip,
}
}
}
}
Return
; Key definitions for autocomplete (0 to 9)
#MaxThreadsPerHotkey 1
$1::
$2::
$3::
$4::
$5::
$6::
$7::
$8::
$9::
$0::
CheckWord(A_ThisHotkey)
Return
; If hotkey was pressed, check wether there's a match going on and send it, otherwise send the number(s) typed
CheckWord(Key)
{
global
Local ATitle
Local A_id2
Local WordIndex
StringRight, Key, Key, 1
IfEqual, Key, 0
{
WordIndex = 10
} else {
WordIndex = %Key%
}
clearword=1
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
SendPlay,%key%
Gosub,clearallvars
Return
}
IfNotEqual, OldCaretY, %A_CaretY% ;Make sure we are still on the same line
{
SendPlay,%key%
Gosub,clearallvars
Return
}
ifequal, Word, ; only continue if word is not empty
{
SendPlay,%key%
Setenv, Word, %key%
clearword=0
Gosub,clearallvars
Return
}
ifequal, singlematch%WordIndex%, ; only continue singlematch is not empty
{
SendPlay,%key%
Setenv, Word, %word%%key%
clearword=0
Gosub,clearallvars
Return
}
Local sending
Local len
Local ClipboardSave
; SEND THE WORD!
if key =0
key = 10
sending := singlematch%WordIndex%
StringLen, len, Word
; Update Typed Count
UpdateWordCount(sending)
SendPlay, {BS %len%}{Raw}%sending% ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
; below works but uses clipboard
;ClipboardSave:=ClipboardAll
;Clipboard = %sending%
;SendPlay, {BS %len%}^v ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
;Clipboard = %ClipboardSave%
Gosub,clearallvars
Return
}
; This is to blank all vars related to matches, tooltip and (optionally) word
clearallvars:
Ifequal,clearword,1
{
Setenv,word,
OldCaretY=
}
ToolTip
; Clear all singlematches
Loop, 10
{
singlematch%a_index% =
}
sending =
key=
match=
clearword=1
Return
AddWordToList(AddWord)
{
global
Local CharTerminateList
Local Base
Local AddWordInList
Local CountWord
Local pos
Ifequal, Addword, ;If we have no word to add, skip out.
Return
if ( Substr(addword,1,1) = ";" ) ;If first char is ";", clear word and skip out.
{
IfEqual, wordlistdone, 0 ;If we are still reading the wordlist file and we come across ;LEARNEDWORDS; set the LearnedWordsCount flag
{
IfEqual, AddWord, `;LEARNEDWORDS`;
LearnedWordsCount=0
}
addword =
Return
}
ifequal, wordlistdone, 1 ;if we are not reading the wordlist file, use the following characters in the terminate list
CharTerminateList = 1,2,3,4,5,6,7,8,9,0
else CharTerminateList =
if addword contains %CharTerminateList% ;if one of the chars in the word is in the terminate list, don't add it
{
addword =
CharTerminateList =
Return
}
CharTerminateList =
IF ( StrLen(addword) <= wlen ) ; don't add the word if it's not longer than the minimum length
{
addword =
Return
}
Base := ConvertWordToAscii(SubStr(addword,1,wlen),1)
AddWordInList =
Loop ;Check to see if the word is already in the list, case sensitive
{
IfEqual, zword%base%%a_index%,, Break
if ( zword%base%%a_index% == AddWord )
{
AddWordInList = 1
Break
}
Continue
}
ifequal, AddWordInList, ; if the word is not in the list
{
IfEqual, WordListDone, 0 ;if this is read from the wordlist
{
IfNotEqual,LearnedWordsCount, ;if this is a stored learned word
{
CountWord := ConvertWordToAscii(addword,0)
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
zCount%CountWord% := LearnedWordsCount++ ;increment the count and store the Weight of the LearnedWord in reverse order (will be inverted later)
}
} else { ; If this is an on-the-fly learned word
CountWord := ConvertWordToAscii(addWord,0)
zCount%CountWord% = 1 ;set the count to one as it's the first time we typed it
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
}
; Increment the counter for each hash
zbasenum%Base%++
pos := zbasenum%Base%
; Set the hashed value to the word
zword%Base%%pos% = %addword%
pos =
} Else {
IfEqual, WordListDone, 1 ;if we've already typed the word and we've loaded the wordlist increment the count
{
UpdateWordCount(addword)
}
}
Return
}
; This sub will reverse the read numbers since now we know the total number of words
ReverseWordNums:
LearnedWordsCount+=4
Loop,parse,LearnedWords, `,
{
AsciiWord := ConvertWordToAscii(A_LoopField,0)
zCount%AsciiWord% := LearnedWordsCount - zCount%AsciiWord%
}
AsciiWord =
LearnedWordsCount =
Return
UpdateWordCount(word)
{
; If the Count for the word already exists - ie if it's a learned word, increment it, else don't.
local CountWord := ConvertWordToAscii(word,0)
IfNotEqual, zCount%CountWord%,
{
zCount%CountWord%++
local WordBase
StringLeft, WordBase, word, %wlen% ;find the pseudohash for the word
WordBase := ConvertWordToAscii(WordBase,1)
Local ConvertWord =
Local LowIndex =
Local WordList =
Loop
{
ifequal, zword%WordBase%%A_Index%, ;Break the loop if no more words to read for the hash
Break
CountWord := zword%WordBase%%A_Index% ;Set CountWord to the current Word position
ConvertWord := ConvertWordToAscii(CountWord,0) ; Find the Ascii equivalent of the word
IfNotEqual, zCount%ConvertWord%, ;If there's no count for this word do nothing
{
IfEqual, LowIndex,
LowIndex = %A_Index% ;If this is the first word we've found with a count set this as our starting position
IfEqual, WordList, ;if we have no words in our wordlist, start it - prefix all words with (Count"z")
{
WordList := zCount%ConvertWord% . "z" . CountWord
} Else { ;else append to the wordlist
WordList := WordList . "," . zCount%ConvertWord% . "z" . CountWord
}
}
}
ifnotequal, Wordlist, ;If we have no words to process, don't
{
Sort, WordList, N R D, ;Sort the wordlist by order of
LowIndex-- ;A_Index starts at 1 so this value needs to be decremented
Local IndexPos =
Loop, Parse, WordList, `,
{
IndexPos := LowIndex + A_Index ;Set the current word we are processing to the starting pos plus word position
StringTrimLeft, CountWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
zword%WordBase%%IndexPos% = %CountWord% ; update the word in the list
}
}
}
Return
}
ConvertWordToAscii(Base,Caps)
{
; Return the word in Ascii numbers padded to length 3 per character
; Capitalize the string if NoCaps is not set
IfEqual, Caps, 1
StringUpper, Base, Base
Loop, % StrLen(Base)
{
New := New . PadZeros(Asc(Base),3)
StringTrimLeft, Base, Base, 1
}
Return New
}
PadZeros(Word,Length)
{
; Pad a string out to Length numbers of 0's
StringLen, WordLen, Word
IfLess, WordLen, Length
{
Loop, % (Length - WordLen)
{
Word := "0" . Word
}
}
Return Word
}
SaveScript:
; Add all the standard words to the tempwordlist
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
IfEqual, A_LoopField, `;LEARNEDWORDS`;
SkipRest = 1
IfEqual, SkipRest,
TempWordList .= A_LoopField "`n"
}
ParseWords =
; Parse the learned words and store them in a new list by count if their total count is greater than 5.
; Prefix the word with the count and "z" for sorting
Loop, Parse, LearnedWords, `,
{
SortWord := ConvertWordToAscii(A_LoopField,0)
IfGreaterOrEqual, zCount%SortWord%, 5
{
IfEqual, SortWordList,
{
SortWordList := zCount%SortWord% . "z" . A_LoopField
} else {
SortWordList := SortWordList . "," . zCount%SortWord% . "z" . A_LoopField
}
}
}
Sort, SortWordList, N R D, ; Sort numerically, comma delimiter
IfNotEqual, SortWordList, ; If SortWordList exists write to the file, otherwise don't.
{
TempWordList .= "`;LEARNEDWORDS`;`n"
FirstTimeLoop = 1
Loop, Parse, SortWordList, `,
{
StringTrimLeft, AppendWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
IfEqual, FirstTimeLoop, ;If we are not in our first time through the loop append a new line before the word
{
AppendWord = `n%AppendWord%
} else {
FirstTimeLoop =
}
TempWordList .= AppendWord
}
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
FileAppend, %TempWordList%, %A_ScriptDir%\Temp_Wordlist.txt ;Only update the file if we have learned words
FileCopy, %A_ScriptDir%\Temp_Wordlist.txt, %A_ScriptDir%\Wordlist.txt, 1
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
}
ExitApp
|
|
|
| Back to top |
|
 |
SoLong&Thx4AllTheFish
Joined: 27 May 2007 Posts: 4999
|
Posted: Mon Jan 11, 2010 4:09 pm Post subject: |
|
|
There might be some ways to strip a few functions here and there, for example you don't need PadZeros as far as I can see and you could replace that with a SubStr in ConvertWordToAscii would save a function call but...
Other then changing the way you store/retrieve the words list data I don't see a way to speed it up as it has to loop each entry. But that would need an import/export routine and a predefined format for the wordlist making it harder to maintain (e.g. not simply editing wordlist.txt in your editor)
For example if I read your large wordlist 1.3 mb first page and use stringsplit to create an array it is done within a second, hows that for speed
So rethinking the format of the list is worth the effort. _________________ AHK Wiki FAQ
TF : Text files & strings lib, TF Forum |
|
| Back to top |
|
 |
maniac
Joined: 28 Aug 2009 Posts: 267
|
Posted: Mon Jan 11, 2010 4:57 pm Post subject: |
|
|
PadZeros is necessary so each character is padded out to 3 characters long when converted to ascii codes... otherwise some will only take 2 characters. 3 chars makes it easy when forming the variable name. I couldn't figure out how to do this with built in functions.
I'll have to reconsider how I store the list, but I'd have to maintain some other structure to keep track of where values are stored which may slow the script down when it's running.
Was having some issues when I put SendPlay everywhere, so I put SendInput back in some places.
| Code: |
; Intellitype: typing aid
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
; - Jordi S
; Heavily modified by:
; Maniac
;___________________________________________
; CONFIGURATIONS
; Editor Window Recognition
; (make it blank to make the script seek all windows)
OnExit, SaveScript
ETitle =
;Minimum word length to make a guess
WLen = 3
keyagain=
key=
clearword=1
;Gosub,clearallvars ; clean vars from start
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
;_______________________________________
CoordMode, ToolTip, Relative
AutoTrim, Off
WordListDone = 0
;reads list of words from file
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
AddWordToList(A_LoopField)
}
ParseWords =
SetTimer, Winchanged, 100
GoSub, ReverseWordNums
WordlistDone = 1
Loop
{
;Editor window check
WinGetActiveTitle, ATitle
WinGet, A_id, ID, %ATitle%
IfNotInString, ATitle, %ETitle%
{
ToolTip
Setenv, Word,
WinWaitActive, %ETitle%
Continue
}
;Get one key at a time
Input, chr, L1 V,{enter}{space}.;`,:¿?¡!'"()]{}{}}{bs}{{}{esc}{tab}{Home}{End}{PgUp}{PdDn}{Up}{Dn}{Left}{Right}
EndKey = %errorlevel%
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
ifequal, OldCaretY,
OldCaretY = %A_CaretY%
ifnotequal, OldCaretY, %A_CaretY%
{
; add the word if switching lines
AddWordToList(Word)
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
OldCaretY=%A_CaretY%
;Backspace clears last letter
ifequal, EndKey, Endkey:BackSpace
{
StringLen, len, Word
IfNotEqual, len, 0
{
ifequal, len, 1
{
Gosub,clearallvars
} else {
StringTrimRight, Word, Word, 1
}
}
} else ifequal, EndKey, Max
{
Setenv, Word, %word%%chr%
} else {
;addword = %Word%
;Gosub, addwordtolist
AddWordToList(Word)
Gosub, clearallvars
}
;Wait till minimum letters
IF ( StrLen(Word) < wlen )
{
ToolTip,
Continue
}
;Match part-word with command
Num =
Match =
singlematch = 0
number = 0
StringLeft, baseword, Word, %wlen%
baseword := ConvertWordToAscii(baseword,1)
Loop
{
IfEqual, zword%baseword%%a_index%,, Break
IfEqual, number, 10
Break
if ( SubStr(zword%baseword%%a_index%, 1, StrLen(Word)) = Word )
{
number ++
singlematch := zword%baseword%%a_index%
match := match . Mod(number,10) . ". " . singlematch . "`n"
singlematch%number% = %singlematch%
Continue
}
}
;If no match then clear Tip
IfEqual, Match,
{
clearword=0
Gosub,clearallvars
Continue
}
;Show matched command
StringTrimRight, match, match, 1 ; Get rid of the last linefeed
WinGetActiveTitle, ATitle
WinGetPos, , PosY, , SizeY, %ATitle%
ToolTipSizeY := (number * 12)
ToolTipPosY := A_CaretY+14
if ((ToolTipSizeY + ToolTipPosY) > (PosY + SizeY))
ToolTipPosY := (A_CaretY - 14 - ToolTipSizeY)
IfNotEqual, Word,,ToolTip, %match%, %A_CaretX%, %ToolTipPosY%
; +14 Move tooltip down a little so as not to hide the caret.
}
; Timed function to detect change of focus (and remove tooltip when changing active window)
Winchanged:
WinGetActiveTitle, ATitle
WinGet, A_id3, ID, %ATitle%
IfNotEqual, A_id, %A_id3%
{
ToolTip ,
} else {
; If we are in the correct window, and OldCaretY is set, clear the tooltip if not in the same line
IfInString, ATitle, %ETitle%
{
IfNotEqual, OldCaretY,
{
IfNotEqual, OldCaretY, %A_CaretY%
{
ToolTip,
}
}
}
}
Return
; Key definitions for autocomplete (0 to 9)
#MaxThreadsPerHotkey 1
$1::
$2::
$3::
$4::
$5::
$6::
$7::
$8::
$9::
$0::
CheckWord(A_ThisHotkey)
Return
; If hotkey was pressed, check wether there's a match going on and send it, otherwise send the number(s) typed
CheckWord(Key)
{
global
Local ATitle
Local A_id2
Local WordIndex
StringRight, Key, Key, 1
IfEqual, Key, 0
{
WordIndex = 10
} else {
WordIndex = %Key%
}
clearword=1
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
SendInput,%key%
Gosub,clearallvars
Return
}
IfNotEqual, OldCaretY, %A_CaretY% ;Make sure we are still on the same line
{
SendInput,%key%
Gosub,clearallvars
Return
}
ifequal, Word, ; only continue if word is not empty
{
SendInput,%key%
Setenv, Word, %key%
clearword=0
Gosub,clearallvars
Return
}
ifequal, singlematch%WordIndex%, ; only continue singlematch is not empty
{
SendInput,%key%
Setenv, Word, %word%%key%
clearword=0
Gosub,clearallvars
Return
}
Local sending
Local len
Local ClipboardSave
; SEND THE WORD!
if key =0
key = 10
sending := singlematch%WordIndex%
StringLen, len, Word
; Update Typed Count
UpdateWordCount(sending)
SendPlay, {BS %len%}{Raw}%sending% ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
; below works but uses clipboard
;ClipboardSave:=ClipboardAll
;Clipboard = %sending%
;SendPlay, {BS %len%}^v ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
;Clipboard = %ClipboardSave%
Gosub,clearallvars
Return
}
; This is to blank all vars related to matches, tooltip and (optionally) word
clearallvars:
Ifequal,clearword,1
{
Setenv,word,
OldCaretY=
}
ToolTip
; Clear all singlematches
Loop, 10
{
singlematch%a_index% =
}
sending =
key=
match=
clearword=1
Return
AddWordToList(AddWord)
{
global
Local CharTerminateList
Local Base
Local AddWordInList
Local CountWord
Local pos
Ifequal, Addword, ;If we have no word to add, skip out.
Return
if ( Substr(addword,1,1) = ";" ) ;If first char is ";", clear word and skip out.
{
IfEqual, wordlistdone, 0 ;If we are still reading the wordlist file and we come across ;LEARNEDWORDS; set the LearnedWordsCount flag
{
IfEqual, AddWord, `;LEARNEDWORDS`;
LearnedWordsCount=0
}
addword =
Return
}
ifequal, wordlistdone, 1 ;if we are not reading the wordlist file, use the following characters in the terminate list
CharTerminateList = 1,2,3,4,5,6,7,8,9,0
else CharTerminateList =
if addword contains %CharTerminateList% ;if one of the chars in the word is in the terminate list, don't add it
{
addword =
CharTerminateList =
Return
}
CharTerminateList =
IF ( StrLen(addword) <= wlen ) ; don't add the word if it's not longer than the minimum length
{
addword =
Return
}
Base := ConvertWordToAscii(SubStr(addword,1,wlen),1)
AddWordInList =
Loop ;Check to see if the word is already in the list, case sensitive
{
IfEqual, zword%base%%a_index%,, Break
if ( zword%base%%a_index% == AddWord )
{
AddWordInList = 1
Break
}
Continue
}
ifequal, AddWordInList, ; if the word is not in the list
{
IfEqual, WordListDone, 0 ;if this is read from the wordlist
{
IfNotEqual,LearnedWordsCount, ;if this is a stored learned word
{
CountWord := ConvertWordToAscii(addword,0)
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
zCount%CountWord% := LearnedWordsCount++ ;increment the count and store the Weight of the LearnedWord in reverse order (will be inverted later)
}
} else { ; If this is an on-the-fly learned word
CountWord := ConvertWordToAscii(addWord,0)
zCount%CountWord% = 1 ;set the count to one as it's the first time we typed it
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
}
; Increment the counter for each hash
zbasenum%Base%++
pos := zbasenum%Base%
; Set the hashed value to the word
zword%Base%%pos% = %addword%
pos =
} Else {
IfEqual, WordListDone, 1 ;if we've already typed the word and we've loaded the wordlist increment the count
{
UpdateWordCount(addword)
}
}
Return
}
; This sub will reverse the read numbers since now we know the total number of words
ReverseWordNums:
LearnedWordsCount+=4
Loop,parse,LearnedWords, `,
{
AsciiWord := ConvertWordToAscii(A_LoopField,0)
zCount%AsciiWord% := LearnedWordsCount - zCount%AsciiWord%
}
AsciiWord =
LearnedWordsCount =
Return
UpdateWordCount(word)
{
; If the Count for the word already exists - ie if it's a learned word, increment it, else don't.
local CountWord := ConvertWordToAscii(word,0)
IfNotEqual, zCount%CountWord%,
{
zCount%CountWord%++
local WordBase
StringLeft, WordBase, word, %wlen% ;find the pseudohash for the word
WordBase := ConvertWordToAscii(WordBase,1)
Local ConvertWord =
Local LowIndex =
Local WordList =
Loop
{
ifequal, zword%WordBase%%A_Index%, ;Break the loop if no more words to read for the hash
Break
CountWord := zword%WordBase%%A_Index% ;Set CountWord to the current Word position
ConvertWord := ConvertWordToAscii(CountWord,0) ; Find the Ascii equivalent of the word
IfNotEqual, zCount%ConvertWord%, ;If there's no count for this word do nothing
{
IfEqual, LowIndex,
LowIndex = %A_Index% ;If this is the first word we've found with a count set this as our starting position
IfEqual, WordList, ;if we have no words in our wordlist, start it - prefix all words with (Count"z")
{
WordList := zCount%ConvertWord% . "z" . CountWord
} Else { ;else append to the wordlist
WordList := WordList . "," . zCount%ConvertWord% . "z" . CountWord
}
}
}
ifnotequal, Wordlist, ;If we have no words to process, don't
{
Sort, WordList, N R D, ;Sort the wordlist by order of
LowIndex-- ;A_Index starts at 1 so this value needs to be decremented
Local IndexPos =
Loop, Parse, WordList, `,
{
IndexPos := LowIndex + A_Index ;Set the current word we are processing to the starting pos plus word position
StringTrimLeft, CountWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
zword%WordBase%%IndexPos% = %CountWord% ; update the word in the list
}
}
}
Return
}
ConvertWordToAscii(Base,Caps)
{
; Return the word in Ascii numbers padded to length 3 per character
; Capitalize the string if NoCaps is not set
IfEqual, Caps, 1
StringUpper, Base, Base
Loop, % StrLen(Base)
{
New := New . PadZeros(Asc(Base),3)
StringTrimLeft, Base, Base, 1
}
Return New
}
PadZeros(Word,Length)
{
; Pad a string out to Length numbers of 0's
StringLen, WordLen, Word
IfLess, WordLen, Length
{
Loop, % (Length - WordLen)
{
Word := "0" . Word
}
}
Return Word
}
SaveScript:
; Add all the standard words to the tempwordlist
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
IfEqual, A_LoopField, `;LEARNEDWORDS`;
SkipRest = 1
IfEqual, SkipRest,
TempWordList .= A_LoopField "`n"
}
ParseWords =
; Parse the learned words and store them in a new list by count if their total count is greater than 5.
; Prefix the word with the count and "z" for sorting
Loop, Parse, LearnedWords, `,
{
SortWord := ConvertWordToAscii(A_LoopField,0)
IfGreaterOrEqual, zCount%SortWord%, 5
{
IfEqual, SortWordList,
{
SortWordList := zCount%SortWord% . "z" . A_LoopField
} else {
SortWordList := SortWordList . "," . zCount%SortWord% . "z" . A_LoopField
}
}
}
Sort, SortWordList, N R D, ; Sort numerically, comma delimiter
IfNotEqual, SortWordList, ; If SortWordList exists write to the file, otherwise don't.
{
TempWordList .= "`;LEARNEDWORDS`;`n"
FirstTimeLoop = 1
Loop, Parse, SortWordList, `,
{
StringTrimLeft, AppendWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
IfEqual, FirstTimeLoop, ;If we are not in our first time through the loop append a new line before the word
{
AppendWord = `n%AppendWord%
} else {
FirstTimeLoop =
}
TempWordList .= AppendWord
}
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
FileAppend, %TempWordList%, %A_ScriptDir%\Temp_Wordlist.txt ;Only update the file if we have learned words
FileCopy, %A_ScriptDir%\Temp_Wordlist.txt, %A_ScriptDir%\Wordlist.txt, 1
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
}
ExitApp
|
|
|
| Back to top |
|
 |
SoLong&Thx4AllTheFish
Joined: 27 May 2007 Posts: 4999
|
Posted: Mon Jan 11, 2010 7:11 pm Post subject: |
|
|
This version no longer needs PadZeros | Code: | ConvertWordToAscii(Base,Caps)
{
; Return the word in Ascii numbers padded to length 3 per character
; Capitalize the string if NoCaps is not set
IfEqual, Caps, 1
StringUpper, Base, Base
Loop, Parse, Base ; will automatically parse each character
New := New . SubStr("00" . Asc(Base),-2)
Return New
} | There are a few more places where some loops could be removed
For example replace | Code: | ; Add all the standard words to the tempwordlist
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
IfEqual, A_LoopField, `;LEARNEDWORDS`;
SkipRest = 1
IfEqual, SkipRest,
TempWordList .= A_LoopField "`n"
} | loop with a one liner | Code: | ; Add all the standard words to the tempwordlist
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
TempWordList := SubStr(ParseWords, 1, InStr(ParseWords, "`;LEARNEDWORDS`;")-1) | would save you a long loop[/code] _________________ AHK Wiki FAQ
TF : Text files & strings lib, TF Forum |
|
| Back to top |
|
 |
kakarukeys
Joined: 28 Sep 2009 Posts: 86
|
Posted: Tue Jan 12, 2010 7:40 am Post subject: |
|
|
| Irfa wrote: |
I wanted to use this version with the 1.3MB dict that is above.
I added ;LEARNEDWORDS; at the top of the dict.
When i exited the script, it started doing something in Temp_wordlist
an cut the wordlist.txt to 82KB.
Can you fix it? |
Hi I keep a repository of word lists here:
http://www.artwinauto.com/downloads/typing-programs/typingaid.html#wordlist
Do you mind sharing your dictionary? if it's not in any languages listed there:
That's wonderful! I tested the script with this version. It worked like charm.
I will be sending it to the Doctor to try. We may be able to help many Bosnian school kids with learning difficulty.
@hugov
Good to hear your suggestions. They really help to gain insights into the performance bottleneck.
This thread woke up from a long sleep and now is a locomotive. _________________ TypingAid autocompletion program made with AHK. |
|
| Back to top |
|
 |
SoLong&Thx4AllTheFish
Joined: 27 May 2007 Posts: 4999
|
Posted: Tue Jan 12, 2010 11:19 am Post subject: |
|
|
Rather than hasing each word individually character by character why not hash the entire wordlist in one go, here is some code to get you started | Code: | ; hash entire wordlist in one go rather than word by word
_str=abcdefghijkmnkopqrstuvwxyzABCDEFGHIJKMNKOPQRSTUVWXYZ
FileRead, wordlist, wordlist.txt
StringCaseSense, On
Loop, Parse, _str
{
StringReplace, wordlist, wordlist, %A_LoopField%, % SubStr("00" . Asc(A_LoopField),-2), All
}
FileAppend, %wordlist%, hashedwordlist.txt
wordlist=
; reverse
FileRead, wordlist, hashedwordlist.txt
wordlist:=RegExReplace(wordlist,"im)(\d{3})","$1|") ; we need this to prevent incorrect replacements
StringCaseSense, On
Loop, Parse, _str
{
StringReplace, wordlist, wordlist, % SubStr("00" . Asc(A_LoopField),-2), %A_LoopField%, All
}
StringReplace, wordlist, wordlist, |,, all
FileAppend, %wordlist%, newwordlist.txt
; newwordlist.txt will be the same wordlist.txt | and take it from there _________________ AHK Wiki FAQ
TF : Text files & strings lib, TF Forum |
|
| Back to top |
|
 |
maniac
Joined: 28 Aug 2009 Posts: 267
|
Posted: Tue Jan 12, 2010 12:48 pm Post subject: |
|
|
| hugov wrote: | | This version no longer needs PadZeros |
Ah-ha, that makes perfect sense. I hate it when my thinking gets boxed .
| hugov wrote: |
There are a few more places where some loops could be removed |
Thanks, I fixed that example and cleaned up some small inefficiencies (unnecessary IF statements) in some other loops, but I couldn't find any more that I could figure out how to remove.
First page, last post:
http://www.autohotkey.com/forum/viewtopic.php?p=296781#296781
| kakarukeys wrote: |
That's wonderful! I tested the script with this version. It worked like charm.
I will be sending it to the Doctor to try. We may be able to help many Bosnian school kids with learning difficulty. |
Did you try it when a unicode character is in the first three characters? As I said before this script relies on ASCII codes for hashing (and it hashes the first 3 characters).
I'll take a look at your hashing suggestion tomorrow hugov, thanks... for now here is the modified version:
| Code: | ; Intellitype: typing aid
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
; - Jordi S
; Heavily modified by:
; Maniac
;___________________________________________
; CONFIGURATIONS
; Editor Window Recognition
; (make it blank to make the script seek all windows)
OnExit, SaveScript
ETitle =
;Minimum word length to make a guess
WLen = 3
keyagain=
key=
clearword=1
;Gosub,clearallvars ; clean vars from start
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
;_______________________________________
CoordMode, ToolTip, Relative
AutoTrim, Off
WordListDone = 0
;reads list of words from file
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
AddWordToList(A_LoopField)
}
ParseWords =
SetTimer, Winchanged, 100
GoSub, ReverseWordNums
WordlistDone = 1
Loop
{
;Editor window check
WinGetActiveTitle, ATitle
WinGet, A_id, ID, %ATitle%
IfNotInString, ATitle, %ETitle%
{
ToolTip
Setenv, Word,
WinWaitActive, %ETitle%
Continue
}
;Get one key at a time
Input, chr, L1 V,{enter}{space}.;`,:¿?¡!'"()]{}{}}{bs}{{}{esc}{tab}{Home}{End}{PgUp}{PdDn}{Up}{Dn}{Left}{Right}
EndKey = %errorlevel%
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
ifequal, OldCaretY,
OldCaretY = %A_CaretY%
ifnotequal, OldCaretY, %A_CaretY%
{
; add the word if switching lines
AddWordToList(Word)
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
OldCaretY=%A_CaretY%
;Backspace clears last letter
ifequal, EndKey, Endkey:BackSpace
{
StringLen, len, Word
IfNotEqual, len, 0
{
ifequal, len, 1
{
Gosub,clearallvars
} else {
StringTrimRight, Word, Word, 1
}
}
} else ifequal, EndKey, Max
{
Setenv, Word, %word%%chr%
} else {
;addword = %Word%
;Gosub, addwordtolist
AddWordToList(Word)
Gosub, clearallvars
}
;Wait till minimum letters
IF ( StrLen(Word) < wlen )
{
ToolTip,
Continue
}
;Match part-word with command
Num =
Match =
singlematch = 0
number = 0
StringLeft, baseword, Word, %wlen%
baseword := ConvertWordToAscii(baseword,1)
Loop
{
IfEqual, zword%baseword%%a_index%,, Break
IfEqual, number, 10
Break
if ( SubStr(zword%baseword%%a_index%, 1, StrLen(Word)) = Word )
{
number ++
singlematch := zword%baseword%%a_index%
match := match . Mod(number,10) . ". " . singlematch . "`n"
singlematch%number% = %singlematch%
Continue
}
}
;If no match then clear Tip
IfEqual, Match,
{
clearword=0
Gosub,clearallvars
Continue
}
;Show matched command
StringTrimRight, match, match, 1 ; Get rid of the last linefeed
WinGetActiveTitle, ATitle
WinGetPos, , PosY, , SizeY, %ATitle%
ToolTipSizeY := (number * 12)
ToolTipPosY := A_CaretY+14
if ((ToolTipSizeY + ToolTipPosY) > (PosY + SizeY))
ToolTipPosY := (A_CaretY - 14 - ToolTipSizeY)
IfNotEqual, Word,,ToolTip, %match%, %A_CaretX%, %ToolTipPosY%
; +14 Move tooltip down a little so as not to hide the caret.
}
; Timed function to detect change of focus (and remove tooltip when changing active window)
Winchanged:
WinGetActiveTitle, ATitle
WinGet, A_id3, ID, %ATitle%
IfNotEqual, A_id, %A_id3%
{
ToolTip ,
} else {
; If we are in the correct window, and OldCaretY is set, clear the tooltip if not in the same line
IfInString, ATitle, %ETitle%
{
IfNotEqual, OldCaretY,
{
IfNotEqual, OldCaretY, %A_CaretY%
{
ToolTip,
}
}
}
}
Return
; Key definitions for autocomplete (0 to 9)
#MaxThreadsPerHotkey 1
$1::
$2::
$3::
$4::
$5::
$6::
$7::
$8::
$9::
$0::
CheckWord(A_ThisHotkey)
Return
; If hotkey was pressed, check wether there's a match going on and send it, otherwise send the number(s) typed
CheckWord(Key)
{
global
Local ATitle
Local A_id2
Local WordIndex
StringRight, Key, Key, 1 ;Grab just the number pushed, trim off the "$"
IfEqual, Key, 0
{
WordIndex = 10
} else {
WordIndex = %Key%
}
clearword=1
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
SendInput,%key%
Gosub,clearallvars
Return
}
IfNotEqual, OldCaretY, %A_CaretY% ;Make sure we are still on the same line
{
SendInput,%key%
Gosub,clearallvars
Return
}
ifequal, Word, ; only continue if word is not empty
{
SendInput,%key%
Setenv, Word, %key%
clearword=0
Gosub,clearallvars
Return
}
ifequal, singlematch%WordIndex%, ; only continue singlematch is not empty
{
SendInput,%key%
Setenv, Word, %word%%key%
clearword=0
Gosub,clearallvars
Return
}
Local sending
Local len
Local ClipboardSave
; SEND THE WORD!
if key =0
key = 10
sending := singlematch%WordIndex%
StringLen, len, Word
; Update Typed Count
UpdateWordCount(sending)
SendPlay, {BS %len%}{Raw}%sending% ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
; below works but uses clipboard
;ClipboardSave:=ClipboardAll
;Clipboard = %sending%
;SendPlay, {BS %len%}^v ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
;Clipboard = %ClipboardSave%
Gosub,clearallvars
Return
}
; This is to blank all vars related to matches, tooltip and (optionally) word
clearallvars:
Ifequal,clearword,1
{
Setenv,word,
OldCaretY=
}
ToolTip
; Clear all singlematches
Loop, 10
{
singlematch%a_index% =
}
sending =
key=
match=
clearword=1
Return
AddWordToList(AddWord)
{
global
Local CharTerminateList
Local Base
Local AddWordInList
Local CountWord
Local pos
Ifequal, Addword, ;If we have no word to add, skip out.
Return
if ( Substr(addword,1,1) = ";" ) ;If first char is ";", clear word and skip out.
{
IfEqual, wordlistdone, 0 ;If we are still reading the wordlist file and we come across ;LEARNEDWORDS; set the LearnedWordsCount flag
{
IfEqual, AddWord, `;LEARNEDWORDS`;
LearnedWordsCount=0
}
addword =
Return
}
ifequal, wordlistdone, 1 ;if we are not reading the wordlist file, use the following characters in the terminate list
CharTerminateList = 1,2,3,4,5,6,7,8,9,0
else CharTerminateList =
if addword contains %CharTerminateList% ;if one of the chars in the word is in the terminate list, don't add it
{
addword =
CharTerminateList =
Return
}
CharTerminateList =
IF ( StrLen(addword) <= wlen ) ; don't add the word if it's not longer than the minimum length
{
addword =
Return
}
Base := ConvertWordToAscii(SubStr(addword,1,wlen),1)
AddWordInList =
Loop ;Check to see if the word is already in the list, case sensitive
{
IfEqual, zword%base%%a_index%,, Break
if ( zword%base%%a_index% == AddWord )
{
AddWordInList = 1
Break
}
Continue
}
ifequal, AddWordInList, ; if the word is not in the list
{
IfEqual, WordListDone, 0 ;if this is read from the wordlist
{
IfNotEqual,LearnedWordsCount, ;if this is a stored learned word
{
CountWord := ConvertWordToAscii(addword,0)
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
zCount%CountWord% := LearnedWordsCount++ ;increment the count and store the Weight of the LearnedWord in reverse order (will be inverted later)
}
} else { ; If this is an on-the-fly learned word
CountWord := ConvertWordToAscii(addWord,0)
zCount%CountWord% = 1 ;set the count to one as it's the first time we typed it
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
}
; Increment the counter for each hash
zbasenum%Base%++
pos := zbasenum%Base%
; Set the hashed value to the word
zword%Base%%pos% = %addword%
pos =
} Else {
IfEqual, WordListDone, 1 ;if we've already typed the word and we've loaded the wordlist increment the count
{
UpdateWordCount(addword)
}
}
Return
}
; This sub will reverse the read numbers since now we know the total number of words
ReverseWordNums:
LearnedWordsCount+=4
Loop,parse,LearnedWords, `,
{
AsciiWord := ConvertWordToAscii(A_LoopField,0)
zCount%AsciiWord% := LearnedWordsCount - zCount%AsciiWord%
}
AsciiWord =
LearnedWordsCount =
Return
UpdateWordCount(word)
{
; If the Count for the word already exists - ie if it's a learned word, increment it, else don't.
local CountWord := ConvertWordToAscii(word,0)
IfNotEqual, zCount%CountWord%,
{
zCount%CountWord%++
local WordBase
StringLeft, WordBase, word, %wlen% ;find the pseudohash for the word
WordBase := ConvertWordToAscii(WordBase,1)
Local ConvertWord =
Local LowIndex =
Local WordList =
Loop
{
ifequal, zword%WordBase%%A_Index%, ;Break the loop if no more words to read for the hash
Break
CountWord := zword%WordBase%%A_Index% ;Set CountWord to the current Word position
ConvertWord := ConvertWordToAscii(CountWord,0) ; Find the Ascii equivalent of the word
IfNotEqual, zCount%ConvertWord%, ;If there's no count for this word do nothing
{
IfEqual, LowIndex,
LowIndex = %A_Index% ;If this is the first word we've found with a count set this as our starting position
IfEqual, WordList, ;if we have no words in our wordlist, start it - prefix all words with (zCount"z")
{
WordList := zCount%ConvertWord% . "z" . CountWord
} Else { ;else append to the wordlist
WordList := WordList . "," . zCount%ConvertWord% . "z" . CountWord
}
}
}
ifnotequal, Wordlist, ;If we have no words to process, don't
{
Sort, WordList, N R D, ;Sort the wordlist by order of
LowIndex-- ;A_Index starts at 1 so this value needs to be decremented
Local IndexPos =
Loop, Parse, WordList, `,
{
IndexPos := LowIndex + A_Index ;Set the current word we are processing to the starting pos plus word position
StringTrimLeft, CountWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
zword%WordBase%%IndexPos% = %CountWord% ; update the word in the list
}
}
}
Return
}
ConvertWordToAscii(Base,Caps)
{
; Return the word in Ascii numbers padded to length 3 per character
; Capitalize the string if NoCaps is not set
IfEqual, Caps, 1
StringUpper, Base, Base
Loop, % StrLen(Base)
{
New := New . SubStr("00" . Asc(Base),-2)
StringTrimLeft, Base, Base, 1
}
Return New
}
SaveScript:
; Add all the standard words to the tempwordlist
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
LearnedwordsPos := InStr(ParseWords, "`;LEARNEDWORDS`;",true,1) ;Check for Learned Words
IfNotEqual, LearnedwordsPos, 0
{
TempWordList := SubStr(ParseWords, 1, LearnedwordsPos - 1) ;Grab all non-learned words out of list
} else {
TempWordList := ParseWords
}
ParseWords =
; Parse the learned words and store them in a new list by count if their total count is greater than 5.
; Prefix the word with the count and "z" for sorting
Loop, Parse, LearnedWords, `,
{
SortWord := ConvertWordToAscii(A_LoopField,0)
IfGreaterOrEqual, zCount%SortWord%, 5
{
SortWordList := SortWordList . "," . zCount%SortWord% . "z" . A_LoopField
}
}
StringTrimLeft, SortWordList, SortWordList, 1 ;remove extra starting comma
Sort, SortWordList, N R D, ; Sort numerically, comma delimiter
IfNotEqual, SortWordList, ; If SortWordList exists write to the file, otherwise don't.
{
TempWordList .= "`;LEARNEDWORDS`;`r`n"
Loop, Parse, SortWordList, `,
{
StringTrimLeft, AppendWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
TempWordList .= AppendWord . "`r`n"
}
StringTrimRight, TempWordList, TempWordList, 2
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
FileAppend, %TempWordList%, %A_ScriptDir%\Temp_Wordlist.txt ;Only update the file if we have learned words
FileCopy, %A_ScriptDir%\Temp_Wordlist.txt, %A_ScriptDir%\Wordlist.txt, 1
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
}
ExitApp
|
|
|
| Back to top |
|
 |
kakarukeys
Joined: 28 Sep 2009 Posts: 86
|
Posted: Tue Jan 12, 2010 1:05 pm Post subject: |
|
|
http://www.artwinauto.com/c-bowl%20recognition.jpg
Any idea how it works underneath the layers of code?
I could only imagine it's an ascii c in there, when it's sent to the application, it became a Unicode c-bowl. This doesn't make much sense. What do you think? _________________ TypingAid autocompletion program made with AHK. |
|
| Back to top |
|
 |
maniac
Joined: 28 Aug 2009 Posts: 267
|
Posted: Tue Jan 12, 2010 2:48 pm Post subject: |
|
|
| kakarukeys wrote: | http://www.artwinauto.com/c-bowl%20recognition.jpg
Any idea how it works underneath the layers of code?
I could only imagine it's an ascii c in there, when it's sent to the application, it became a Unicode c-bowl. This doesn't make much sense. What do you think? |
I'm not sure, if you type "poc" in all regular characters does it work then (ie does the autocomplete pop up for po(c-bowl)?
The other option is that ASC is returning a unicode value, I haven't tried the unicode version to see what is being returned. You'd have to look at the zBaseWord variables to find out.
Also, I just fixed some huge efficiency issues. So it turns out that doing:
SortWordList := SortWordList . "new value"
is WAYYY less efficient than doing:
SortWordList .= "new value"
I changed all my instances of the above to use .=
It now takes ~1 minute to start the script and less than 30 seconds to exit it (with the 1.3 MB wordlist). I also increased max CPU usage of the script from 50% to 66%, and I added a few other small performance boosts (ListLines, Off; #NoEnv).
| Code: | ; Intellitype: typing aid
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
; - Jordi S
; Heavily modified by:
; Maniac
;___________________________________________
; CONFIGURATIONS
#NoEnv
SetBatchLines, 20ms
ListLines Off
OnExit, SaveScript
; Editor Window Recognition
; (make it blank to make the script seek all windows)
ETitle =
;Minimum word length to make a guess
WLen = 3
keyagain=
key=
clearword=1
;Gosub,clearallvars ; clean vars from start
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
;_______________________________________
CoordMode, ToolTip, Relative
AutoTrim, Off
WordListDone = 0
;reads list of words from file
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
AddWordToList(A_LoopField)
}
ParseWords =
SetTimer, Winchanged, 100
GoSub, ReverseWordNums
WordlistDone = 1
Loop
{
;Editor window check
WinGetActiveTitle, ATitle
WinGet, A_id, ID, %ATitle%
IfNotInString, ATitle, %ETitle%
{
ToolTip
Setenv, Word,
WinWaitActive, %ETitle%
Continue
}
;Get one key at a time
Input, chr, L1 V,{enter}{space}.;`,:¿?¡!'"()]{}{}}{bs}{{}{esc}{tab}{Home}{End}{PgUp}{PdDn}{Up}{Dn}{Left}{Right}
EndKey = %errorlevel%
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
ifequal, OldCaretY,
OldCaretY = %A_CaretY%
ifnotequal, OldCaretY, %A_CaretY%
{
; add the word if switching lines
AddWordToList(Word)
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
OldCaretY=%A_CaretY%
;Backspace clears last letter
ifequal, EndKey, Endkey:BackSpace
{
StringLen, len, Word
IfNotEqual, len, 0
{
ifequal, len, 1
{
Gosub,clearallvars
} else {
StringTrimRight, Word, Word, 1
}
}
} else ifequal, EndKey, Max
{
Setenv, Word, %word%%chr%
} else {
;addword = %Word%
;Gosub, addwordtolist
AddWordToList(Word)
Gosub, clearallvars
}
;Wait till minimum letters
IF ( StrLen(Word) < wlen )
{
ToolTip,
Continue
}
;Match part-word with command
Num =
Match =
singlematch = 0
number = 0
StringLeft, baseword, Word, %wlen%
baseword := ConvertWordToAscii(baseword,1)
Loop
{
IfEqual, zword%baseword%%a_index%,, Break
IfEqual, number, 10
Break
if ( SubStr(zword%baseword%%a_index%, 1, StrLen(Word)) = Word )
{
number ++
singlematch := zword%baseword%%a_index%
match .= Mod(number,10) . ". " . singlematch . "`n"
singlematch%number% = %singlematch%
Continue
}
}
;If no match then clear Tip
IfEqual, Match,
{
clearword=0
Gosub,clearallvars
Continue
}
;Show matched command
StringTrimRight, match, match, 1 ; Get rid of the last linefeed
WinGetActiveTitle, ATitle
WinGetPos, , PosY, , SizeY, %ATitle%
ToolTipSizeY := (number * 12)
ToolTipPosY := A_CaretY+14
if ((ToolTipSizeY + ToolTipPosY) > (PosY + SizeY))
ToolTipPosY := (A_CaretY - 14 - ToolTipSizeY)
IfNotEqual, Word,,ToolTip, %match%, %A_CaretX%, %ToolTipPosY%
; +14 Move tooltip down a little so as not to hide the caret.
}
; Timed function to detect change of focus (and remove tooltip when changing active window)
Winchanged:
WinGetActiveTitle, ATitle
WinGet, A_id3, ID, %ATitle%
IfNotEqual, A_id, %A_id3%
{
ToolTip ,
} else {
; If we are in the correct window, and OldCaretY is set, clear the tooltip if not in the same line
IfInString, ATitle, %ETitle%
{
IfNotEqual, OldCaretY,
{
IfNotEqual, OldCaretY, %A_CaretY%
{
ToolTip,
}
}
}
}
Return
; Key definitions for autocomplete (0 to 9)
#MaxThreadsPerHotkey 1
$1::
$2::
$3::
$4::
$5::
$6::
$7::
$8::
$9::
$0::
CheckWord(A_ThisHotkey)
Return
; If hotkey was pressed, check wether there's a match going on and send it, otherwise send the number(s) typed
CheckWord(Key)
{
global
Local ATitle
Local A_id2
Local WordIndex
StringRight, Key, Key, 1 ;Grab just the number pushed, trim off the "$"
IfEqual, Key, 0
{
WordIndex = 10
} else {
WordIndex = %Key%
}
clearword=1
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
SendInput,%key%
Gosub,clearallvars
Return
}
IfNotEqual, OldCaretY, %A_CaretY% ;Make sure we are still on the same line
{
SendInput,%key%
Gosub,clearallvars
Return
}
ifequal, Word, ; only continue if word is not empty
{
SendInput,%key%
Setenv, Word, %key%
clearword=0
Gosub,clearallvars
Return
}
ifequal, singlematch%WordIndex%, ; only continue singlematch is not empty
{
SendInput,%key%
Setenv, Word, %word%%key%
clearword=0
Gosub,clearallvars
Return
}
Local sending
Local len
Local ClipboardSave
; SEND THE WORD!
if key =0
key = 10
sending := singlematch%WordIndex%
StringLen, len, Word
; Update Typed Count
UpdateWordCount(sending)
SendPlay, {BS %len%}{Raw}%sending% ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
; below works but uses clipboard
;ClipboardSave:=ClipboardAll
;Clipboard = %sending%
;SendPlay, {BS %len%}^v ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
;Clipboard = %ClipboardSave%
Gosub,clearallvars
Return
}
; This is to blank all vars related to matches, tooltip and (optionally) word
clearallvars:
Ifequal,clearword,1
{
Setenv,word,
OldCaretY=
}
ToolTip
; Clear all singlematches
Loop, 10
{
singlematch%a_index% =
}
sending =
key=
match=
clearword=1
Return
AddWordToList(AddWord)
{
global
Local CharTerminateList
Local Base
Local AddWordInList
Local CountWord
Local pos
Ifequal, Addword, ;If we have no word to add, skip out.
Return
if ( Substr(addword,1,1) = ";" ) ;If first char is ";", clear word and skip out.
{
IfEqual, wordlistdone, 0 ;If we are still reading the wordlist file and we come across ;LEARNEDWORDS; set the LearnedWordsCount flag
{
IfEqual, AddWord, `;LEARNEDWORDS`;
LearnedWordsCount=0
}
addword =
Return
}
ifequal, wordlistdone, 1 ;if we are not reading the wordlist file, use the following characters in the terminate list
CharTerminateList = 1,2,3,4,5,6,7,8,9,0
else CharTerminateList =
if addword contains %CharTerminateList% ;if one of the chars in the word is in the terminate list, don't add it
{
addword =
CharTerminateList =
Return
}
CharTerminateList =
IF ( StrLen(addword) <= wlen ) ; don't add the word if it's not longer than the minimum length
{
addword =
Return
}
Base := ConvertWordToAscii(SubStr(addword,1,wlen),1)
AddWordInList =
Loop ;Check to see if the word is already in the list, case sensitive
{
IfEqual, zword%base%%a_index%,, Break
if ( zword%base%%a_index% == AddWord )
{
AddWordInList = 1
Break
}
Continue
}
ifequal, AddWordInList, ; if the word is not in the list
{
IfEqual, WordListDone, 0 ;if this is read from the wordlist
{
IfNotEqual,LearnedWordsCount, ;if this is a stored learned word
{
CountWord := ConvertWordToAscii(addword,0)
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
zCount%CountWord% := LearnedWordsCount++ ;increment the count and store the Weight of the LearnedWord in reverse order (will be inverted later)
}
} else { ; If this is an on-the-fly learned word
CountWord := ConvertWordToAscii(addWord,0)
zCount%CountWord% = 1 ;set the count to one as it's the first time we typed it
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
}
; Increment the counter for each hash
zbasenum%Base%++
pos := zbasenum%Base%
; Set the hashed value to the word
zword%Base%%pos% = %addword%
pos =
} Else {
IfEqual, WordListDone, 1 ;if we've already typed the word and we've loaded the wordlist increment the count
{
UpdateWordCount(addword)
}
}
Return
}
; This sub will reverse the read numbers since now we know the total number of words
ReverseWordNums:
LearnedWordsCount+=4
Loop,parse,LearnedWords, `,
{
AsciiWord := ConvertWordToAscii(A_LoopField,0)
zCount%AsciiWord% := LearnedWordsCount - zCount%AsciiWord%
}
AsciiWord =
LearnedWordsCount =
Return
UpdateWordCount(word)
{
; If the Count for the word already exists - ie if it's a learned word, increment it, else don't.
local CountWord := ConvertWordToAscii(word,0)
IfNotEqual, zCount%CountWord%,
{
zCount%CountWord%++
local WordBase
StringLeft, WordBase, word, %wlen% ;find the pseudohash for the word
WordBase := ConvertWordToAscii(WordBase,1)
Local ConvertWord =
Local LowIndex =
Local WordList =
Loop
{
ifequal, zword%WordBase%%A_Index%, ;Break the loop if no more words to read for the hash
Break
CountWord := zword%WordBase%%A_Index% ;Set CountWord to the current Word position
ConvertWord := ConvertWordToAscii(CountWord,0) ; Find the Ascii equivalent of the word
IfNotEqual, zCount%ConvertWord%, ;If there's no count for this word do nothing
{
IfEqual, LowIndex,
LowIndex = %A_Index% ;If this is the first word we've found with a count set this as our starting position
WordList .= "," . zCount%ConvertWord% . "z" . CountWord ;prefix all words with (zCount"z")
}
}
ifnotequal, Wordlist, ;If we have no words to process, don't
{
StringTrimLeft, WordList, WordList, 1
Sort, WordList, N R D, ;Sort the wordlist by order of
LowIndex-- ;A_Index starts at 1 so this value needs to be decremented
Local IndexPos =
Loop, Parse, WordList, `,
{
IndexPos := LowIndex + A_Index ;Set the current word we are processing to the starting pos plus word position
StringTrimLeft, CountWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
zword%WordBase%%IndexPos% = %CountWord% ; update the word in the list
}
}
}
Return
}
ConvertWordToAscii(Base,Caps)
{
; Return the word in Ascii numbers padded to length 3 per character
; Capitalize the string if NoCaps is not set
IfEqual, Caps, 1
StringUpper, Base, Base
Loop, % StrLen(Base)
{
New .= SubStr("00" . Asc(Base),-2)
StringTrimLeft, Base, Base, 1
}
Return New
}
SaveScript:
; Add all the standard words to the tempwordlist
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
LearnedwordsPos := InStr(ParseWords, "`;LEARNEDWORDS`;",true,1) ;Check for Learned Words
IfNotEqual, LearnedwordsPos, 0
{
TempWordList := SubStr(ParseWords, 1, LearnedwordsPos - 1) ;Grab all non-learned words out of list
} else {
TempWordList := ParseWords
}
ParseWords =
; Parse the learned words and store them in a new list by count if their total count is greater than 5.
; Prefix the word with the count and "z" for sorting
Loop, Parse, LearnedWords, `,
{
SortWord := ConvertWordToAscii(A_LoopField,0)
IfGreaterOrEqual, zCount%SortWord%, 5
{
SortWordList .= "," . zCount%SortWord% . "z" . A_LoopField
}
}
StringTrimLeft, SortWordList, SortWordList, 1 ;remove extra starting comma
Sort, SortWordList, N R D, ; Sort numerically, comma delimiter
IfNotEqual, SortWordList, ; If SortWordList exists write to the file, otherwise don't.
{
TempWordList .= "`;LEARNEDWORDS`;`r`n"
Loop, Parse, SortWordList, `,
{
StringTrimLeft, AppendWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
TempWordList .= AppendWord . "`r`n"
}
StringTrimRight, TempWordList, TempWordList, 2
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
FileAppend, %TempWordList%, %A_ScriptDir%\Temp_Wordlist.txt ;Only update the file if we have learned words
FileCopy, %A_ScriptDir%\Temp_Wordlist.txt, %A_ScriptDir%\Wordlist.txt, 1
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
}
ExitApp
|
Last edited by maniac on Tue Jan 12, 2010 2:54 pm; edited 1 time in total |
|
| Back to top |
|
 |
SoLong&Thx4AllTheFish
Joined: 27 May 2007 Posts: 4999
|
Posted: Tue Jan 12, 2010 2:57 pm Post subject: |
|
|
| Code: | Loop, % StrLen(Base)
{
New .= SubStr("00" . Asc(Base),-2)
StringTrimLeft, Base, Base, 1
} | Minor optimisation: | Code: | Loop, parse, Base
{
New .= SubStr("00" . Asc(A_Loopfield),-2)
} |  _________________ AHK Wiki FAQ
TF : Text files & strings lib, TF Forum |
|
| Back to top |
|
 |
maniac
Joined: 28 Aug 2009 Posts: 267
|
Posted: Tue Jan 12, 2010 3:01 pm Post subject: |
|
|
| hugov wrote: | Minor optimisation:
 |
Good call, thanks.
| Code: | ; Intellitype: typing aid
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
; - Jordi S
; Heavily modified by:
; Maniac
;___________________________________________
; CONFIGURATIONS
#NoEnv
SetBatchLines, 20ms
ListLines Off
OnExit, SaveScript
; Editor Window Recognition
; (make it blank to make the script seek all windows)
ETitle =
;Minimum word length to make a guess
WLen = 3
keyagain=
key=
clearword=1
;Gosub,clearallvars ; clean vars from start
; Press 1 to 0 keys to autocomplete the word upon suggestion
; (0 will match suggestion 10)
;_______________________________________
CoordMode, ToolTip, Relative
AutoTrim, Off
WordListDone = 0
;reads list of words from file
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
Loop, Parse, ParseWords, `n, `r
{
AddWordToList(A_LoopField)
}
ParseWords =
SetTimer, Winchanged, 100
GoSub, ReverseWordNums
WordlistDone = 1
Loop
{
;Editor window check
WinGetActiveTitle, ATitle
WinGet, A_id, ID, %ATitle%
IfNotInString, ATitle, %ETitle%
{
ToolTip
Setenv, Word,
WinWaitActive, %ETitle%
Continue
}
;Get one key at a time
Input, chr, L1 V,{enter}{space}.;`,:¿?¡!'"()]{}{}}{bs}{{}{esc}{tab}{Home}{End}{PgUp}{PdDn}{Up}{Dn}{Left}{Right}
EndKey = %errorlevel%
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
ifequal, OldCaretY,
OldCaretY = %A_CaretY%
ifnotequal, OldCaretY, %A_CaretY%
{
; add the word if switching lines
AddWordToList(Word)
Gosub,clearallvars
Setenv, Word, %chr%
Continue
}
OldCaretY=%A_CaretY%
;Backspace clears last letter
ifequal, EndKey, Endkey:BackSpace
{
StringLen, len, Word
IfNotEqual, len, 0
{
ifequal, len, 1
{
Gosub,clearallvars
} else {
StringTrimRight, Word, Word, 1
}
}
} else ifequal, EndKey, Max
{
Setenv, Word, %word%%chr%
} else {
;addword = %Word%
;Gosub, addwordtolist
AddWordToList(Word)
Gosub, clearallvars
}
;Wait till minimum letters
IF ( StrLen(Word) < wlen )
{
ToolTip,
Continue
}
;Match part-word with command
Num =
Match =
singlematch = 0
number = 0
StringLeft, baseword, Word, %wlen%
baseword := ConvertWordToAscii(baseword,1)
Loop
{
IfEqual, zword%baseword%%a_index%,, Break
IfEqual, number, 10
Break
if ( SubStr(zword%baseword%%a_index%, 1, StrLen(Word)) = Word )
{
number ++
singlematch := zword%baseword%%a_index%
match .= Mod(number,10) . ". " . singlematch . "`n"
singlematch%number% = %singlematch%
Continue
}
}
;If no match then clear Tip
IfEqual, Match,
{
clearword=0
Gosub,clearallvars
Continue
}
;Show matched command
StringTrimRight, match, match, 1 ; Get rid of the last linefeed
WinGetActiveTitle, ATitle
WinGetPos, , PosY, , SizeY, %ATitle%
ToolTipSizeY := (number * 12)
ToolTipPosY := A_CaretY+14
if ((ToolTipSizeY + ToolTipPosY) > (PosY + SizeY))
ToolTipPosY := (A_CaretY - 14 - ToolTipSizeY)
IfNotEqual, Word,,ToolTip, %match%, %A_CaretX%, %ToolTipPosY%
; +14 Move tooltip down a little so as not to hide the caret.
}
; Timed function to detect change of focus (and remove tooltip when changing active window)
Winchanged:
WinGetActiveTitle, ATitle
WinGet, A_id3, ID, %ATitle%
IfNotEqual, A_id, %A_id3%
{
ToolTip ,
} else {
; If we are in the correct window, and OldCaretY is set, clear the tooltip if not in the same line
IfInString, ATitle, %ETitle%
{
IfNotEqual, OldCaretY,
{
IfNotEqual, OldCaretY, %A_CaretY%
{
ToolTip,
}
}
}
}
Return
; Key definitions for autocomplete (0 to 9)
#MaxThreadsPerHotkey 1
$1::
$2::
$3::
$4::
$5::
$6::
$7::
$8::
$9::
$0::
CheckWord(A_ThisHotkey)
Return
; If hotkey was pressed, check wether there's a match going on and send it, otherwise send the number(s) typed
CheckWord(Key)
{
global
Local ATitle
Local A_id2
Local WordIndex
StringRight, Key, Key, 1 ;Grab just the number pushed, trim off the "$"
IfEqual, Key, 0
{
WordIndex = 10
} else {
WordIndex = %Key%
}
clearword=1
; If active window has different window ID from before the input, blank word
; (well, assign the number pressed to the word)
WinGetActiveTitle, ATitle
WinGet, A_id2, ID, %ATitle%
IfNotEqual, A_id, %A_id2%
{
SendInput,%key%
Gosub,clearallvars
Return
}
IfNotEqual, OldCaretY, %A_CaretY% ;Make sure we are still on the same line
{
SendInput,%key%
Gosub,clearallvars
Return
}
ifequal, Word, ; only continue if word is not empty
{
SendInput,%key%
Setenv, Word, %key%
clearword=0
Gosub,clearallvars
Return
}
ifequal, singlematch%WordIndex%, ; only continue singlematch is not empty
{
SendInput,%key%
Setenv, Word, %word%%key%
clearword=0
Gosub,clearallvars
Return
}
Local sending
Local len
Local ClipboardSave
; SEND THE WORD!
if key =0
key = 10
sending := singlematch%WordIndex%
StringLen, len, Word
; Update Typed Count
UpdateWordCount(sending)
SendPlay, {BS %len%}{Raw}%sending% ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
; below works but uses clipboard
;ClipboardSave:=ClipboardAll
;Clipboard = %sending%
;SendPlay, {BS %len%}^v ; First do the backspaces, Then send word (Raw because we want the string exactly as in wordlist.txt)
;Clipboard = %ClipboardSave%
Gosub,clearallvars
Return
}
; This is to blank all vars related to matches, tooltip and (optionally) word
clearallvars:
Ifequal,clearword,1
{
Setenv,word,
OldCaretY=
}
ToolTip
; Clear all singlematches
Loop, 10
{
singlematch%a_index% =
}
sending =
key=
match=
clearword=1
Return
AddWordToList(AddWord)
{
global
Local CharTerminateList
Local Base
Local AddWordInList
Local CountWord
Local pos
Ifequal, Addword, ;If we have no word to add, skip out.
Return
if ( Substr(addword,1,1) = ";" ) ;If first char is ";", clear word and skip out.
{
IfEqual, wordlistdone, 0 ;If we are still reading the wordlist file and we come across ;LEARNEDWORDS; set the LearnedWordsCount flag
{
IfEqual, AddWord, `;LEARNEDWORDS`;
LearnedWordsCount=0
}
addword =
Return
}
ifequal, wordlistdone, 1 ;if we are not reading the wordlist file, use the following characters in the terminate list
CharTerminateList = 1,2,3,4,5,6,7,8,9,0
else CharTerminateList =
if addword contains %CharTerminateList% ;if one of the chars in the word is in the terminate list, don't add it
{
addword =
CharTerminateList =
Return
}
CharTerminateList =
IF ( StrLen(addword) <= wlen ) ; don't add the word if it's not longer than the minimum length
{
addword =
Return
}
Base := ConvertWordToAscii(SubStr(addword,1,wlen),1)
AddWordInList =
Loop ;Check to see if the word is already in the list, case sensitive
{
IfEqual, zword%base%%a_index%,, Break
if ( zword%base%%a_index% == AddWord )
{
AddWordInList = 1
Break
}
Continue
}
ifequal, AddWordInList, ; if the word is not in the list
{
IfEqual, WordListDone, 0 ;if this is read from the wordlist
{
IfNotEqual,LearnedWordsCount, ;if this is a stored learned word
{
CountWord := ConvertWordToAscii(addword,0)
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
zCount%CountWord% := LearnedWordsCount++ ;increment the count and store the Weight of the LearnedWord in reverse order (will be inverted later)
}
} else { ; If this is an on-the-fly learned word
CountWord := ConvertWordToAscii(addWord,0)
zCount%CountWord% = 1 ;set the count to one as it's the first time we typed it
IfEqual, LearnedWords, ;if we haven't learned any words yet, set the LearnedWords list to the new word
{
LearnedWords = %addword%
} else { ;otherwise append the learned word to the list
LearnedWords = %LearnedWords%,%addword%
}
}
; Increment the counter for each hash
zbasenum%Base%++
pos := zbasenum%Base%
; Set the hashed value to the word
zword%Base%%pos% = %addword%
pos =
} Else {
IfEqual, WordListDone, 1 ;if we've already typed the word and we've loaded the wordlist increment the count
{
UpdateWordCount(addword)
}
}
Return
}
; This sub will reverse the read numbers since now we know the total number of words
ReverseWordNums:
LearnedWordsCount+=4
Loop,parse,LearnedWords, `,
{
AsciiWord := ConvertWordToAscii(A_LoopField,0)
zCount%AsciiWord% := LearnedWordsCount - zCount%AsciiWord%
}
AsciiWord =
LearnedWordsCount =
Return
UpdateWordCount(word)
{
; If the Count for the word already exists - ie if it's a learned word, increment it, else don't.
local CountWord := ConvertWordToAscii(word,0)
IfNotEqual, zCount%CountWord%,
{
zCount%CountWord%++
local WordBase
StringLeft, WordBase, word, %wlen% ;find the pseudohash for the word
WordBase := ConvertWordToAscii(WordBase,1)
Local ConvertWord =
Local LowIndex =
Local WordList =
Loop
{
ifequal, zword%WordBase%%A_Index%, ;Break the loop if no more words to read for the hash
Break
CountWord := zword%WordBase%%A_Index% ;Set CountWord to the current Word position
ConvertWord := ConvertWordToAscii(CountWord,0) ; Find the Ascii equivalent of the word
IfNotEqual, zCount%ConvertWord%, ;If there's no count for this word do nothing
{
IfEqual, LowIndex,
LowIndex = %A_Index% ;If this is the first word we've found with a count set this as our starting position
WordList .= "," . zCount%ConvertWord% . "z" . CountWord ;prefix all words with (zCount"z")
}
}
ifnotequal, Wordlist, ;If we have no words to process, don't
{
StringTrimLeft, WordList, WordList, 1
Sort, WordList, N R D, ;Sort the wordlist by order of
LowIndex-- ;A_Index starts at 1 so this value needs to be decremented
Local IndexPos =
Loop, Parse, WordList, `,
{
IndexPos := LowIndex + A_Index ;Set the current word we are processing to the starting pos plus word position
StringTrimLeft, CountWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
zword%WordBase%%IndexPos% = %CountWord% ; update the word in the list
}
}
}
Return
}
ConvertWordToAscii(Base,Caps)
{
; Return the word in Ascii numbers padded to length 3 per character
; Capitalize the string if NoCaps is not set
IfEqual, Caps, 1
StringUpper, Base, Base
Loop, Parse, Base
{
New .= SubStr("00" . Asc(A_LoopField),-2)
}
Return New
}
SaveScript:
; Add all the standard words to the tempwordlist
FileRead, ParseWords, %A_ScriptDir%\Wordlist.txt
LearnedwordsPos := InStr(ParseWords, "`;LEARNEDWORDS`;",true,1) ;Check for Learned Words
IfNotEqual, LearnedwordsPos, 0
{
TempWordList := SubStr(ParseWords, 1, LearnedwordsPos - 1) ;Grab all non-learned words out of list
} else {
TempWordList := ParseWords
}
ParseWords =
; Parse the learned words and store them in a new list by count if their total count is greater than 5.
; Prefix the word with the count and "z" for sorting
Loop, Parse, LearnedWords, `,
{
SortWord := ConvertWordToAscii(A_LoopField,0)
IfGreaterOrEqual, zCount%SortWord%, 5
{
SortWordList .= "," . zCount%SortWord% . "z" . A_LoopField
}
}
StringTrimLeft, SortWordList, SortWordList, 1 ;remove extra starting comma
Sort, SortWordList, N R D, ; Sort numerically, comma delimiter
IfNotEqual, SortWordList, ; If SortWordList exists write to the file, otherwise don't.
{
TempWordList .= "`;LEARNEDWORDS`;`r`n"
Loop, Parse, SortWordList, `,
{
StringTrimLeft, AppendWord, A_LoopField, InStr(A_LoopField,"z") ;Strip (Number,"z") from beginning
TempWordList .= AppendWord . "`r`n"
}
StringTrimRight, TempWordList, TempWordList, 2
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
FileAppend, %TempWordList%, %A_ScriptDir%\Temp_Wordlist.txt ;Only update the file if we have learned words
FileCopy, %A_ScriptDir%\Temp_Wordlist.txt, %A_ScriptDir%\Wordlist.txt, 1
FileDelete, %A_ScriptDir%\Temp_Wordlist.txt
}
ExitApp
|
|
|
| Back to top |
|
 |
rogal
Joined: 23 Dec 2007 Posts: 62 Location: Austin
|
Posted: Wed Jan 13, 2010 11:02 pm Post subject: more than 10 words |
|
|
Hi,
Thanks for the great script. I am trying version 1,2, and I found that if I have many items with the same first three characters, typingaid does not show them at all.
I don't know if this is a known problem. For example, I have about 35 items with "con," and when I type con, typingaid tooltip window does not show up.
Thanks,
Joon |
|
| Back to top |
|
 |
maniac
Joined: 28 Aug 2009 Posts: 267
|
Posted: Thu Jan 14, 2010 1:50 am Post subject: Re: more than 10 words |
|
|
| rogal wrote: | Hi,
Thanks for the great script. I am trying version 1,2, and I found that if I have many items with the same first three characters, typingaid does not show them at all.
I don't know if this is a known problem. For example, I have about 35 items with "con," and when I type con, typingaid tooltip window does not show up.
Thanks,
Joon |
Hmm, that shouldn't occur. It should be limited to displaying 10, but it shouldn't be not showing any. I think I have a similar situation in my wordlist and mine all show.
Could you try the script in the post above yours rather than typingaid? Typingaid has a few modifications that script does not have (although they should not affect it).
Please let me know the result, thanks. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|